diff --git a/arm/Makefile b/arm/Makefile index 210da51fc..cc8d4a0d2 100644 --- a/arm/Makefile +++ b/arm/Makefile @@ -404,13 +404,17 @@ UNOPT_OBJ = p256/unopt/bignum_montmul_p256_base.o \ fastmul/unopt/bignum_mul_8_16_base.o \ fastmul/unopt/bignum_sqr_8_16_base.o -OBJ = $(POINT_OBJ) $(BIGNUM_OBJ) +AES_XTS_OBJ = aes-xts/aes_xts_decrypt.o \ + aes-xts/aes_xts_encrypt.o + + +OBJ = $(POINT_OBJ) $(BIGNUM_OBJ) $(AES_XTS_OBJ) # Tutorial assembly files TUTORIAL_PROOFS = $(wildcard tutorial/*.ml) -TUTORIAL_OBJ = $(filter-out tutorial/safety.o, $(TUTORIAL_PROOFS:.ml=.o)) \ +TUTORIAL_OBJ = $(filter-out tutorial/aes_encrypt_decrypt.o tutorial/safety.o, $(TUTORIAL_PROOFS:.ml=.o)) \ curve25519/bignum_mod_n25519.o p256/bignum_mux_4.o \ tutorial/rel_loop2.o \ tutorial/rel_simp2.o tutorial/rel_veceq2.o tutorial/rel_equivtac2.o \ @@ -421,9 +425,9 @@ TUTORIAL_OBJ = $(filter-out tutorial/safety.o, $(TUTORIAL_PROOFS:.ml=.o)) \ # x18 should not be used for Apple platforms. Check this using grep. %.o : %.S - cat $< | $(PREPROCESS) | $(SPLIT) | grep -v -E '^\s+\.(quad|hword)\s+(0x|-)?[0-9a-f]+$$' | $(ASSEMBLE) -o $@ - + cat $< | $(PREPROCESS) | $(SPLIT) | grep -v -E '^\s+.quad\s+0x[0-9a-f]+$$' | $(ASSEMBLE) -march=armv8-a+crypto -o $@ - $(OBJDUMP) $@ | ( ( ! grep --ignore-case -E 'w18|[^0]x18' ) || ( rm $@ ; exit 1 ) ) - cat $< | $(PREPROCESS) | $(SPLIT) | $(ASSEMBLE) -o $@ - + cat $< | $(PREPROCESS) | $(SPLIT) | $(ASSEMBLE) -march=armv8-a+crypto -o $@ - libs2nbignum.a: $(OBJ) ; ar -rc libs2nbignum.a $(OBJ) @@ -525,6 +529,12 @@ sm2/sm2_montjscalarmul_alt.native: sm2/sm2_montjadd_alt.native sm2/sm2_montjdoub tutorial/safety.native: tutorial/safety.ml proofs/bignum_mux_4.ml \ curve25519/bignum_mod_n25519.o ; \ ../tools/build-proof.sh "$<" "$(HOLLIGHT)" "$@" + +# aes_encrypt_decrypt tutorial concatenates proofs for both aes_encrypt.S and aes_decrypt.S +tutorial/aes_encrypt_decrypt.native: tutorial/aes_encrypt_decrypt.ml \ + tutorial/aes_encrypt.o tutorial/aes_decrypt.o ; \ + ../tools/build-proof.sh "$<" "$(HOLLIGHT)" "$@" + # other tutorials have their .o files .SECONDEXPANSION: tutorial/%.native: tutorial/%.ml tutorial/%.o ; ../tools/build-proof.sh "$<" "$(HOLLIGHT)" "$@" diff --git a/arm/aes-xts/Makefile b/arm/aes-xts/Makefile new file mode 100644 index 000000000..1c804cde2 --- /dev/null +++ b/arm/aes-xts/Makefile @@ -0,0 +1,39 @@ +############################################################################# +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0 +############################################################################# + +# If actually on an ARM8 machine, just use the GNU assembler (as). Otherwise +# use a cross-assembling version so that the code can still be assembled +# and the proofs checked against the object files (though you won't be able +# to run code without additional emulation infrastructure). The aarch64 +# cross-assembling version can be installed manually by something like: +# +# sudo apt-get install binutils-aarch64-linux-gnu + +#UNAME_RESULT=$(shell uname -p) +OSTYPE_RESULT=$(shell uname -s) +ARCHTYPE_RESULT=$(shell uname -m) + +ifeq ($(ARCHTYPE_RESULT),aarch64) +GAS=as +else +ifeq ($(OSTYPE_RESULT),Darwin) +GAS=as -arch arm64 +OBJDUMP=otool -tvV +else +GAS=aarch64-linux-gnu-as +endif +endif + +# List of object files + +OBJ = aes_xts_decrypt.o \ + aes_xts_encrypt.o + + +%.o : %.S ; $(CC) -E -I../../include $< | $(GAS) -o $@ - + +default: $(OBJ); + +clean:; rm -f *.o *.correct diff --git a/arm/aes-xts/aes_xts_decrypt.S b/arm/aes-xts/aes_xts_decrypt.S new file mode 100644 index 000000000..4f15c5202 --- /dev/null +++ b/arm/aes-xts/aes_xts_decrypt.S @@ -0,0 +1,671 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0 + +// ---------------------------------------------------------------------------- +// AES_XTS_DECRYPT (256-bit) +// Inputs in[length], length, key1[244], key2[244], iv[16]; output out[length] +// +// extern void aes_xts_decrypt(const uint8_t *in, uint8_t *out, +// size_t length, +// const s2n_bignum_AES_KEY *key1, +// const s2n_bignum_AES_KEY *key2, +// const uint8_t iv[static 16]); +// +// Standard ARM ABI: X0 = in, X1 = out, X2 = length, X3 = key1, X4 = key2, X5 = iv +// ---------------------------------------------------------------------------- +#include "_internal_s2n_bignum.h" + + .arch armv8-a+crypto + S2N_BN_SYM_VISIBILITY_DIRECTIVE(aes_xts_decrypt) + S2N_BN_SYM_PRIVACY_DIRECTIVE(aes_xts_decrypt) + .text + .balign 4 + + +#define STACK_SIZE_GPRS 32 //2*16 +#define STACK_SIZE_VREGS 64 //4*16 +#define STACK_SIZE (STACK_SIZE_GPRS + STACK_SIZE_VREGS) + +#define STACK_BASE_GPRS 0 +#define STACK_BASE_VREGS STACK_SIZE_GPRS + +#define save_regs \ + stp x19, x20, [sp, #(STACK_BASE_GPRS + 16*0)] __LF \ + stp x21, x22, [sp, #(STACK_BASE_GPRS + 16*1)] + +#define restore_regs \ + ldp x19, x20, [sp, #(STACK_BASE_GPRS + 16*0)] __LF \ + ldp x21, x22, [sp, #(STACK_BASE_GPRS + 16*1)] + +#define save_vregs \ + stp d8, d9, [sp, #(STACK_BASE_VREGS + 16*0)] __LF \ + stp d10, d11, [sp, #(STACK_BASE_VREGS + 16*1)] __LF \ + stp d12, d13, [sp, #(STACK_BASE_VREGS + 16*2)] __LF \ + stp d14, d15, [sp, #(STACK_BASE_VREGS + 16*3)] + +#define restore_vregs \ + ldp d8, d9, [sp, #(STACK_BASE_VREGS + 16*0)] __LF \ + ldp d10, d11, [sp, #(STACK_BASE_VREGS + 16*1)] __LF \ + ldp d12, d13, [sp, #(STACK_BASE_VREGS + 16*2)] __LF \ + ldp d14, d15, [sp, #(STACK_BASE_VREGS + 16*3)] + +// A single AES round +// Prevent SLOTHY from unfolding because uArchs tend to fuse AESMC+AESE +#define aesr(data, key) \ + aese data, key __LF \ + aesmc data, data + +// A single AESD round +// Prevent SLOTHY from unfolding because uArchs tend to fuse AESIMC+AESD +#define aesdr(data, key) \ + aesd data, key __LF \ + aesimc data, data + +#define tweak(lo, hi) \ + extr x22, x10, x10, #32 __LF \ + extr x10, x10, x9, #63 __LF \ + and w11, w19, w22, asr#31 __LF \ + eor x9, x11, x9, lsl#1 __LF \ + fmov lo, x9 __LF \ + fmov hi, x10 + +#define udiv_by_80(src, dst) \ + mov dst, #-0x3333333333333334 __LF \ + movk dst, #0xcccd __LF \ + umulh dst, src, dst __LF \ + lsr dst, dst, #6 + +S2N_BN_SYMBOL(aes_xts_decrypt): + // AARCH64_VALID_CALL_TARGET + sub sp, sp, #STACK_SIZE + save_vregs + save_regs + + cmp x2,#16 + // Original input data size bigger than 16, jump to big size processing. + b.lt .Lxts_dec_abort + +.align 5 +.Lxts_dec_big_size: // decrypt input size >= 16 bytes + and x21, x2, #0xf // store the tail value of length%16 + and x2, x2, #-16 // len &= 0x1..110000, now divisible by 16 + + // Firstly, encrypt the iv with key2, as the first iv of XEX. + ldr w6, [x4,#240] + ld1 {v0.4s}, [x4], #16 + ld1 {v6.16b}, [x5] + sub w6, w6, #2 + ld1 {v1.4s}, [x4], #16 + +.Loop_dec_iv_enc: + aesr(v6.16b, v0.16b) + ld1 {v0.4s}, [x4], #16 + subs w6, w6, #2 + aesr(v6.16b, v1.16b) + ld1 {v1.4s}, [x4], #16 + b.gt .Loop_dec_iv_enc + + aesr(v6.16b, v0.16b) + ld1 {v0.4s}, [x4] + aese v6.16b, v1.16b + eor v6.16b, v6.16b, v0.16b + + // The iv for second block + // x9- iv(low), x10 - iv(high) + // the five ivs stored into, v6.16b,v8.16b,v9.16b,v10.16b,v11.16b + fmov x9, d6 + fmov x10, v6.d[1] + mov w19, #0x87 + tweak(d8, v8.d[1]) + + mov x7, x3 + ld1 {v16.4s,v17.4s},[x7], #32 // load key schedule + ld1 {v12.4s,v13.4s},[x7], #32 + ld1 {v14.4s,v15.4s},[x7], #32 + ld1 {v4.4s,v5.4s}, [x7], #32 + ld1 {v18.4s,v19.4s},[x7], #32 + ld1 {v20.4s,v21.4s},[x7], #32 + ld1 {v22.4s,v23.4s},[x7], #32 + ld1 {v7.4s}, [x7] + +// decryption +.Lxts_dec: + tst x21,#0xf + b.eq .Lxts_dec_begin + subs x2,x2,#16 + cmp x2, #16 + b.lt .Lxts_dec_done // There is one block and a tail, go directy to cipher-stealing + +.Lxts_dec_begin: + udiv_by_80(x2, x8) // Number of 5x-unrolled iterations + + cmp x2, #0x20 + b.lo .Lxts_dec_tail1x // when input = 1 with another block and a tail + + cmp x2,#0x30 // bias + b.lo .Lxts_dec_tail2x // when input size = 2 with another block and a tail + + // The iv for third block + tweak(d9,v9.d[1]) + + cmp x2,#0x40 + b.lo .Lxts_dec_tail3x // when input size = 3 with another block and a tail + + // The iv for fourth block + tweak(d10,v10.d[1]) + + cmp x2,#0x50 + b.lo .Lxts_dec_tail4x // when input size = 4 with another block and a tail + + // The iv for fifth block + tweak(d11,v11.d[1]) + +.align 4 +.Loop5x_xts_dec: + ldp q0, q1, [x0], #0x50 + ldp q24, q25, [x0, #-0x30] + ldr q26, [x0, #-0x10] + + eor v0.16b,v0.16b,v6.16b + eor v1.16b,v1.16b,v8.16b + eor v24.16b,v24.16b,v9.16b + eor v25.16b,v25.16b,v10.16b + eor v26.16b,v26.16b,v11.16b + + aesdr(v0.16b, v16.16b) + aesdr(v1.16b, v16.16b) + aesdr(v24.16b, v16.16b) + aesdr(v25.16b, v16.16b) + aesdr(v26.16b, v16.16b) + + aesdr(v0.16b, v17.16b) + aesdr(v1.16b, v17.16b) + aesdr(v24.16b, v17.16b) + aesdr(v25.16b, v17.16b) + aesdr(v26.16b, v17.16b) + + aesdr(v0.16b, v12.16b) + aesdr(v1.16b, v12.16b) + aesdr(v24.16b, v12.16b) + aesdr(v25.16b, v12.16b) + aesdr(v26.16b, v12.16b) + + aesdr(v0.16b, v13.16b) + aesdr(v1.16b, v13.16b) + aesdr(v24.16b, v13.16b) + aesdr(v25.16b, v13.16b) + aesdr(v26.16b, v13.16b) + + aesdr(v0.16b, v14.16b) + aesdr(v1.16b, v14.16b) + aesdr(v24.16b, v14.16b) + aesdr(v25.16b, v14.16b) + aesdr(v26.16b, v14.16b) + + aesdr(v0.16b, v15.16b) + aesdr(v1.16b, v15.16b) + aesdr(v24.16b, v15.16b) + aesdr(v25.16b, v15.16b) + aesdr(v26.16b, v15.16b) + + aesdr(v0.16b, v4.16b) + aesdr(v1.16b, v4.16b) + aesdr(v24.16b, v4.16b) + aesdr(v25.16b, v4.16b) + aesdr(v26.16b, v4.16b) + + aesdr(v0.16b, v5.16b) + aesdr(v1.16b, v5.16b) + aesdr(v24.16b, v5.16b) + aesdr(v25.16b, v5.16b) + aesdr(v26.16b, v5.16b) + + aesdr(v0.16b, v18.16b) + aesdr(v1.16b, v18.16b) + aesdr(v24.16b, v18.16b) + aesdr(v25.16b, v18.16b) + aesdr(v26.16b, v18.16b) + + aesdr(v0.16b, v19.16b) + aesdr(v1.16b, v19.16b) + aesdr(v24.16b, v19.16b) + aesdr(v25.16b, v19.16b) + aesdr(v26.16b, v19.16b) + + aesdr(v0.16b, v20.16b) + aesdr(v1.16b, v20.16b) + aesdr(v24.16b, v20.16b) + aesdr(v25.16b, v20.16b) + aesdr(v26.16b, v20.16b) + + aesdr(v0.16b, v21.16b) + aesdr(v1.16b, v21.16b) + aesdr(v24.16b, v21.16b) + aesdr(v25.16b, v21.16b) + aesdr(v26.16b, v21.16b) + + aesdr(v0.16b, v22.16b) + aesdr(v1.16b, v22.16b) + aesdr(v24.16b, v22.16b) + aesdr(v25.16b, v22.16b) + aesdr(v26.16b, v22.16b) + + aesd v0.16b,v23.16b + aesd v1.16b,v23.16b + aesd v24.16b,v23.16b + aesd v25.16b,v23.16b + aesd v26.16b,v23.16b + + eor v0.16b,v0.16b,v7.16b + eor v0.16b,v0.16b,v6.16b + // The iv for first block of one iteration + tweak(d6,v6.d[1]) + eor v1.16b,v1.16b,v7.16b + eor v1.16b,v1.16b,v8.16b + + // The iv for second block + tweak(d8,v8.d[1]) + eor v24.16b,v24.16b,v7.16b + eor v24.16b,v24.16b,v9.16b + + // The iv for third block + tweak(d9,v9.d[1]) + eor v25.16b,v25.16b,v7.16b + eor v25.16b,v25.16b,v10.16b + + // The iv for fourth block + tweak(d10,v10.d[1]) + eor v26.16b,v26.16b,v7.16b + eor v26.16b,v26.16b,v11.16b + + // The iv for fifth block + tweak(d11,v11.d[1]) + + stp q0, q1, [x1], #0x50 + stp q24, q25, [x1, #-0x30] + str q26, [x1, #-0x10] + + subs x2,x2,#0x50 + subs x8,x8,#1 + cbnz x8, .Loop5x_xts_dec + +.Loop5x_dec_after: + cmp x2,#0x40 + b.eq .Lxts_dec_tail4x // 4 blocks left + 1block and a tail + + cmp x2,#0x30 + b.eq .Lxts_dec_tail3x // 3 blocks left + 1block and a tail + + cmp x2,#0x20 + b.eq .Lxts_dec_tail2x // 2 block left + 1block and a tail + + cmp x2,#0x10 + b.eq .Lxts_dec_tail1x // 1 blocks left + 1block and a tail + + b .Lxts_dec_done // no blocks left + 1block and a tail + +.align 4 +.Lxts_dec_tail4x: + ld1 {v0.16b,v1.16b}, [x0],#32 // the first and second blocks + ld1 {v24.16b,v25.16b}, [x0],#32 // the third and fourth blocks + + eor v0.16b,v0.16b,v6.16b + eor v1.16b,v1.16b,v8.16b + eor v24.16b,v24.16b,v9.16b + eor v25.16b,v25.16b,v10.16b + + aesdr(v0.16b, v16.16b) + aesdr(v1.16b, v16.16b) + aesdr(v24.16b, v16.16b) + aesdr(v25.16b, v16.16b) + + aesdr(v0.16b, v17.16b) + aesdr(v1.16b, v17.16b) + aesdr(v24.16b, v17.16b) + aesdr(v25.16b, v17.16b) + + aesdr(v0.16b, v12.16b) + aesdr(v1.16b, v12.16b) + aesdr(v24.16b, v12.16b) + aesdr(v25.16b, v12.16b) + + aesdr(v0.16b, v13.16b) + aesdr(v1.16b, v13.16b) + aesdr(v24.16b, v13.16b) + aesdr(v25.16b, v13.16b) + + aesdr(v0.16b, v14.16b) + aesdr(v1.16b, v14.16b) + aesdr(v24.16b, v14.16b) + aesdr(v25.16b, v14.16b) + + aesdr(v0.16b, v15.16b) + aesdr(v1.16b, v15.16b) + aesdr(v24.16b, v15.16b) + aesdr(v25.16b, v15.16b) + + aesdr(v0.16b, v4.16b) + aesdr(v1.16b, v4.16b) + aesdr(v24.16b, v4.16b) + aesdr(v25.16b, v4.16b) + + aesdr(v0.16b, v5.16b) + aesdr(v1.16b, v5.16b) + aesdr(v24.16b, v5.16b) + aesdr(v25.16b, v5.16b) + + aesdr(v0.16b, v18.16b) + aesdr(v1.16b, v18.16b) + aesdr(v24.16b, v18.16b) + aesdr(v25.16b, v18.16b) + + aesdr(v0.16b, v19.16b) + aesdr(v1.16b, v19.16b) + aesdr(v24.16b, v19.16b) + aesdr(v25.16b, v19.16b) + + aesdr(v0.16b, v20.16b) + aesdr(v1.16b, v20.16b) + aesdr(v24.16b, v20.16b) + aesdr(v25.16b, v20.16b) + + aesdr(v0.16b, v21.16b) + aesdr(v1.16b, v21.16b) + aesdr(v24.16b, v21.16b) + aesdr(v25.16b, v21.16b) + + aesdr(v0.16b, v22.16b) + aesdr(v1.16b, v22.16b) + aesdr(v24.16b, v22.16b) + aesdr(v25.16b, v22.16b) + + aesd v0.16b,v23.16b + aesd v1.16b,v23.16b + aesd v24.16b,v23.16b + aesd v25.16b,v23.16b + + eor v0.16b,v0.16b,v7.16b + eor v0.16b,v0.16b,v6.16b + + eor v1.16b,v1.16b,v7.16b + eor v1.16b,v1.16b,v8.16b + + eor v24.16b,v24.16b,v7.16b + eor v24.16b,v24.16b,v9.16b + + eor v25.16b,v25.16b,v7.16b + eor v25.16b,v25.16b,v10.16b + // The iv for tail + fmov x9,d10 + fmov x10,v10.d[1] + tweak(d6,v6.d[1]) + + st1 {v0.16b,v1.16b},[x1],#32 + st1 {v24.16b,v25.16b},[x1],#32 + + b .Lxts_dec_done + +.align 4 +.Lxts_dec_tail3x: + ld1 {v0.16b,v1.16b}, [x0],#32 + ld1 {v24.16b}, [x0],#16 + + eor v0.16b,v0.16b,v6.16b + eor v1.16b,v1.16b,v8.16b + eor v24.16b,v24.16b,v9.16b + + aesdr(v0.16b, v16.16b) + aesdr(v1.16b, v16.16b) + aesdr(v24.16b, v16.16b) + + aesdr(v0.16b, v17.16b) + aesdr(v1.16b, v17.16b) + aesdr(v24.16b, v17.16b) + + aesdr(v0.16b, v12.16b) + aesdr(v1.16b, v12.16b) + aesdr(v24.16b, v12.16b) + + aesdr(v0.16b, v13.16b) + aesdr(v1.16b, v13.16b) + aesdr(v24.16b, v13.16b) + + aesdr(v0.16b, v14.16b) + aesdr(v1.16b, v14.16b) + aesdr(v24.16b, v14.16b) + + aesdr(v0.16b, v15.16b) + aesdr(v1.16b, v15.16b) + aesdr(v24.16b, v15.16b) + + aesdr(v0.16b, v4.16b) + aesdr(v1.16b, v4.16b) + aesdr(v24.16b, v4.16b) + + aesdr(v0.16b, v5.16b) + aesdr(v1.16b, v5.16b) + aesdr(v24.16b, v5.16b) + + aesdr(v0.16b, v18.16b) + aesdr(v1.16b, v18.16b) + aesdr(v24.16b, v18.16b) + + aesdr(v0.16b, v19.16b) + aesdr(v1.16b, v19.16b) + aesdr(v24.16b, v19.16b) + + aesdr(v0.16b, v20.16b) + aesdr(v1.16b, v20.16b) + aesdr(v24.16b, v20.16b) + + aesdr(v0.16b, v21.16b) + aesdr(v1.16b, v21.16b) + aesdr(v24.16b, v21.16b) + + aesdr(v0.16b, v22.16b) + aesdr(v1.16b, v22.16b) + aesdr(v24.16b, v22.16b) + + aesd v0.16b,v23.16b + aesd v1.16b,v23.16b + aesd v24.16b,v23.16b + + eor v0.16b,v0.16b,v7.16b + eor v0.16b,v0.16b,v6.16b + eor v1.16b,v1.16b,v7.16b + eor v1.16b,v1.16b,v8.16b + eor v24.16b,v24.16b,v7.16b + eor v24.16b,v24.16b,v9.16b + + // The iv for tail + fmov x9,d9 + fmov x10,v9.d[1] + tweak(d6,v6.d[1]) + + st1 {v0.16b,v1.16b},[x1],#32 + st1 {v24.16b},[x1],#16 + b .Lxts_dec_done // done processing three blocks + +.Lxts_dec_tail2x: + ld1 {v0.16b,v1.16b},[x0],#32 // the first block + + eor v0.16b,v0.16b,v6.16b + eor v1.16b,v1.16b,v8.16b + + aesdr(v0.16b, v16.16b) + aesdr(v1.16b, v16.16b) + + aesdr(v0.16b, v17.16b) + aesdr(v1.16b, v17.16b) + + aesdr(v0.16b, v12.16b) + aesdr(v1.16b, v12.16b) + + + aesdr(v0.16b, v13.16b) + aesdr(v1.16b, v13.16b) + + aesdr(v0.16b, v14.16b) + aesdr(v1.16b, v14.16b) + + aesdr(v0.16b, v15.16b) + aesdr(v1.16b, v15.16b) + + aesdr(v0.16b, v4.16b) + aesdr(v1.16b, v4.16b) + + aesdr(v0.16b, v5.16b) + aesdr(v1.16b, v5.16b) + + aesdr(v0.16b, v18.16b) + aesdr(v1.16b, v18.16b) + + aesdr(v0.16b, v19.16b) + aesdr(v1.16b, v19.16b) + + aesdr(v0.16b, v20.16b) + aesdr(v1.16b, v20.16b) + + aesdr(v0.16b, v21.16b) + aesdr(v1.16b, v21.16b) + + aesdr(v0.16b, v22.16b) + aesdr(v1.16b, v22.16b) + aesd v0.16b,v23.16b + aesd v1.16b,v23.16b + + eor v0.16b,v0.16b,v7.16b + eor v0.16b,v0.16b,v6.16b + eor v1.16b,v1.16b,v7.16b + eor v1.16b,v1.16b,v8.16b + + st1 {v0.16b,v1.16b},[x1],#32 + + // The iv for tail + fmov x9,d8 + fmov x10,v8.d[1] + tweak(d6,v6.d[1]) + b .Lxts_dec_done + +.Lxts_dec_tail1x: + ld1 {v0.16b}, [x0],#16 // the first block + + eor v0.16b,v0.16b,v6.16b + + aesdr(v0.16b, v16.16b) + + aesdr(v0.16b, v17.16b) + + aesdr(v0.16b, v12.16b) + + aesdr(v0.16b, v13.16b) + + aesdr(v0.16b, v14.16b) + + aesdr(v0.16b, v15.16b) + + aesdr(v0.16b, v4.16b) + + aesdr(v0.16b, v5.16b) + + aesdr(v0.16b, v18.16b) + + aesdr(v0.16b, v19.16b) + + aesdr(v0.16b, v20.16b) + aesdr(v0.16b, v21.16b) + aesdr(v0.16b, v22.16b) + aesd v0.16b,v23.16b + + eor v0.16b,v0.16b,v7.16b + eor v0.16b,v0.16b,v6.16b + st1 {v0.16b},[x1],#16 + // tweak for tail + fmov x9,d6 + fmov x10,v6.d[1] + tweak(d6,v6.d[1]) + b .Lxts_dec_done + +.Lxts_dec_done: + tst x21,#0xf + b.eq .Lxts_dec_abort + // Processing the last 1 block and a tail with cipher stealing. + // At this point, we know there is 1 block+tail + // We need two tweaks, one is already calculated and stored in v6 + // We use it to calculate v8 + mov x7,x3 + + fmov x9,d6 + fmov x10,v6.d[1] + tweak(d8,v8.d[1]) + + ld1 {v0.4s},[x0],#16 + +// Decrypt the second to last block +.Lxts_dec_1st_done: + eor v26.16b,v0.16b,v8.16b + + aesdr(v26.16b, v16.16b) + aesdr(v26.16b, v17.16b) + aesdr(v26.16b, v12.16b) + aesdr(v26.16b, v13.16b) + aesdr(v26.16b, v14.16b) + aesdr(v26.16b, v15.16b) + aesdr(v26.16b, v4.16b) + aesdr(v26.16b, v5.16b) + aesdr(v26.16b, v18.16b) + aesdr(v26.16b, v19.16b) + aesdr(v26.16b, v20.16b) + aesdr(v26.16b, v21.16b) + aesdr(v26.16b, v22.16b) + aesd v26.16b,v23.16b + eor v26.16b,v26.16b,v7.16b + + eor v26.16b,v26.16b,v8.16b + st1 {v26.16b},[x1] + + mov x20,x0 + add x13,x1,#16 + + // Composite the tailcnt "16 byte not aligned block" into the last second plain blocks + // to get the last encrypted block. +.composite_dec_loop: + subs x21,x21,#1 + ldrb w15,[x1,x21] + ldrb w14,[x20,x21] + strb w15,[x13,x21] + strb w14,[x1,x21] + b.gt .composite_dec_loop +.Lxts_dec_load_done: + ld1 {v26.16b},[x1] + eor v26.16b,v26.16b,v6.16b + + // Decrypt the composite block to get the last second plain text block + aesdr(v26.16b, v16.16b) + aesdr(v26.16b, v17.16b) + aesdr(v26.16b, v12.16b) + aesdr(v26.16b, v13.16b) + aesdr(v26.16b, v14.16b) + aesdr(v26.16b, v15.16b) + aesdr(v26.16b, v4.16b) + aesdr(v26.16b, v5.16b) + aesdr(v26.16b, v18.16b) + aesdr(v26.16b, v19.16b) + aesdr(v26.16b, v20.16b) + aesdr(v26.16b, v21.16b) + aesdr(v26.16b, v22.16b) + aesd v26.16b,v23.16b + eor v26.16b,v26.16b,v7.16b + + eor v26.16b,v26.16b,v6.16b + st1 {v26.16b},[x1] + +.Lxts_dec_abort: + restore_vregs + restore_regs + add sp, sp, #STACK_SIZE + ret + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack, "", %progbits +#endif diff --git a/arm/aes-xts/aes_xts_encrypt.S b/arm/aes-xts/aes_xts_encrypt.S new file mode 100644 index 000000000..e46ee52f3 --- /dev/null +++ b/arm/aes-xts/aes_xts_encrypt.S @@ -0,0 +1,619 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0 + +// ---------------------------------------------------------------------------- +// AES_XTS_ENCRYPT (256-bit) +// Inputs in[length], length, key1[244], key2[244], iv[16]; output out[length] +// +// extern void aes_xts_encrypt(const uint8_t *in, uint8_t *out, +// size_t length, +// const s2n_bignum_AES_KEY *key1, +// const s2n_bignum_AES_KEY *key2, +// const uint8_t iv[static 16]); +// +// Standard ARM ABI: X0 = in, X1 = out, X2 = length, X3 = key1, X4 = key2, X5 = iv +// ---------------------------------------------------------------------------- +// Auto-added during import for AWS-LC symbol prefixing support +#include "_internal_s2n_bignum.h" + + .arch armv8-a+crypto + S2N_BN_SYM_VISIBILITY_DIRECTIVE(aes_xts_encrypt) + S2N_BN_SYM_PRIVACY_DIRECTIVE(aes_xts_encrypt) + .text + .balign 4 + +#define STACK_SIZE_GPRS 32 //2*16 +#define STACK_SIZE_VREGS 64 //4*16 +#define STACK_SIZE (STACK_SIZE_GPRS + STACK_SIZE_VREGS) + +#define STACK_BASE_GPRS 0 +#define STACK_BASE_VREGS STACK_SIZE_GPRS + +#define save_regs \ + stp x19, x20, [sp, #(STACK_BASE_GPRS + 16*0)] __LF \ + stp x21, x22, [sp, #(STACK_BASE_GPRS + 16*1)] + +#define restore_regs \ + ldp x19, x20, [sp, #(STACK_BASE_GPRS + 16*0)] __LF \ + ldp x21, x22, [sp, #(STACK_BASE_GPRS + 16*1)] + +#define save_vregs \ + stp d8, d9, [sp, #(STACK_BASE_VREGS + 16*0)] __LF \ + stp d10, d11, [sp, #(STACK_BASE_VREGS + 16*1)] __LF \ + stp d12, d13, [sp, #(STACK_BASE_VREGS + 16*2)] __LF \ + stp d14, d15, [sp, #(STACK_BASE_VREGS + 16*3)] + +#define restore_vregs \ + ldp d8, d9, [sp, #(STACK_BASE_VREGS + 16*0)] __LF \ + ldp d10, d11, [sp, #(STACK_BASE_VREGS + 16*1)] __LF \ + ldp d12, d13, [sp, #(STACK_BASE_VREGS + 16*2)] __LF \ + ldp d14, d15, [sp, #(STACK_BASE_VREGS + 16*3)] + +// A single AES round +// Prevent SLOTHY from unfolding because uArchs tend to fuse AESMC+AESE +#define aesr(data, key) \ + aese data, key __LF \ + aesmc data, data + +#define tweak(lo, hi) \ + extr x22, x10, x10, #32 __LF \ + extr x10, x10, x9, #63 __LF \ + and w11, w19, w22, asr#31 __LF \ + eor x9, x11, x9, lsl#1 __LF \ + fmov lo, x9 __LF \ + fmov hi, x10 + +#define udiv_by_80(src, dst) \ + mov dst, #-0x3333333333333334 __LF \ + movk dst, #0xcccd __LF \ + umulh dst, src, dst __LF \ + lsr dst, dst, #6 + +S2N_BN_SYMBOL(aes_xts_encrypt): + # AARCH64_VALID_CALL_TARGET + + sub sp, sp, #STACK_SIZE + save_vregs + save_regs + + + cmp x2, #16 // AES-XTS needs at least one block + b.lt .Lxts_enc_abort +.align 4 +.Lxts_enc_big_size: // Encrypt input size >= 16 bytes + and x21, x2, #0xf // store the tail value of length%16 + and x2, x2, #-16 // len &= 0x1..110000, now divisible by 16 + + // Firstly, encrypt the iv with key2, as the first iv of XEX. + ldr w6, [x4,#240] + ld1 {v0.4s}, [x4], #16 + ld1 {v6.16b}, [x5] + sub w6, w6, #2 + ld1 {v1.4s}, [x4], #16 + +.Loop_iv_enc: + aesr(v6.16b, v0.16b) + ld1 {v0.4s}, [x4], #16 + subs w6, w6, #2 + aesr(v6.16b, v1.16b) + ld1 {v1.4s}, [x4], #16 + b.gt .Loop_iv_enc + + aesr(v6.16b, v0.16b) + ld1 {v0.4s}, [x4] + aese v6.16b, v1.16b + eor v6.16b, v6.16b, v0.16b + + mov x7, x3 + ld1 {v16.4s,v17.4s},[x7], #32 // load key schedule + ld1 {v12.4s,v13.4s},[x7], #32 + ld1 {v14.4s,v15.4s},[x7], #32 + ld1 {v4.4s,v5.4s}, [x7], #32 + ld1 {v18.4s,v19.4s},[x7], #32 + ld1 {v20.4s,v21.4s},[x7], #32 + ld1 {v22.4s,v23.4s},[x7], #32 + ld1 {v7.4s}, [x7] + +// Encryption +.Lxts_enc: + mov w19, #0x87 + cmp x2, #0x20 + b.lo .Lxts_enc_tail1x // when input = 1 with tail + + // The iv for second block + // x9- iv(low), x10 - iv(high) + // the five ivs stored into, v6.16b,v8.16b,v9.16b,v10.16b,v11.16b + fmov x9, d6 + fmov x10, v6.d[1] + tweak(d8, v8.d[1]) + + cmp x2, #0x30 + b.lo .Lxts_enc_tail2x // when input size = 2 + + // The iv for third block + tweak(d9,v9.d[1]) + + cmp x2,#0x40 + b.lo .Lxts_enc_tail3x + + // The iv for fourth block + tweak(d10,v10.d[1]) + + cmp x2,#0x50 + b.lo .Lxts_enc_tail4x + + // The iv for fifth block + tweak(d11,v11.d[1]) + + udiv_by_80(x2, x8) // Number of 5x-unrolled iterations + +.align 4 +.Loop5x_xts_enc: + ldp q0, q1, [x0], #0x50 + ldp q24, q25, [x0, #-0x30] + ldr q26, [x0, #-0x10] + + eor v0.16b,v0.16b,v6.16b // before encryption, xor with iv + eor v1.16b,v1.16b,v8.16b + eor v24.16b,v24.16b,v9.16b + eor v25.16b,v25.16b,v10.16b + eor v26.16b,v26.16b,v11.16b + + aesr(v0.16b, v16.16b) + aesr(v1.16b, v16.16b) + aesr(v24.16b, v16.16b) + aesr(v25.16b, v16.16b) + aesr(v26.16b, v16.16b) + + aesr(v0.16b, v17.16b) + aesr(v1.16b, v17.16b) + aesr(v24.16b, v17.16b) + aesr(v25.16b, v17.16b) + aesr(v26.16b, v17.16b) + + aesr(v0.16b, v12.16b) + aesr(v1.16b, v12.16b) + aesr(v24.16b, v12.16b) + aesr(v25.16b, v12.16b) + aesr(v26.16b, v12.16b) + + aesr(v0.16b, v13.16b) + aesr(v1.16b, v13.16b) + aesr(v24.16b, v13.16b) + aesr(v25.16b, v13.16b) + aesr(v26.16b, v13.16b) + + aesr(v0.16b, v14.16b) + aesr(v1.16b, v14.16b) + aesr(v24.16b, v14.16b) + aesr(v25.16b, v14.16b) + aesr(v26.16b, v14.16b) + + aesr(v0.16b, v15.16b) + aesr(v1.16b, v15.16b) + aesr(v24.16b, v15.16b) + aesr(v25.16b, v15.16b) + aesr(v26.16b, v15.16b) + + aesr(v0.16b, v4.16b) + aesr(v1.16b, v4.16b) + aesr(v24.16b, v4.16b) + aesr(v25.16b, v4.16b) + aesr(v26.16b, v4.16b) + + aesr(v0.16b, v5.16b) + aesr(v1.16b, v5.16b) + aesr(v24.16b, v5.16b) + aesr(v25.16b, v5.16b) + aesr(v26.16b, v5.16b) + + aesr(v0.16b, v18.16b) + aesr(v1.16b, v18.16b) + aesr(v24.16b, v18.16b) + aesr(v25.16b, v18.16b) + aesr(v26.16b, v18.16b) + + aesr(v0.16b, v19.16b) + aesr(v1.16b, v19.16b) + aesr(v24.16b, v19.16b) + aesr(v25.16b, v19.16b) + aesr(v26.16b, v19.16b) + + aesr(v0.16b, v20.16b) + aesr(v1.16b, v20.16b) + aesr(v24.16b, v20.16b) + aesr(v25.16b, v20.16b) + aesr(v26.16b, v20.16b) + + aesr(v0.16b, v21.16b) + aesr(v1.16b, v21.16b) + aesr(v24.16b, v21.16b) + aesr(v25.16b, v21.16b) + aesr(v26.16b, v21.16b) + + aesr(v0.16b, v22.16b) + aesr(v1.16b, v22.16b) + aesr(v24.16b, v22.16b) + aesr(v25.16b, v22.16b) + aesr(v26.16b, v22.16b) + + aese v0.16b,v23.16b + aese v1.16b,v23.16b + aese v24.16b,v23.16b + aese v25.16b,v23.16b + aese v26.16b,v23.16b + + eor v0.16b,v0.16b,v7.16b + eor v0.16b,v0.16b,v6.16b + // The iv for first block of one iteration + tweak(d6, v6.d[1]) + eor v1.16b,v1.16b,v7.16b + eor v1.16b,v1.16b,v8.16b + + // The iv for second block + tweak(d8, v8.d[1]) + eor v24.16b,v24.16b,v7.16b + eor v24.16b,v24.16b,v9.16b + + // The iv for third block + tweak(d9, v9.d[1]) + eor v25.16b,v25.16b,v7.16b + eor v25.16b,v25.16b,v10.16b + + // The iv for fourth block + tweak(d10, v10.d[1]) + eor v26.16b,v26.16b,v7.16b + eor v26.16b,v26.16b,v11.16b + + // The iv for fifth block + tweak(d11, v11.d[1]) + + stp q0, q1, [x1], #0x50 + stp q24, q25, [x1, #-0x30] + str q26, [x1, #-0x10] + + sub x2, x2, #0x50 + subs x8,x8,#1 + cbnz x8, .Loop5x_xts_enc + +.Loop5x_enc_after: + cmp x2,#0x40 + b.eq .Lxts_enc_tail4x // 4 blocks left + + cmp x2,#0x30 + b.eq .Lxts_enc_tail3x + + cmp x2,#0x20 + b.eq .Lxts_enc_tail2x + + cmp x2,#0x10 + b.eq .Lxts_enc_tail1x + + b .Lxts_enc_done // no blocks left + +.align 4 +.Lxts_enc_tail4x: + ld1 {v0.16b}, [x0],#16 // the first block + ld1 {v1.16b}, [x0],#16 // the second block + ld1 {v24.16b},[x0],#16 // the third block + ld1 {v25.16b},[x0],#16 // the fourth block + + eor v0.16b,v0.16b,v6.16b + eor v1.16b,v1.16b,v8.16b + eor v24.16b,v24.16b,v9.16b + eor v25.16b,v25.16b,v10.16b + + aesr(v0.16b, v16.16b) + aesr(v1.16b, v16.16b) + aesr(v24.16b, v16.16b) + aesr(v25.16b, v16.16b) + + aesr(v0.16b, v17.16b) + aesr(v1.16b, v17.16b) + aesr(v24.16b, v17.16b) + aesr(v25.16b, v17.16b) + + aesr(v0.16b, v12.16b) + aesr(v1.16b, v12.16b) + aesr(v24.16b, v12.16b) + aesr(v25.16b, v12.16b) + + aesr(v0.16b, v13.16b) + aesr(v1.16b, v13.16b) + aesr(v24.16b, v13.16b) + aesr(v25.16b, v13.16b) + + aesr(v0.16b, v14.16b) + aesr(v1.16b, v14.16b) + aesr(v24.16b, v14.16b) + aesr(v25.16b, v14.16b) + + aesr(v0.16b, v15.16b) + aesr(v1.16b, v15.16b) + aesr(v24.16b, v15.16b) + aesr(v25.16b, v15.16b) + + aesr(v0.16b, v4.16b) + aesr(v1.16b, v4.16b) + aesr(v24.16b, v4.16b) + aesr(v25.16b, v4.16b) + + aesr(v0.16b, v5.16b) + aesr(v1.16b, v5.16b) + aesr(v24.16b, v5.16b) + aesr(v25.16b, v5.16b) + + aesr(v0.16b, v18.16b) + aesr(v1.16b, v18.16b) + aesr(v24.16b, v18.16b) + aesr(v25.16b, v18.16b) + + aesr(v0.16b, v19.16b) + aesr(v1.16b, v19.16b) + aesr(v24.16b, v19.16b) + aesr(v25.16b, v19.16b) + + aesr(v0.16b, v20.16b) + aesr(v1.16b, v20.16b) + aesr(v24.16b, v20.16b) + aesr(v25.16b, v20.16b) + + aesr(v0.16b, v21.16b) + aesr(v1.16b, v21.16b) + aesr(v24.16b, v21.16b) + aesr(v25.16b, v21.16b) + + aesr(v0.16b, v22.16b) + aesr(v1.16b, v22.16b) + aesr(v24.16b, v22.16b) + aesr(v25.16b, v22.16b) + + aese v0.16b,v23.16b + aese v1.16b,v23.16b + aese v24.16b,v23.16b + aese v25.16b,v23.16b + + eor v0.16b,v0.16b,v7.16b + eor v0.16b,v0.16b,v6.16b + + eor v1.16b,v1.16b,v7.16b + eor v1.16b,v1.16b,v8.16b + + eor v24.16b,v24.16b,v7.16b + eor v24.16b,v24.16b,v9.16b + + eor v25.16b,v25.16b,v7.16b + eor v25.16b,v25.16b,v10.16b + + st1 {v0.16b,v1.16b},[x1],#32 + st1 {v24.16b,v25.16b},[x1],#32 + + // The iv for tail + fmov x9,d10 + fmov x10,v10.d[1] + tweak(d6, v6.d[1]) + + b .Lxts_enc_done + +.align 4 +.Lxts_enc_tail3x: + ld1 {v0.16b,v1.16b}, [x0],#32 + ld1 {v24.16b}, [x0],#16 + + eor v0.16b,v0.16b,v6.16b + eor v1.16b,v1.16b,v8.16b + eor v24.16b,v24.16b,v9.16b + + aesr(v0.16b, v16.16b) + aesr(v1.16b, v16.16b) + aesr(v24.16b, v16.16b) + + aesr(v0.16b, v17.16b) + aesr(v1.16b, v17.16b) + aesr(v24.16b, v17.16b) + + aesr(v0.16b, v12.16b) + aesr(v1.16b, v12.16b) + aesr(v24.16b, v12.16b) + + aesr(v0.16b, v13.16b) + aesr(v1.16b, v13.16b) + aesr(v24.16b, v13.16b) + + aesr(v0.16b, v14.16b) + aesr(v1.16b, v14.16b) + aesr(v24.16b, v14.16b) + + aesr(v0.16b, v15.16b) + aesr(v1.16b, v15.16b) + aesr(v24.16b, v15.16b) + + aesr(v0.16b, v4.16b) + aesr(v1.16b, v4.16b) + aesr(v24.16b, v4.16b) + + aesr(v0.16b, v5.16b) + aesr(v1.16b, v5.16b) + aesr(v24.16b, v5.16b) + + aesr(v0.16b, v18.16b) + aesr(v1.16b, v18.16b) + aesr(v24.16b, v18.16b) + + aesr(v0.16b, v19.16b) + aesr(v1.16b, v19.16b) + aesr(v24.16b, v19.16b) + + aesr(v0.16b, v20.16b) + aesr(v1.16b, v20.16b) + aesr(v24.16b, v20.16b) + + aesr(v0.16b, v21.16b) + aesr(v1.16b, v21.16b) + aesr(v24.16b, v21.16b) + + aesr(v0.16b, v22.16b) + aesr(v1.16b, v22.16b) + aesr(v24.16b, v22.16b) + + aese v0.16b,v23.16b + aese v1.16b,v23.16b + aese v24.16b,v23.16b + + eor v0.16b,v0.16b,v7.16b + eor v0.16b,v0.16b,v6.16b + eor v1.16b,v1.16b,v7.16b + eor v1.16b,v1.16b,v8.16b + eor v24.16b,v24.16b,v7.16b + eor v24.16b,v24.16b,v9.16b + + st1 {v0.16b,v1.16b},[x1],#32 + st1 {v24.16b},[x1],#16 + + // The iv for tail + fmov x9,d9 + fmov x10,v9.d[1] + tweak(d6, v6.d[1]) + + b .Lxts_enc_done // done processing three blocks + +.Lxts_enc_tail2x: + ld1 {v0.16b,v1.16b},[x0],#32 // the first block + + eor v0.16b,v0.16b,v6.16b + eor v1.16b,v1.16b,v8.16b + + aesr(v0.16b, v16.16b) + aesr(v1.16b, v16.16b) + + aesr(v0.16b, v17.16b) + aesr(v1.16b, v17.16b) + + aesr(v0.16b, v12.16b) + aesr(v1.16b, v12.16b) + + aesr(v0.16b, v13.16b) + aesr(v1.16b, v13.16b) + + aesr(v0.16b, v14.16b) + aesr(v1.16b, v14.16b) + + aesr(v0.16b, v15.16b) + aesr(v1.16b, v15.16b) + + aesr(v0.16b, v4.16b) + aesr(v1.16b, v4.16b) + + aesr(v0.16b, v5.16b) + aesr(v1.16b, v5.16b) + + aesr(v0.16b, v18.16b) + aesr(v1.16b, v18.16b) + + aesr(v0.16b, v19.16b) + aesr(v1.16b, v19.16b) + + aesr(v0.16b, v20.16b) + aesr(v1.16b, v20.16b) + + aesr(v0.16b, v21.16b) + aesr(v1.16b, v21.16b) + + aesr(v0.16b, v22.16b) + aesr(v1.16b, v22.16b) + + aese v0.16b,v23.16b + aese v1.16b,v23.16b + + eor v0.16b,v0.16b,v7.16b + eor v0.16b,v0.16b,v6.16b + eor v1.16b,v1.16b,v7.16b + eor v1.16b,v1.16b,v8.16b + + st1 {v0.16b,v1.16b},[x1],#32 + + // The iv for tail + fmov x9,d8 + fmov x10,v8.d[1] + tweak(d6, v6.d[1]) + b .Lxts_enc_done + +.Lxts_enc_tail1x: + ld1 {v0.16b}, [x0],#16 // the first block + + eor v0.16b,v0.16b,v6.16b + + aesr(v0.16b, v16.16b) + aesr(v0.16b, v17.16b) + aesr(v0.16b, v12.16b) + aesr(v0.16b, v13.16b) + aesr(v0.16b, v14.16b) + aesr(v0.16b, v15.16b) + aesr(v0.16b, v4.16b) + aesr(v0.16b, v5.16b) + aesr(v0.16b, v18.16b) + aesr(v0.16b, v19.16b) + aesr(v0.16b, v20.16b) + aesr(v0.16b, v21.16b) + aesr(v0.16b, v22.16b) + aese v0.16b,v23.16b + + eor v0.16b,v0.16b,v7.16b + eor v0.16b,v0.16b,v6.16b + st1 {v0.16b},[x1],#16 + + // tweak for tail + fmov x9,d6 + fmov x10,v6.d[1] + tweak(d6, v6.d[1]) + b .Lxts_enc_done + +.align 5 +.Lxts_enc_done: + // Process the tail block with cipher stealing. + tst x21,#0xf + b.eq .Lxts_enc_abort + + mov x20,x0 + mov x13,x1 + sub x1,x1,#16 +.composite_enc_loop: + subs x21,x21,#1 + ldrb w15,[x1,x21] + ldrb w14,[x20,x21] + strb w15,[x13,x21] + strb w14,[x1,x21] + b.gt .composite_enc_loop +.Lxts_enc_load_done: + ld1 {v26.16b},[x1] + eor v26.16b,v26.16b,v6.16b + + // Encrypt the composite block to get the last second encrypted text block + aesr(v26.16b, v16.16b) + aesr(v26.16b, v17.16b) + aesr(v26.16b, v12.16b) + aesr(v26.16b, v13.16b) + aesr(v26.16b, v14.16b) + aesr(v26.16b, v15.16b) + aesr(v26.16b, v4.16b) + aesr(v26.16b, v5.16b) + aesr(v26.16b, v18.16b) + aesr(v26.16b, v19.16b) + aesr(v26.16b, v20.16b) + aesr(v26.16b, v21.16b) + aesr(v26.16b, v22.16b) + aese v26.16b,v23.16b + eor v26.16b,v26.16b,v7.16b + + eor v26.16b,v26.16b,v6.16b + st1 {v26.16b},[x1] + +.Lxts_enc_abort: + restore_regs + restore_vregs + add sp, sp, #STACK_SIZE + ret + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack, "", %progbits +#endif diff --git a/arm/proofs/aes_xts_decrypt.ml b/arm/proofs/aes_xts_decrypt.ml new file mode 100644 index 000000000..833eb50e9 --- /dev/null +++ b/arm/proofs/aes_xts_decrypt.ml @@ -0,0 +1,6656 @@ +(* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0 + *) +(* ========================================================================= *) +(* AES-256-XTS decryption. *) +(* ========================================================================= *) + +needs "arm/proofs/utils/aes_xts_common.ml";; +needs "arm/proofs/consttime.ml";; + +(* print_literal_from_elf "arm/aes-xts/aes_xts_decrypt.o";; *) +let aes_xts_decrypt_mc = define_assert_from_elf "aes_xts_decrypt_mc" "arm/aes-xts/aes_xts_decrypt.o" +[ + 0xd10183ff; (* arm_SUB SP SP (rvalue (word 0x60)) *) + 0x6d0227e8; (* arm_STP D8 D9 SP (Immediate_Offset (iword (&0x20))) *) + 0x6d032fea; (* arm_STP D10 D11 SP (Immediate_Offset (iword (&0x30))) *) + 0x6d0437ec; (* arm_STP D12 D13 SP (Immediate_Offset (iword (&0x40))) *) + 0x6d053fee; (* arm_STP D14 D15 SP (Immediate_Offset (iword (&0x50))) *) + 0xa90053f3; (* arm_STP X19 X20 SP (Immediate_Offset (iword (&0x0))) *) + 0xa9015bf5; (* arm_STP X21 X22 SP (Immediate_Offset (iword (&0x10))) *) + 0xf100405f; (* arm_CMP X2 (rvalue (word 0x10)) *) + 0x540059cb; (* arm_BLT (word 0xb38) *) + 0xd503201f; (* arm_NOP *) + 0xd503201f; (* arm_NOP *) + 0xd503201f; (* arm_NOP *) + 0xd503201f; (* arm_NOP *) + 0xd503201f; (* arm_NOP *) + 0xd503201f; (* arm_NOP *) + 0xd503201f; (* arm_NOP *) + 0x92400c55; (* arm_AND X21 X2 (rvalue (word 0xf)) *) + 0x927cec42; (* arm_AND X2 X2 (rvalue (word 0xfffffffffffffff0)) *) + 0xb940f086; (* arm_LDR W6 X4 (Immediate_Offset (word 0xf0)) *) + 0x4cdf7880; (* arm_LDR Q0 X4 (Postimmediate_Offset (word 0x10)) *) + 0x4c4070a6; (* arm_LDR Q6 X5 No_Offset *) + 0x510008c6; (* arm_SUB W6 W6 (rvalue (word 0x2)) *) + 0x4cdf7881; (* arm_LDR Q1 X4 (Postimmediate_Offset (word 0x10)) *) + 0x4e284806; (* arm_AESE Q6 Q0 *) + 0x4e2868c6; (* arm_AESMC Q6 Q6 *) + 0x4cdf7880; (* arm_LDR Q0 X4 (Postimmediate_Offset (word 0x10)) *) + 0x710008c6; (* arm_SUBS W6 W6 (rvalue (word 0x2)) *) + 0x4e284826; (* arm_AESE Q6 Q1 *) + 0x4e2868c6; (* arm_AESMC Q6 Q6 *) + 0x4cdf7881; (* arm_LDR Q1 X4 (Postimmediate_Offset (word 0x10)) *) + 0x54ffff2c; (* arm_BGT (word 0x1fffe4) *) + 0x4e284806; (* arm_AESE Q6 Q0 *) + 0x4e2868c6; (* arm_AESMC Q6 Q6 *) + 0x4c407880; (* arm_LDR Q0 X4 No_Offset *) + 0x4e284826; (* arm_AESE Q6 Q1 *) + 0x6e201cc6; (* arm_EOR_VEC Q6 Q6 Q0 0x80 *) + 0x9e6600c9; (* arm_FMOV_FtoI X9 Q6 0x0 0x40 *) + 0x9eae00ca; (* arm_FMOV_FtoI X10 Q6 0x1 0x40 *) + 0x528010f3; (* arm_MOV W19 (rvalue (word 0x87)) *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670128; (* arm_FMOV_ItoF Q8 X9 0x0 *) + 0x9eaf0148; (* arm_FMOV_ItoF Q8 X10 0x1 *) + 0xaa0303e7; (* arm_MOV X7 X3 *) + 0x4cdfa8f0; (* arm_LDP Q16 Q17 X7 (Postimmediate_Offset (word 0x20)) *) + 0x4cdfa8ec; (* arm_LDP Q12 Q13 X7 (Postimmediate_Offset (word 0x20)) *) + 0x4cdfa8ee; (* arm_LDP Q14 Q15 X7 (Postimmediate_Offset (word 0x20)) *) + 0x4cdfa8e4; (* arm_LDP Q4 Q5 X7 (Postimmediate_Offset (word 0x20)) *) + 0x4cdfa8f2; (* arm_LDP Q18 Q19 X7 (Postimmediate_Offset (word 0x20)) *) + 0x4cdfa8f4; (* arm_LDP Q20 Q21 X7 (Postimmediate_Offset (word 0x20)) *) + 0x4cdfa8f6; (* arm_LDP Q22 Q23 X7 (Postimmediate_Offset (word 0x20)) *) + 0x4c4078e7; (* arm_LDR Q7 X7 No_Offset *) + 0xf2400ebf; (* arm_TST X21 (rvalue (word 0xf)) *) + 0x54000080; (* arm_BEQ (word 0x10) *) + 0xf1004042; (* arm_SUBS X2 X2 (rvalue (word 0x10)) *) + 0xf100405f; (* arm_CMP X2 (rvalue (word 0x10)) *) + 0x5400492b; (* arm_BLT (word 0x924) *) + 0xb202e7e8; (* arm_MOV X8 (rvalue (word 0xcccccccccccccccc)) *) + 0xf29999a8; (* arm_MOVK X8 (word 0xcccd) 0x0 *) + 0x9bc87c48; (* arm_UMULH X8 X2 X8 *) + 0xd346fd08; (* arm_LSR X8 X8 0x6 *) + 0xf100805f; (* arm_CMP X2 (rvalue (word 0x20)) *) + 0x54004343; (* arm_BCC (word 0x868) *) + 0xf100c05f; (* arm_CMP X2 (rvalue (word 0x30)) *) + 0x54003a23; (* arm_BCC (word 0x744) *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670129; (* arm_FMOV_ItoF Q9 X9 0x0 *) + 0x9eaf0149; (* arm_FMOV_ItoF Q9 X10 0x1 *) + 0xf101005f; (* arm_CMP X2 (rvalue (word 0x40)) *) + 0x54002c43; (* arm_BCC (word 0x588) *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e67012a; (* arm_FMOV_ItoF Q10 X9 0x0 *) + 0x9eaf014a; (* arm_FMOV_ItoF Q10 X10 0x1 *) + 0xf101405f; (* arm_CMP X2 (rvalue (word 0x50)) *) + 0x54001a43; (* arm_BCC (word 0x348) *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e67012b; (* arm_FMOV_ItoF Q11 X9 0x0 *) + 0x9eaf014b; (* arm_FMOV_ItoF Q11 X10 0x1 *) + 0xd503201f; (* arm_NOP *) + 0xd503201f; (* arm_NOP *) + 0xd503201f; (* arm_NOP *) + 0xacc28400; (* arm_LDP Q0 Q1 X0 (Postimmediate_Offset (iword (&0x50))) *) + 0xad7ee418; (* arm_LDP Q24 Q25 X0 (Immediate_Offset (iword (-- &0x30))) *) + 0x3cdf001a; (* arm_LDR Q26 X0 (Immediate_Offset (word 0xfffffffffffffff0)) *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x6e291f18; (* arm_EOR_VEC Q24 Q24 Q9 0x80 *) + 0x6e2a1f39; (* arm_EOR_VEC Q25 Q25 Q10 0x80 *) + 0x6e2b1f5a; (* arm_EOR_VEC Q26 Q26 Q11 0x80 *) + 0x4e285a00; (* arm_AESD Q0 Q16 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a01; (* arm_AESD Q1 Q16 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a18; (* arm_AESD Q24 Q16 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285a19; (* arm_AESD Q25 Q16 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285a1a; (* arm_AESD Q26 Q16 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285a20; (* arm_AESD Q0 Q17 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a21; (* arm_AESD Q1 Q17 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a38; (* arm_AESD Q24 Q17 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285a39; (* arm_AESD Q25 Q17 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285a3a; (* arm_AESD Q26 Q17 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285980; (* arm_AESD Q0 Q12 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285981; (* arm_AESD Q1 Q12 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285998; (* arm_AESD Q24 Q12 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285999; (* arm_AESD Q25 Q12 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e28599a; (* arm_AESD Q26 Q12 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e2859a0; (* arm_AESD Q0 Q13 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859a1; (* arm_AESD Q1 Q13 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2859b8; (* arm_AESD Q24 Q13 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e2859b9; (* arm_AESD Q25 Q13 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e2859ba; (* arm_AESD Q26 Q13 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e2859c0; (* arm_AESD Q0 Q14 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859c1; (* arm_AESD Q1 Q14 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2859d8; (* arm_AESD Q24 Q14 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e2859d9; (* arm_AESD Q25 Q14 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e2859da; (* arm_AESD Q26 Q14 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e2859e0; (* arm_AESD Q0 Q15 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859e1; (* arm_AESD Q1 Q15 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2859f8; (* arm_AESD Q24 Q15 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e2859f9; (* arm_AESD Q25 Q15 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e2859fa; (* arm_AESD Q26 Q15 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285880; (* arm_AESD Q0 Q4 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285881; (* arm_AESD Q1 Q4 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285898; (* arm_AESD Q24 Q4 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285899; (* arm_AESD Q25 Q4 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e28589a; (* arm_AESD Q26 Q4 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e2858a0; (* arm_AESD Q0 Q5 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2858a1; (* arm_AESD Q1 Q5 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2858b8; (* arm_AESD Q24 Q5 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e2858b9; (* arm_AESD Q25 Q5 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e2858ba; (* arm_AESD Q26 Q5 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285a40; (* arm_AESD Q0 Q18 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a41; (* arm_AESD Q1 Q18 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a58; (* arm_AESD Q24 Q18 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285a59; (* arm_AESD Q25 Q18 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285a5a; (* arm_AESD Q26 Q18 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285a60; (* arm_AESD Q0 Q19 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a61; (* arm_AESD Q1 Q19 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a78; (* arm_AESD Q24 Q19 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285a79; (* arm_AESD Q25 Q19 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285a7a; (* arm_AESD Q26 Q19 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285a80; (* arm_AESD Q0 Q20 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a81; (* arm_AESD Q1 Q20 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a98; (* arm_AESD Q24 Q20 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285a99; (* arm_AESD Q25 Q20 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285a9a; (* arm_AESD Q26 Q20 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285aa0; (* arm_AESD Q0 Q21 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285aa1; (* arm_AESD Q1 Q21 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285ab8; (* arm_AESD Q24 Q21 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285ab9; (* arm_AESD Q25 Q21 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285aba; (* arm_AESD Q26 Q21 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285ac0; (* arm_AESD Q0 Q22 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285ac1; (* arm_AESD Q1 Q22 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285ad8; (* arm_AESD Q24 Q22 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285ad9; (* arm_AESD Q25 Q22 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285ada; (* arm_AESD Q26 Q22 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285ae0; (* arm_AESD Q0 Q23 *) + 0x4e285ae1; (* arm_AESD Q1 Q23 *) + 0x4e285af8; (* arm_AESD Q24 Q23 *) + 0x4e285af9; (* arm_AESD Q25 Q23 *) + 0x4e285afa; (* arm_AESD Q26 Q23 *) + 0x6e271c00; (* arm_EOR_VEC Q0 Q0 Q7 0x80 *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670126; (* arm_FMOV_ItoF Q6 X9 0x0 *) + 0x9eaf0146; (* arm_FMOV_ItoF Q6 X10 0x1 *) + 0x6e271c21; (* arm_EOR_VEC Q1 Q1 Q7 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670128; (* arm_FMOV_ItoF Q8 X9 0x0 *) + 0x9eaf0148; (* arm_FMOV_ItoF Q8 X10 0x1 *) + 0x6e271f18; (* arm_EOR_VEC Q24 Q24 Q7 0x80 *) + 0x6e291f18; (* arm_EOR_VEC Q24 Q24 Q9 0x80 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670129; (* arm_FMOV_ItoF Q9 X9 0x0 *) + 0x9eaf0149; (* arm_FMOV_ItoF Q9 X10 0x1 *) + 0x6e271f39; (* arm_EOR_VEC Q25 Q25 Q7 0x80 *) + 0x6e2a1f39; (* arm_EOR_VEC Q25 Q25 Q10 0x80 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e67012a; (* arm_FMOV_ItoF Q10 X9 0x0 *) + 0x9eaf014a; (* arm_FMOV_ItoF Q10 X10 0x1 *) + 0x6e271f5a; (* arm_EOR_VEC Q26 Q26 Q7 0x80 *) + 0x6e2b1f5a; (* arm_EOR_VEC Q26 Q26 Q11 0x80 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e67012b; (* arm_FMOV_ItoF Q11 X9 0x0 *) + 0x9eaf014b; (* arm_FMOV_ItoF Q11 X10 0x1 *) + 0xac828420; (* arm_STP Q0 Q1 X1 (Postimmediate_Offset (iword (&0x50))) *) + 0xad3ee438; (* arm_STP Q24 Q25 X1 (Immediate_Offset (iword (-- &0x30))) *) + 0x3c9f003a; (* arm_STR Q26 X1 (Immediate_Offset (word 0xfffffffffffffff0)) *) + 0xf1014042; (* arm_SUBS X2 X2 (rvalue (word 0x50)) *) + 0xf1000508; (* arm_SUBS X8 X8 (rvalue (word 0x1)) *) + 0xb5ffe888; (* arm_CBNZ X8 (word 0x1ffd10) *) + 0xf101005f; (* arm_CMP X2 (rvalue (word 0x40)) *) + 0x54000140; (* arm_BEQ (word 0x28) *) + 0xf100c05f; (* arm_CMP X2 (rvalue (word 0x30)) *) + 0x54001200; (* arm_BEQ (word 0x240) *) + 0xf100805f; (* arm_CMP X2 (rvalue (word 0x20)) *) + 0x54001ea0; (* arm_BEQ (word 0x3d4) *) + 0xf100405f; (* arm_CMP X2 (rvalue (word 0x10)) *) + 0x54002740; (* arm_BEQ (word 0x4e8) *) + 0x14000162; (* arm_B (word 0x588) *) + 0xd503201f; (* arm_NOP *) + 0xd503201f; (* arm_NOP *) + 0x4cdfa000; (* arm_LDP Q0 Q1 X0 (Postimmediate_Offset (word 0x20)) *) + 0x4cdfa018; (* arm_LDP Q24 Q25 X0 (Postimmediate_Offset (word 0x20)) *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x6e291f18; (* arm_EOR_VEC Q24 Q24 Q9 0x80 *) + 0x6e2a1f39; (* arm_EOR_VEC Q25 Q25 Q10 0x80 *) + 0x4e285a00; (* arm_AESD Q0 Q16 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a01; (* arm_AESD Q1 Q16 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a18; (* arm_AESD Q24 Q16 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285a19; (* arm_AESD Q25 Q16 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285a20; (* arm_AESD Q0 Q17 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a21; (* arm_AESD Q1 Q17 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a38; (* arm_AESD Q24 Q17 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285a39; (* arm_AESD Q25 Q17 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285980; (* arm_AESD Q0 Q12 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285981; (* arm_AESD Q1 Q12 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285998; (* arm_AESD Q24 Q12 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285999; (* arm_AESD Q25 Q12 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e2859a0; (* arm_AESD Q0 Q13 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859a1; (* arm_AESD Q1 Q13 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2859b8; (* arm_AESD Q24 Q13 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e2859b9; (* arm_AESD Q25 Q13 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e2859c0; (* arm_AESD Q0 Q14 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859c1; (* arm_AESD Q1 Q14 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2859d8; (* arm_AESD Q24 Q14 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e2859d9; (* arm_AESD Q25 Q14 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e2859e0; (* arm_AESD Q0 Q15 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859e1; (* arm_AESD Q1 Q15 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2859f8; (* arm_AESD Q24 Q15 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e2859f9; (* arm_AESD Q25 Q15 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285880; (* arm_AESD Q0 Q4 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285881; (* arm_AESD Q1 Q4 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285898; (* arm_AESD Q24 Q4 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285899; (* arm_AESD Q25 Q4 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e2858a0; (* arm_AESD Q0 Q5 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2858a1; (* arm_AESD Q1 Q5 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2858b8; (* arm_AESD Q24 Q5 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e2858b9; (* arm_AESD Q25 Q5 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285a40; (* arm_AESD Q0 Q18 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a41; (* arm_AESD Q1 Q18 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a58; (* arm_AESD Q24 Q18 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285a59; (* arm_AESD Q25 Q18 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285a60; (* arm_AESD Q0 Q19 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a61; (* arm_AESD Q1 Q19 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a78; (* arm_AESD Q24 Q19 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285a79; (* arm_AESD Q25 Q19 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285a80; (* arm_AESD Q0 Q20 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a81; (* arm_AESD Q1 Q20 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a98; (* arm_AESD Q24 Q20 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285a99; (* arm_AESD Q25 Q20 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285aa0; (* arm_AESD Q0 Q21 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285aa1; (* arm_AESD Q1 Q21 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285ab8; (* arm_AESD Q24 Q21 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285ab9; (* arm_AESD Q25 Q21 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285ac0; (* arm_AESD Q0 Q22 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285ac1; (* arm_AESD Q1 Q22 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285ad8; (* arm_AESD Q24 Q22 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285ad9; (* arm_AESD Q25 Q22 *) + 0x4e287b39; (* arm_AESIMC Q25 Q25 *) + 0x4e285ae0; (* arm_AESD Q0 Q23 *) + 0x4e285ae1; (* arm_AESD Q1 Q23 *) + 0x4e285af8; (* arm_AESD Q24 Q23 *) + 0x4e285af9; (* arm_AESD Q25 Q23 *) + 0x6e271c00; (* arm_EOR_VEC Q0 Q0 Q7 0x80 *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x6e271c21; (* arm_EOR_VEC Q1 Q1 Q7 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x6e271f18; (* arm_EOR_VEC Q24 Q24 Q7 0x80 *) + 0x6e291f18; (* arm_EOR_VEC Q24 Q24 Q9 0x80 *) + 0x6e271f39; (* arm_EOR_VEC Q25 Q25 Q7 0x80 *) + 0x6e2a1f39; (* arm_EOR_VEC Q25 Q25 Q10 0x80 *) + 0x9e660149; (* arm_FMOV_FtoI X9 Q10 0x0 0x40 *) + 0x9eae014a; (* arm_FMOV_FtoI X10 Q10 0x1 0x40 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670126; (* arm_FMOV_ItoF Q6 X9 0x0 *) + 0x9eaf0146; (* arm_FMOV_ItoF Q6 X10 0x1 *) + 0x4c9fa020; (* arm_STP Q0 Q1 X1 (Postimmediate_Offset (word 0x20)) *) + 0x4c9fa038; (* arm_STP Q24 Q25 X1 (Postimmediate_Offset (word 0x20)) *) + 0x140000db; (* arm_B (word 0x36c) *) + 0xd503201f; (* arm_NOP *) + 0xd503201f; (* arm_NOP *) + 0xd503201f; (* arm_NOP *) + 0x4cdfa000; (* arm_LDP Q0 Q1 X0 (Postimmediate_Offset (word 0x20)) *) + 0x4cdf7018; (* arm_LDR Q24 X0 (Postimmediate_Offset (word 0x10)) *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x6e291f18; (* arm_EOR_VEC Q24 Q24 Q9 0x80 *) + 0x4e285a00; (* arm_AESD Q0 Q16 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a01; (* arm_AESD Q1 Q16 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a18; (* arm_AESD Q24 Q16 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285a20; (* arm_AESD Q0 Q17 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a21; (* arm_AESD Q1 Q17 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a38; (* arm_AESD Q24 Q17 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285980; (* arm_AESD Q0 Q12 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285981; (* arm_AESD Q1 Q12 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285998; (* arm_AESD Q24 Q12 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e2859a0; (* arm_AESD Q0 Q13 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859a1; (* arm_AESD Q1 Q13 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2859b8; (* arm_AESD Q24 Q13 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e2859c0; (* arm_AESD Q0 Q14 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859c1; (* arm_AESD Q1 Q14 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2859d8; (* arm_AESD Q24 Q14 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e2859e0; (* arm_AESD Q0 Q15 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859e1; (* arm_AESD Q1 Q15 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2859f8; (* arm_AESD Q24 Q15 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285880; (* arm_AESD Q0 Q4 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285881; (* arm_AESD Q1 Q4 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285898; (* arm_AESD Q24 Q4 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e2858a0; (* arm_AESD Q0 Q5 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2858a1; (* arm_AESD Q1 Q5 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2858b8; (* arm_AESD Q24 Q5 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285a40; (* arm_AESD Q0 Q18 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a41; (* arm_AESD Q1 Q18 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a58; (* arm_AESD Q24 Q18 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285a60; (* arm_AESD Q0 Q19 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a61; (* arm_AESD Q1 Q19 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a78; (* arm_AESD Q24 Q19 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285a80; (* arm_AESD Q0 Q20 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a81; (* arm_AESD Q1 Q20 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a98; (* arm_AESD Q24 Q20 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285aa0; (* arm_AESD Q0 Q21 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285aa1; (* arm_AESD Q1 Q21 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285ab8; (* arm_AESD Q24 Q21 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285ac0; (* arm_AESD Q0 Q22 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285ac1; (* arm_AESD Q1 Q22 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285ad8; (* arm_AESD Q24 Q22 *) + 0x4e287b18; (* arm_AESIMC Q24 Q24 *) + 0x4e285ae0; (* arm_AESD Q0 Q23 *) + 0x4e285ae1; (* arm_AESD Q1 Q23 *) + 0x4e285af8; (* arm_AESD Q24 Q23 *) + 0x6e271c00; (* arm_EOR_VEC Q0 Q0 Q7 0x80 *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x6e271c21; (* arm_EOR_VEC Q1 Q1 Q7 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x6e271f18; (* arm_EOR_VEC Q24 Q24 Q7 0x80 *) + 0x6e291f18; (* arm_EOR_VEC Q24 Q24 Q9 0x80 *) + 0x9e660129; (* arm_FMOV_FtoI X9 Q9 0x0 0x40 *) + 0x9eae012a; (* arm_FMOV_FtoI X10 Q9 0x1 0x40 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670126; (* arm_FMOV_ItoF Q6 X9 0x0 *) + 0x9eaf0146; (* arm_FMOV_ItoF Q6 X10 0x1 *) + 0x4c9fa020; (* arm_STP Q0 Q1 X1 (Postimmediate_Offset (word 0x20)) *) + 0x4c9f7038; (* arm_STR Q24 X1 (Postimmediate_Offset (word 0x10)) *) + 0x14000071; (* arm_B (word 0x1c4) *) + 0x4cdfa000; (* arm_LDP Q0 Q1 X0 (Postimmediate_Offset (word 0x20)) *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x4e285a00; (* arm_AESD Q0 Q16 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a01; (* arm_AESD Q1 Q16 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a20; (* arm_AESD Q0 Q17 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a21; (* arm_AESD Q1 Q17 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285980; (* arm_AESD Q0 Q12 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285981; (* arm_AESD Q1 Q12 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2859a0; (* arm_AESD Q0 Q13 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859a1; (* arm_AESD Q1 Q13 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2859c0; (* arm_AESD Q0 Q14 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859c1; (* arm_AESD Q1 Q14 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2859e0; (* arm_AESD Q0 Q15 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859e1; (* arm_AESD Q1 Q15 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285880; (* arm_AESD Q0 Q4 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285881; (* arm_AESD Q1 Q4 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e2858a0; (* arm_AESD Q0 Q5 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2858a1; (* arm_AESD Q1 Q5 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a40; (* arm_AESD Q0 Q18 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a41; (* arm_AESD Q1 Q18 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a60; (* arm_AESD Q0 Q19 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a61; (* arm_AESD Q1 Q19 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285a80; (* arm_AESD Q0 Q20 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a81; (* arm_AESD Q1 Q20 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285aa0; (* arm_AESD Q0 Q21 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285aa1; (* arm_AESD Q1 Q21 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285ac0; (* arm_AESD Q0 Q22 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285ac1; (* arm_AESD Q1 Q22 *) + 0x4e287821; (* arm_AESIMC Q1 Q1 *) + 0x4e285ae0; (* arm_AESD Q0 Q23 *) + 0x4e285ae1; (* arm_AESD Q1 Q23 *) + 0x6e271c00; (* arm_EOR_VEC Q0 Q0 Q7 0x80 *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x6e271c21; (* arm_EOR_VEC Q1 Q1 Q7 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x4c9fa020; (* arm_STP Q0 Q1 X1 (Postimmediate_Offset (word 0x20)) *) + 0x9e660109; (* arm_FMOV_FtoI X9 Q8 0x0 0x40 *) + 0x9eae010a; (* arm_FMOV_FtoI X10 Q8 0x1 0x40 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670126; (* arm_FMOV_ItoF Q6 X9 0x0 *) + 0x9eaf0146; (* arm_FMOV_ItoF Q6 X10 0x1 *) + 0x1400002a; (* arm_B (word 0xa8) *) + 0x4cdf7000; (* arm_LDR Q0 X0 (Postimmediate_Offset (word 0x10)) *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x4e285a00; (* arm_AESD Q0 Q16 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a20; (* arm_AESD Q0 Q17 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285980; (* arm_AESD Q0 Q12 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859a0; (* arm_AESD Q0 Q13 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859c0; (* arm_AESD Q0 Q14 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2859e0; (* arm_AESD Q0 Q15 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285880; (* arm_AESD Q0 Q4 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e2858a0; (* arm_AESD Q0 Q5 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a40; (* arm_AESD Q0 Q18 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a60; (* arm_AESD Q0 Q19 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285a80; (* arm_AESD Q0 Q20 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285aa0; (* arm_AESD Q0 Q21 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285ac0; (* arm_AESD Q0 Q22 *) + 0x4e287800; (* arm_AESIMC Q0 Q0 *) + 0x4e285ae0; (* arm_AESD Q0 Q23 *) + 0x6e271c00; (* arm_EOR_VEC Q0 Q0 Q7 0x80 *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x4c9f7020; (* arm_STR Q0 X1 (Postimmediate_Offset (word 0x10)) *) + 0x9e6600c9; (* arm_FMOV_FtoI X9 Q6 0x0 0x40 *) + 0x9eae00ca; (* arm_FMOV_FtoI X10 Q6 0x1 0x40 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670126; (* arm_FMOV_ItoF Q6 X9 0x0 *) + 0x9eaf0146; (* arm_FMOV_ItoF Q6 X10 0x1 *) + 0x14000001; (* arm_B (word 0x4) *) + 0xf2400ebf; (* arm_TST X21 (rvalue (word 0xf)) *) + 0x54000a40; (* arm_BEQ (word 0x148) *) + 0xaa0303e7; (* arm_MOV X7 X3 *) + 0x9e6600c9; (* arm_FMOV_FtoI X9 Q6 0x0 0x40 *) + 0x9eae00ca; (* arm_FMOV_FtoI X10 Q6 0x1 0x40 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670128; (* arm_FMOV_ItoF Q8 X9 0x0 *) + 0x9eaf0148; (* arm_FMOV_ItoF Q8 X10 0x1 *) + 0x4cdf7800; (* arm_LDR Q0 X0 (Postimmediate_Offset (word 0x10)) *) + 0x6e281c1a; (* arm_EOR_VEC Q26 Q0 Q8 0x80 *) + 0x4e285a1a; (* arm_AESD Q26 Q16 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285a3a; (* arm_AESD Q26 Q17 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e28599a; (* arm_AESD Q26 Q12 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e2859ba; (* arm_AESD Q26 Q13 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e2859da; (* arm_AESD Q26 Q14 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e2859fa; (* arm_AESD Q26 Q15 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e28589a; (* arm_AESD Q26 Q4 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e2858ba; (* arm_AESD Q26 Q5 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285a5a; (* arm_AESD Q26 Q18 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285a7a; (* arm_AESD Q26 Q19 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285a9a; (* arm_AESD Q26 Q20 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285aba; (* arm_AESD Q26 Q21 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285ada; (* arm_AESD Q26 Q22 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285afa; (* arm_AESD Q26 Q23 *) + 0x6e271f5a; (* arm_EOR_VEC Q26 Q26 Q7 0x80 *) + 0x6e281f5a; (* arm_EOR_VEC Q26 Q26 Q8 0x80 *) + 0x4c00703a; (* arm_STR Q26 X1 No_Offset *) + 0xaa0003f4; (* arm_MOV X20 X0 *) + 0x9100402d; (* arm_ADD X13 X1 (rvalue (word 0x10)) *) + 0xf10006b5; (* arm_SUBS X21 X21 (rvalue (word 0x1)) *) + 0x3875682f; (* arm_LDRB W15 X1 (Register_Offset X21) *) + 0x38756a8e; (* arm_LDRB W14 X20 (Register_Offset X21) *) + 0x383569af; (* arm_STRB W15 X13 (Register_Offset X21) *) + 0x3835682e; (* arm_STRB W14 X1 (Register_Offset X21) *) + 0x54ffff6c; (* arm_BGT (word 0x1fffec) *) + 0x4c40703a; (* arm_LDR Q26 X1 No_Offset *) + 0x6e261f5a; (* arm_EOR_VEC Q26 Q26 Q6 0x80 *) + 0x4e285a1a; (* arm_AESD Q26 Q16 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285a3a; (* arm_AESD Q26 Q17 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e28599a; (* arm_AESD Q26 Q12 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e2859ba; (* arm_AESD Q26 Q13 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e2859da; (* arm_AESD Q26 Q14 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e2859fa; (* arm_AESD Q26 Q15 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e28589a; (* arm_AESD Q26 Q4 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e2858ba; (* arm_AESD Q26 Q5 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285a5a; (* arm_AESD Q26 Q18 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285a7a; (* arm_AESD Q26 Q19 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285a9a; (* arm_AESD Q26 Q20 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285aba; (* arm_AESD Q26 Q21 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285ada; (* arm_AESD Q26 Q22 *) + 0x4e287b5a; (* arm_AESIMC Q26 Q26 *) + 0x4e285afa; (* arm_AESD Q26 Q23 *) + 0x6e271f5a; (* arm_EOR_VEC Q26 Q26 Q7 0x80 *) + 0x6e261f5a; (* arm_EOR_VEC Q26 Q26 Q6 0x80 *) + 0x4c00703a; (* arm_STR Q26 X1 No_Offset *) + 0x6d4227e8; (* arm_LDP D8 D9 SP (Immediate_Offset (iword (&0x20))) *) + 0x6d432fea; (* arm_LDP D10 D11 SP (Immediate_Offset (iword (&0x30))) *) + 0x6d4437ec; (* arm_LDP D12 D13 SP (Immediate_Offset (iword (&0x40))) *) + 0x6d453fee; (* arm_LDP D14 D15 SP (Immediate_Offset (iword (&0x50))) *) + 0xa94053f3; (* arm_LDP X19 X20 SP (Immediate_Offset (iword (&0x0))) *) + 0xa9415bf5; (* arm_LDP X21 X22 SP (Immediate_Offset (iword (&0x10))) *) + 0x910183ff; (* arm_ADD SP SP (rvalue (word 0x60)) *) + 0xd65f03c0 (* arm_RET X30 *) +];; + +let AES_XTS_DECRYPT_EXEC = ARM_MK_EXEC_RULE aes_xts_decrypt_mc;; + +(**********************************************************************) +(** Decrypt-specific lemmas **) + +let LENGTH_OF_AES256_XTS_DECRYPT_REC = prove( + `!(i:num) (m:num) (C:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + LENGTH(aes256_xts_decrypt_rec i m C iv key1 key2) = (if m < i then 0 else (m - i + 1) * 0x10)`, + REPEAT GEN_TAC THEN + (* Wellfounded induction with measure (m + 1) - i + Note that the parentheses are essential because of the precedence of + and - *) + WF_INDUCT_TAC `(m + 1) - i` THEN + ONCE_REWRITE_TAC[aes256_xts_decrypt_rec] THEN + COND_CASES_TAC THENL + [ SIMP_TAC[LENGTH_EQ_NIL]; + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[LENGTH_APPEND] THEN + SUBGOAL_THEN `~(m < i) ==> (m + 1) - (i + 1) < (m + 1) - i` ASSUME_TAC THENL + [ ASM_ARITH_TAC ; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + COND_CASES_TAC THENL + [ASM_ARITH_TAC; ASM_ARITH_TAC]] +);; + +let LENGTH_OF_FST_OF_CIPHER_STEALING = prove( + `!(block:byte list) (tail:byte list) (tail_len:num) + (iv:int128) (i:num) (key1:int128 list) (key2:int128 list). + LENGTH (FST (cipher_stealing block tail tail_len iv i key1 key2)) = 16`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[cipher_stealing] THEN + ASM_REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] +);; + +let LENGTH_OF_SND_OF_CIPHER_STEALING = prove( + `!(block:byte list) (tail:byte list) (tail_len:num) + (iv:int128) (i:num) (key1:int128 list) (key2:int128 list). + LENGTH (SND (cipher_stealing block tail tail_len iv i key1 key2)) = MIN tail_len 16`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[cipher_stealing] THEN + ASM_REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[LENGTH_SUB_LIST] THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[MIN] THEN + CONV_TAC NUM_REDUCE_CONV +);; + +let LENGTH_OF_AES256_XTS_DECRYPT_TAIL = prove( + `! (i:num) (tail_len:num) (C:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + LENGTH(aes256_xts_decrypt_tail i tail_len C iv key1 key2) = 0x10 + MIN tail_len 16`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[aes256_xts_decrypt_tail] THEN + COND_CASES_TAC THENL [ + ASM_REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[ADD_CLAUSES; MIN] THEN + CONV_TAC NUM_REDUCE_CONV; + + REWRITE_TAC[LET_DEF; LET_END_DEF; LENGTH_APPEND] THEN + REWRITE_TAC[LENGTH_OF_FST_OF_CIPHER_STEALING] THEN + REWRITE_TAC[LENGTH_OF_SND_OF_CIPHER_STEALING]] +);; + +let LENGTH_OF_AES256_XTS_DECRYPT_REC_TRIVIAL = prove( + `!(ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + LENGTH (aes256_xts_decrypt_rec 0x0 0x0 ct iv key1 key2) = 16`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_REC] THEN + CONV_TAC NUM_REDUCE_CONV +);; + +let LENGTH_OF_AES256_XTS_DECRYPT_TAIL_TRIVIAL = prove( + `!(ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + LENGTH(aes256_xts_decrypt_tail 0 0 ct iv key1 key2) = 16`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_TAIL] THEN + CONV_TAC NUM_REDUCE_CONV +);; + +let AES256_XTS_DECRYPT_REC_EQ_TAIL_TRIVIAL = prove( + `!(ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + aes256_xts_decrypt_rec 0x0 0x0 ct iv key1 key2 = + aes256_xts_decrypt_tail 0x0 0x0 ct iv key1 key2`, + REPEAT STRIP_TAC THEN + ONCE_REWRITE_TAC[aes256_xts_decrypt_rec] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + ONCE_REWRITE_TAC[aes256_xts_decrypt_rec] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[APPEND_NIL] THEN + + REWRITE_TAC[aes256_xts_decrypt_tail] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV +);; + +let LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS = prove( + `! (i:num) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + LENGTH(aes256_xts_decrypt ct (0x10 * i) iv key1 key2) = 0x10 * i`, + REPEAT STRIP_TAC THEN + SPEC_TAC (`i:num`, `i:num`) THEN + INDUCT_TAC THENL + [ + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[aes256_xts_decrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LENGTH_EQ_NIL]; + ALL_TAC] THEN + + REWRITE_TAC[ADD1; LEFT_ADD_DISTRIB] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[aes256_xts_decrypt] THEN + + ASM_CASES_TAC `i = 0` THENL + [ ASM_SIMP_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[LET_DEF;LET_END_DEF;SUB_0] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_TAIL_TRIVIAL] + ; ALL_TAC + ] THEN + + SUBGOAL_THEN `~(0x10 * i + 0x10 < 0x10)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC ] THEN ASM_SIMP_TAC[] THEN + REWRITE_TAC[ARITH_RULE `0x10 * i + 0x10 = 0x10 * (i + 1)`; MOD_MULT] THEN + IMP_REWRITE_TAC[LET_DEF; LET_END_DEF;SUB_0;DIV_MULT] THEN + CONJ_TAC THENL [ALL_TAC; ARITH_TAC] THEN + SUBGOAL_THEN `~(i + 0x1 < 0x2)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN ASM_SIMP_TAC[] THEN + REWRITE_TAC[LENGTH_APPEND] THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_REC] THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_TAIL] THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_ARITH_TAC +);; + +let LENGTH_OF_AES256_XTS_DECRYPT = prove( + `! (i:num) (tail_len:num) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + ~(tail_len = 0) /\ tail_len < 16 ==> + LENGTH(aes256_xts_decrypt ct (16 * i + 16 + tail_len) iv key1 key2) = 16 * i + 16 + tail_len`, + REPEAT STRIP_TAC THEN + (* Case 1: i = 0 *) + ASM_CASES_TAC `i = 0` THENL + [ + ASM_SIMP_TAC[ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[aes256_xts_decrypt] THEN + SUBGOAL_THEN `~(0x10 + tail_len < 0x10)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `(0x10 + tail_len) MOD 0x10 = tail_len` ASSUME_TAC THENL + [ REWRITE_TAC[ARITH_RULE `0x10 + tail_len = 1 * 16 + tail_len`] THEN + IMP_REWRITE_TAC[MOD_MULT_ADD; MOD_LT]; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + SUBGOAL_THEN `((0x10 + tail_len) - tail_len) DIV 0x10 = 1` SUBST1_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC ] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_TAIL] THEN + ASM_ARITH_TAC; + ALL_TAC + ] THEN + + (* Case 2: i >= 1 *) + ASM_CASES_TAC `i >= 1` THENL + [ + REWRITE_TAC[aes256_xts_decrypt] THEN + SUBGOAL_THEN `(0x10 * i + 0x10 + tail_len) MOD 0x10 = tail_len` SUBST1_TAC THENL + [ REWRITE_TAC[ADD_ASSOC; ARITH_RULE `0x10 * i + 0x10 = 16 * (i + 1)`] THEN + IMP_REWRITE_TAC[MOD_MULT_ADD; MOD_LT]; ALL_TAC] THEN + SUBGOAL_THEN `~(0x10 * i + 0x10 + tail_len < 0x10)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + SUBGOAL_THEN `((0x10 * i + 0x10 + tail_len) - tail_len) DIV 0x10 = i + 1` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `(0x10 * i + 0x10 + tail_len) - tail_len = 16 * (i + 1)`] THEN + IMP_REWRITE_TAC[DIV_MULT] THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(i + 1 < 2)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + IMP_REWRITE_TAC[ARITH_RULE `(i + 1) - 2 = i - 1`; ADD_SUB] THEN + REWRITE_TAC[LENGTH_APPEND] THEN + IMP_REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_REC] THEN + IMP_REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_TAIL] THEN + ASM_ARITH_TAC; + ALL_TAC + ] THEN + + ASM_ARITH_TAC +);; + +let AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK = prove( + `!(n:num) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + bytes_to_int128 + (aes256_xts_decrypt_tail n 0x0 ct iv key1 key2) = + aes256_xts_decrypt_round + (bytes_to_int128 (SUB_LIST (n * 0x10,0x10) ct)) + (calculate_tweak n iv key2) key1`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[aes256_xts_decrypt_tail] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[BYTES_TO_INT128_OF_INT128_TO_BYTES] +);; + +let AES256_XTS_DECRYPT_REC_EQ_TAIL = prove( + `!(i:num) (k:num) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + k >= i ==> + aes256_xts_decrypt_rec i (k + 1) ct iv key1 key2 = + APPEND (aes256_xts_decrypt_rec i k ct iv key1 key2) + (aes256_xts_decrypt_tail (k + 1) 0x0 ct iv key1 key2)`, + REPEAT GEN_TAC THEN + WF_INDUCT_TAC `(k + 1) - i` THEN + STRIP_TAC THEN + GEN_REWRITE_TAC (RATOR_CONV o ONCE_DEPTH_CONV) [aes256_xts_decrypt_rec] THEN + SUBGOAL_THEN `~(k + 0x1 < i)` ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + SUBGOAL_THEN `(k + 1) - (i + 1) < (k + 1) - i` ASSUME_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + FIRST_X_ASSUM (MP_TAC o SPECL [`k:num`; `i + 1:num`]) THEN + ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + ASM_CASES_TAC `k >= i + 1` THENL + [ + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + REWRITE_TAC[APPEND_ASSOC] THEN + AP_THM_TAC THEN + GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [aes256_xts_decrypt_rec] THEN + SUBGOAL_THEN `~(k < i)` ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF]; ALL_TAC + ] THEN + SUBGOAL_THEN `k:num = i` ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + STRIP_TAC THEN ASM_REWRITE_TAC[] THEN + ONCE_REWRITE_TAC[aes256_xts_decrypt_rec] THEN + REWRITE_TAC[LT_REFL; LET_DEF; LET_END_DEF] THEN + ONCE_REWRITE_TAC[aes256_xts_decrypt_rec] THEN + REWRITE_TAC[ARITH_RULE `i < i + 1`; APPEND_NIL] THEN + AP_TERM_TAC THEN + REWRITE_TAC[aes256_xts_decrypt_tail; LET_DEF; LET_END_DEF] +);; + + +let SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS = prove( + `!(i:num) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + (SUB_LIST (0,16 * i) + (aes256_xts_decrypt ct (16 * i + 16) iv key1 key2)) + = aes256_xts_decrypt ct (16 * i) iv key1 key2`, + REPEAT STRIP_TAC THEN + + (* when i = 0, trivial *) + ASM_CASES_TAC `i = 0` THENL + [ + ASM_REWRITE_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[CONJUNCT1 SUB_LIST; aes256_xts_decrypt] THEN + CONV_TAC NUM_REDUCE_CONV; + ALL_TAC + ] THEN + + (* when i = 1, using aes256_xts_decrypt_tail *) + ASM_CASES_TAC `i = 1` THENL + [ + ASM_REWRITE_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[aes256_xts_decrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`ct:byte list`; `iv:int128`; `key1: int128 list`; `key2: int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC_TRIVIAL) THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_LEFT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + REWRITE_TAC[AES256_XTS_DECRYPT_REC_EQ_TAIL_TRIVIAL]; + ALL_TAC + ] THEN + + (* when i >= 2, using aes256_xts_decrypt_rec *) + REWRITE_TAC[aes256_xts_decrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `~(0x10 * i < 0x10)` ASSUME_TAC THENL + [ ASM_ARITH_TAC ; ALL_TAC] THEN + SUBGOAL_THEN `~(0x10 * i + 0x10 < 0x10)` ASSUME_TAC THENL + [ ASM_ARITH_TAC ; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + REWRITE_TAC[ARITH_RULE `16 * i + 16 = 16 * (i + 1)`; MOD_MULT] THEN + IMP_REWRITE_TAC[LET_DEF;LET_END_DEF;SUB_0;DIV_MULT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `~(i < 0x2)` ASSUME_TAC THENL + [ ASM_ARITH_TAC ; ALL_TAC] THEN + SUBGOAL_THEN `~(i + 1 < 0x2)` ASSUME_TAC THENL + [ ASM_ARITH_TAC ; ALL_TAC] THEN + ASM_SIMP_TAC[ARITH_RULE `(i + 0x1) - 0x2 = i - 1`; ADD_SUB] THEN + SUBGOAL_THEN `LENGTH (aes256_xts_decrypt_rec 0x0 (i - 0x1) ct iv key1 key2) = 16 * i` ASSUME_TAC THENL + [ REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_REC] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_LEFT; SUB_LIST_LENGTH_IMPLIES] THEN + CONJ_TAC THENL [ALL_TAC; ARITH_TAC] THEN + SUBGOAL_THEN `i - 1 = i - 2 + 1` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC ] THEN + ASM_REWRITE_TAC[] THEN + IMP_REWRITE_TAC[AES256_XTS_DECRYPT_REC_EQ_TAIL] THEN + ASM_ARITH_TAC +);; + +let SUB_LIST_OF_AES256_XTS_DECRYPT = prove( + `!(i:num) (tail_len:num) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + ~(tail_len = 0) /\ tail_len < 16 ==> + (SUB_LIST (0,16 * i) + (aes256_xts_decrypt ct (16 * i + 16 + tail_len) iv key1 key2)) + = aes256_xts_decrypt ct (16 * i) iv key1 key2`, + REPEAT STRIP_TAC THEN + (* Case 1: i = 0 *) + ASM_CASES_TAC `i = 0` THENL + [ + ASM_REWRITE_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[ADD; SUB_LIST_CLAUSES; aes256_xts_decrypt] THEN + CONV_TAC NUM_REDUCE_CONV; + ALL_TAC + ] THEN + (* Case 2: i = 1 *) + ASM_CASES_TAC `i = 1` THENL + [ + ASM_REWRITE_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[aes256_xts_decrypt; ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `~(0x20 + tail_len < 0x10)` ASSUME_TAC THENL [ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `(0x20 + tail_len) MOD 0x10 = tail_len` ASSUME_TAC THENL + [ ASM_SIMP_TAC[ARITH_RULE `32 = 2 * 16`; MOD_MULT_ADD] THEN + IMP_REWRITE_TAC[MOD_LT] + ; ALL_TAC] THEN + SUBGOAL_THEN `((0x20 + tail_len) - (0x20 + tail_len) MOD 0x10) DIV 0x10 = 0x2` ASSUME_TAC THENL + [ ASM_REWRITE_TAC[ADD_ASSOC; ADD_SUB] THEN + ARITH_TAC ; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_REWRITE_TAC[] THEN + MP_TAC (SPECL [`ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_REC_TRIVIAL) THEN + DISCH_TAC THEN IMP_REWRITE_TAC[SUB_LIST_APPEND_LEFT] THEN + REWRITE_TAC[AES256_XTS_DECRYPT_REC_EQ_TAIL_TRIVIAL] THEN + MP_TAC (SPECL [`ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_TAIL_TRIVIAL) THEN + DISCH_TAC THEN IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + ARITH_TAC; + ALL_TAC + ] THEN + + (* Case 3: i >= 2 *) + ASM_CASES_TAC `i >= 2` THENL + [ + ASM_REWRITE_TAC[ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[aes256_xts_decrypt] THEN + SUBGOAL_THEN `~(0x10 * i < 0x10)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~((0x10 * i + 0x10) + tail_len < 0x10)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[LET_DEF; LET_END_DEF] THEN + SUBGOAL_THEN `((0x10 * i + 0x10) + tail_len) MOD 0x10 = tail_len` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `0x10 * i + 0x10 = 16 * (i + 1)`] THEN + IMP_REWRITE_TAC[MOD_MULT_ADD; MOD_LT] + ; ALL_TAC] THEN + REWRITE_TAC[ADD_SUB; MOD_MULT; SUB_0; + ARITH_RULE `0x10 * i + 0x10 = 16 * (i + 1)`] THEN + IMP_REWRITE_TAC[DIV_MULT] THEN + SUBGOAL_THEN `~(i + 1 < 2)` ASSUME_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(i < 2)` ASSUME_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[ADD_SUB; ARITH_RULE `(i + 1) - 2 = i - 1`] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0:num`; `(i - 1):num`; `ct:byte list`; `iv:int128`; + `key1:int128 list`; `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SUBGOAL_THEN `~((i - 1) < 0)` ASSUME_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + IMP_REWRITE_TAC[ARITH_RULE `i >= 2 ==> i - 0x1 - 0x0 + 0x1 = i`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_LEFT] THEN + SIMP_TAC[ARITH_RULE `16 * i <= i * 16`] THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + SIMP_TAC[ARITH_RULE `i * 16 = 16 * i`] THEN + DISCH_TAC THEN + MP_TAC (SPECL [`0`; `(i-2):num`; `ct:byte list`; `iv:int128`; + `key1:int128 list`; `key2:int128 list`] AES256_XTS_DECRYPT_REC_EQ_TAIL) THEN + ANTS_TAC THENL [ ASM_ARITH_TAC; ALL_TAC ] THEN + IMP_REWRITE_TAC[ARITH_RULE `i >= 2 ==> i - 0x2 + 0x1 = i - 1`]; + ALL_TAC + ] THEN + + ASM_ARITH_TAC +);; + +let READ_BYTES_EQ_READ_BYTE128_1BLOCK = prove( + `!(ptr:int64) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list) s. + (read (memory :> bytes128 pt_ptr) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x0,0x10) ct)) + (calculate_tweak 0x0 iv key2) + key1) ==> + read (memory :> bytes (pt_ptr,0x10)) s = + num_of_bytelist (SUB_LIST (0x0,0x10) (aes256_xts_decrypt ct 0x10 iv key1 key2))`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[READ_MEMORY_BYTES_BYTES128] THEN + ASM_REWRITE_TAC[] THEN + REWRITE_TAC[aes256_xts_decrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[aes256_xts_decrypt_tail] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[SUB_LIST_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[NUM_OF_BYTELIST_OF_INT128_TO_BYTES] +);; + +let READ_BYTES_EQ_READ_BYTE128_2BLOCKS = prove( + `!(ptr:int64) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list) s. + (read (memory :> bytes128 pt_ptr) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x0,0x10) ct)) + (calculate_tweak 0x0 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x10))) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x10,0x10) ct)) + (calculate_tweak 0x1 iv key2) + key1) ==> + read (memory :> bytes (pt_ptr,0x20)) s = + num_of_bytelist (SUB_LIST (0x0,0x20) (aes256_xts_decrypt ct 0x20 iv key1 key2))`, + REPEAT STRIP_TAC THEN + IMP_REWRITE_TAC[ARITH_RULE `0x20 = 0x10 + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `aes256_xts_decrypt ct 0x20 iv key1 key2` THEN + REPEAT CONJ_TAC THENL + [ + CONV_TAC NUM_REDUCE_CONV; + + MP_TAC (SPECL [`2:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + ARITH_TAC; + + REWRITE_TAC[aes256_xts_decrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC_TRIVIAL) THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + REWRITE_TAC[aes256_xts_decrypt_tail] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[SUB_LIST_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[NUM_OF_BYTELIST_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[BYTES_TO_INT128_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV; + + MP_TAC (SPECL [`1:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + CONV_TAC NUM_REDUCE_CONV THEN + SIMP_TAC[] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_1BLOCK] THEN + MP_TAC (SPECL [`1:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] + ] +);; + +let READ_BYTES_EQ_READ_BYTE128_3BLOCKS = prove( + `!(ptr:int64) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list) s. + (read (memory :> bytes128 pt_ptr) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x0,0x10) ct)) + (calculate_tweak 0x0 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x10))) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x10,0x10) ct)) + (calculate_tweak 0x1 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x20))) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x20,0x10) ct)) + (calculate_tweak 0x2 iv key2) + key1) ==> + read (memory :> bytes (pt_ptr,0x30)) s = + num_of_bytelist (SUB_LIST (0x0,0x30) (aes256_xts_decrypt ct 0x30 iv key1 key2))`, + REPEAT STRIP_TAC THEN + IMP_REWRITE_TAC[ARITH_RULE `0x30 = 0x20 + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `aes256_xts_decrypt ct 0x30 iv key1 key2` THEN + REPEAT CONJ_TAC THENL + [ + CONV_TAC NUM_REDUCE_CONV; + + MP_TAC (SPECL [`3:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + ARITH_TAC; + + REWRITE_TAC[aes256_xts_decrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0:num`; `1:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + REWRITE_TAC[aes256_xts_decrypt_tail] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[SUB_LIST_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[NUM_OF_BYTELIST_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[BYTES_TO_INT128_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV; + ALL_TAC] THEN + + MP_TAC (SPECL [`2:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + CONV_TAC NUM_REDUCE_CONV THEN + SIMP_TAC[] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_2BLOCKS] THEN + MP_TAC (SPECL [`2:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] +);; + +let READ_BYTES_EQ_READ_BYTE128_4BLOCKS = prove( + `!(ptr:int64) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list) s. + (read (memory :> bytes128 pt_ptr) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x0,0x10) ct)) + (calculate_tweak 0x0 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x10))) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x10,0x10) ct)) + (calculate_tweak 0x1 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x20))) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x20,0x10) ct)) + (calculate_tweak 0x2 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x30))) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x30,0x10) ct)) + (calculate_tweak 0x3 iv key2) + key1) ==> + read (memory :> bytes (pt_ptr,0x40)) s = + num_of_bytelist (SUB_LIST (0x0,0x40) (aes256_xts_decrypt ct 0x40 iv key1 key2))`, + REPEAT STRIP_TAC THEN + IMP_REWRITE_TAC[ARITH_RULE `0x40 = 0x30 + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `aes256_xts_decrypt ct 0x40 iv key1 key2` THEN + REPEAT CONJ_TAC THENL + [ + CONV_TAC NUM_REDUCE_CONV; + + MP_TAC (SPECL [`4:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + ARITH_TAC; + + REWRITE_TAC[aes256_xts_decrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0:num`; `2:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + REWRITE_TAC[aes256_xts_decrypt_tail] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[SUB_LIST_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[BYTES_TO_INT128_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV; + ALL_TAC] THEN + + MP_TAC (SPECL [`3:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + CONV_TAC NUM_REDUCE_CONV THEN + SIMP_TAC[] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_3BLOCKS] THEN + MP_TAC (SPECL [`3:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] +);; + + +let READ_BYTES_EQ_READ_BYTE128_5BLOCKS = prove( + `!(ptr:int64) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list) s. + (read (memory :> bytes128 pt_ptr) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x0,0x10) ct)) + (calculate_tweak 0x0 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x10))) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x10,0x10) ct)) + (calculate_tweak 0x1 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x20))) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x20,0x10) ct)) + (calculate_tweak 0x2 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x30))) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x30,0x10) ct)) + (calculate_tweak 0x3 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x40))) s = + aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (0x40,0x10) ct)) + (calculate_tweak 0x4 iv key2) + key1) ==> + read (memory :> bytes (pt_ptr,0x50)) s = + num_of_bytelist (SUB_LIST (0x0,0x50) (aes256_xts_decrypt ct 0x50 iv key1 key2))`, + REPEAT STRIP_TAC THEN + IMP_REWRITE_TAC[ARITH_RULE `0x50 = 0x40 + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `aes256_xts_decrypt ct 0x50 iv key1 key2` THEN + REPEAT CONJ_TAC THENL + [ + CONV_TAC NUM_REDUCE_CONV; + + MP_TAC (SPECL [`5:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + ARITH_TAC; + + REWRITE_TAC[aes256_xts_decrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0:num`; `3:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + REWRITE_TAC[aes256_xts_decrypt_tail] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[SUB_LIST_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[BYTES_TO_INT128_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV; + ALL_TAC] THEN + + MP_TAC (SPECL [`4:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + CONV_TAC NUM_REDUCE_CONV THEN + SIMP_TAC[] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_4BLOCKS] THEN + MP_TAC (SPECL [`4:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] +);; + +(**********************************************************************) +(** Tactics **) + +let AESENC_TAC = + REWRITE_TAC [aes256_encrypt] THEN + REWRITE_TAC EL_15_128_CLAUSES THEN + REWRITE_TAC [aes256_encrypt_round] THEN + CONV_TAC(TOP_DEPTH_CONV let_CONV) THEN + REWRITE_TAC [aese;aesmc] THEN + GEN_REWRITE_TAC LAND_CONV [WORD_XOR_SYM] THEN + REFL_TAC;; + +let AESDEC_TAC = + REWRITE_TAC [aes256_decrypt] THEN + REWRITE_TAC EL_15_128_CLAUSES THEN + CONV_TAC(TOP_DEPTH_CONV let_CONV) THEN + REWRITE_TAC [aes256_decrypt_round] THEN + CONV_TAC(TOP_DEPTH_CONV let_CONV) THEN + REWRITE_TAC [aesd;aesimc] THEN + (* NOTE: BITBLAST_TAC couldn't handle this goal *) + GEN_REWRITE_TAC LAND_CONV [WORD_XOR_SYM] THEN + AP_THM_TAC THEN AP_TERM_TAC THEN + GEN_REWRITE_TAC LAND_CONV [WORD_XOR_SYM] THEN + AP_THM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN + REPLICATE_TAC 13 (AP_THM_TAC THEN (REPLICATE_TAC 4 AP_TERM_TAC)) THEN + AP_THM_TAC THEN AP_TERM_TAC THEN + GEN_REWRITE_TAC LAND_CONV [WORD_XOR_SYM] THEN REFL_TAC;; + +let TWEAK_UPDATE_CONV = + let thms = CONJUNCTS + ((REWRITE_RULE[ARITH; ADD_0] o + CONV_RULE EXPAND_CASES_CONV o ARITH_RULE) + `forall i. i < 9 ==> forall n. n + SUC i = SUC (n + i)`) in + NUM_REDUCE_CONV THENC + RATOR_CONV (LAND_CONV (num_CONV ORELSEC + FIRST_CONV + (map (fun th -> CHANGED_CONV (ONCE_REWRITE_CONV [th])) thms))) THENC + REWRITE_CONV [CONJUNCT2 calculate_tweak] THENC + GF_128_MULT_BY_PRIMITIVE_CONV;; + +let TWEAK_TAC reg ind indm1 = + let lower_term = subst [ind,`ind:num`] `(word_zx:int128->int64) (calculate_tweak ind iv key2)` in + let upper_term = subst [ind,`ind:num`] `(word_subword:int128->num#num->int64) (calculate_tweak ind iv key2) (64,64)` in + let full_term = subst [ind,`ind:num`] `calculate_tweak ind iv key2` in + let full_lemma = subst [reg,`reg:(armstate,int128)component`] `read (reg:(armstate,int128)component) (s:armstate) = a ==> !a'. a = a' ==> read reg s = a'` in + let abbrev_term = subst [indm1,`indm1:num`] `tweak_pre:int128 = (calculate_tweak indm1 iv key2)` in + FIRST_X_ASSUM(MP_TAC o SPEC lower_term + o MATCH_MP (MESON[] `read X9 s = a ==> !a'. a = a' ==> read X9 s = a'`)) THEN + ANTS_TAC THENL [CONV_TAC (RAND_CONV (RAND_CONV TWEAK_UPDATE_CONV)) THEN + ABBREV_TAC abbrev_term THEN + BITBLAST_TAC; DISCH_TAC] THEN + FIRST_X_ASSUM(MP_TAC o SPEC upper_term + o MATCH_MP (MESON[] `read X10 s = a ==> !a'. a = a' ==> read X10 s = a'`)) THEN + ANTS_TAC THENL [CONV_TAC (RAND_CONV (RATOR_CONV (RAND_CONV TWEAK_UPDATE_CONV))) THEN + ABBREV_TAC abbrev_term THEN + BITBLAST_TAC; DISCH_TAC] THEN + FIRST_X_ASSUM(MP_TAC o SPEC full_term + o MATCH_MP (MESON[] full_lemma)) THEN + ANTS_TAC THENL [CONV_TAC (RAND_CONV TWEAK_UPDATE_CONV) THEN + ABBREV_TAC abbrev_term THEN + BITBLAST_TAC; DISCH_TAC];; + +let XTSDEC_TAC reg ind ind_tweak = + let tm = subst [ind, `ind:num`; ind_tweak, `ind_tweak:num`] + `aes256_xts_decrypt_round (bytes_to_int128 (SUB_LIST (ind,0x10) (ct:byte list))) + (calculate_tweak ind_tweak iv key2) key1` in + let lemma = subst [reg, `reg:(armstate,int128)component`] + `read (reg:(armstate,int128)component) (s:armstate) = a ==> !a'. a = a' ==> read reg s = a'` in + FIRST_X_ASSUM(MP_TAC o SPEC tm o MATCH_MP (MESON[] lemma)) THEN + ANTS_TAC THENL + [ EXPAND_TAC "key1" THEN + CONV_TAC (RAND_CONV ( + REWRITE_CONV [aes256_xts_decrypt_round] THENC + DEPTH_CONV let_CONV)) THEN + AESDEC_TAC; DISCH_TAC ];; + +let TAIL_SWAP_CASE_TAC case = + let c_tm = `case:num` in + let v_tm = `v:num` in + let v = rand (concl (NUM_RED_CONV (subst [case,c_tm] `0x10 + case`))) in + let r1 = subst [case,c_tm; v,v_tm] `curr_len + 0x10 + case = curr_len + v` in + let t1 = subst [case,c_tm] `(cipher_stealing_inv case curr_len (val (tail_len:int64)) PP ct):int128` in + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN REWRITE_TAC[th]) THEN + (* Simplify so that symbolic execution could match up, but couldn't use + CONV_TAC NUM_REDUCE_CONV because of non-overlapping *) + RULE_ASSUM_TAC(REWRITE_RULE[ARITH_RULE r1]) THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--5) THEN + RULE_ASSUM_TAC(REWRITE_RULE[GSYM ADD_ASSOC]) THEN + RULE_ASSUM_TAC (CONV_RULE NUM_REDUCE_CONV) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + REWRITE_TAC[ + WORD_RULE `!(a:int64) b c. word_add (word_add a b) c = word_add a (word_add b c)`; + WORD_RULE `!a b. word_add ((word a):int64) (word b) = word (a + b)`]; + + MATCH_MP_TAC (snd (EQ_IMP_RULE (SPECL [`(word_add pt_ptr (word curr_len)):int64`; + `s5:armstate`; t1] BREAK_ONE_BLOCK_INTO_BYTES))) THEN + REWRITE_TAC[ + WORD_RULE `!(a:int64) b c. word_add (word_add a b) c = word_add a (word_add b c)`; + WORD_RULE `!a b. word_add ((word a):int64) (word b) = word (a + b)`] THEN + ASM_REWRITE_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [case; `curr_len:num`; `tail_len:int64`; `PP:int128`; `ct:byte list`] + CIPHER_STEALING_BYTE_EQUAL) THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + STRIP_TAC THEN + + MAP_EVERY (fun i -> CONJ_TAC THENL + [CIPHER_STEALING_INV_SIMP_TAC (mk_numeral (num i)); ALL_TAC]) + (0--0xe) THEN + CIPHER_STEALING_INV_SIMP_TAC `0xf:num`; + + MP_TAC (SPECL [`pt_ptr:int64`; case; `val (tail_len:int64)`; + `curr_len:num`; `(int128_to_bytes PP):byte list`; `s5:armstate`] + BYTE_LIST_AT_SPLIT_BACKWARDS) THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_SIMP_TAC[] THEN + ANTS_TAC THENL + [ IMP_REWRITE_TAC[WORD_ZX_ZX] THEN + REWRITE_TAC[DIMINDEX_8; DIMINDEX_32; DIMINDEX_64] THEN + MP_TAC (SPECL [case; `curr_len:num`; `tail_len:int64`; `PP:int128`; `ct:byte list`] + CIPHER_STEALING_INV_SELECT) THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_SIMP_TAC[] + ; ALL_TAC ] THEN + MESON_TAC[]; + + WORD_ARITH_TAC; + WORD_ARITH_TAC + ];; + +let TAIL_SWAP_ASM_CASES_TAC case = + let c_tm = `case:num` in + let asm_case = subst [case, c_tm] `(i:num) = case` in + ASM_CASES_TAC asm_case THENL [ TAIL_SWAP_CASE_TAC case; ALL_TAC] THEN + MP_TAC (SPECL [case; `i:num`] LE_LT) THEN + ASM_SIMP_TAC[] THEN + DISCH_TAC THEN + MP_TAC (SPECL [case; `i:num`] LE_SUC_LT) THEN + ASM_SIMP_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_SIMP_TAC[] THEN + DISCH_TAC;; + + +(**********************************************************************) +(** Proofs **) + + +(* Proof: Cipher stealing *) +let CIPHER_STEALING_CORRECT = time prove( + `!ct_ptr pt_ptr ct key1_ptr iv len pc + k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e + tail_len num_blocks key1 num_blocks_adjusted num_5blocks_adjusted. + nonoverlapping (word pc, LENGTH aes_xts_decrypt_mc) (pt_ptr, val len) + /\ nonoverlapping (ct_ptr, val len) (pt_ptr, val len) + /\ nonoverlapping (key1_ptr, 260) (pt_ptr, val len) + /\ val len >= 16 /\ val len <= 2 EXP 24 /\ LENGTH ct = val len + /\ word_add tail_len num_blocks = len + /\ word_and len (word 0xfffffffffffffff0) = num_blocks + /\ word_and len (word 0xf) = tail_len + /\ [k00; k01; k02; k03; k04; k05; k06; k07; k08; k09; k0a; k0b; k0c; k0d; k0e] = key1 + /\ (if val tail_len = 0x0 then num_blocks else word_sub num_blocks (word 0x10)) = num_blocks_adjusted + /\ word (val num_blocks_adjusted DIV 0x50) = num_5blocks_adjusted + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes_xts_decrypt_mc /\ + read PC s = word (pc + 0xa0c) /\ + read X0 s = word_add ct_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X1 s = word_add pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X3 s = key1_ptr /\ + read X21 s = tail_len /\ + read Q6 s = calculate_tweak (acc_blocks num_5blocks_adjusted num_blocks_adjusted T) iv key2 /\ + read X19 s = word 0x87 /\ + read Q16 s = k00 /\ read Q17 s = k01 /\ read Q12 s = k02 /\ read Q13 s = k03 /\ + read Q14 s = k04 /\ read Q15 s = k05 /\ read Q4 s = k06 /\ read Q5 s = k07 /\ + read Q18 s = k08 /\ read Q19 s = k09 /\ read Q20 s = k0a /\ read Q21 s = k0b /\ + read Q22 s = k0c /\ read Q23 s = k0d /\ read Q7 s = k0e /\ + byte_list_at ct ct_ptr len s /\ + byte_list_at (aes256_xts_decrypt ct (acc_len num_5blocks_adjusted num_blocks_adjusted) iv key1 key2) + pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) s) + (\s. read PC s = word (pc + 0xb58) /\ + byte_list_at (aes256_xts_decrypt ct (val len) iv key1 key2) pt_ptr len s + ) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes(pt_ptr, val len)]) + `, + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + (* Prove once and for all the bounds for num_blocks, num_blocks_adjusted + and num_5blocks_adjusted *) + SUBGOAL_THEN `~(val (num_blocks:int64) < 16)` ASSUME_TAC THENL + [ SUBGOAL_THEN `~(val (len:int64) < 16)` MP_TAC THENL + [ASM_ARITH_TAC; ALL_TAC] THEN + UNDISCH_TAC `word_and len (word 0xfffffffffffffff0) = (num_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `num_blocks:int64`] NUM_BLOCKS_LO_BOUND_1BLOCK_THM) THEN + SIMP_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks:int64) <= 2 EXP 24` ASSUME_TAC THENL + [ UNDISCH_TAC `val (len:int64) <= 2 EXP 24` THEN + UNDISCH_TAC `word_and len (word 0xfffffffffffffff0) = (num_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `num_blocks:int64`] NUM_BLOCKS_HI_BOUND_THM) THEN + SIMP_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_blocks_adjusted:int64) < 0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (num_blocks:int64) < 16)` THEN + UNDISCH_TAC `(if val (tail_len:int64) = 0x0 + then (num_blocks:int64) + else word_sub num_blocks (word 0x10)) = + num_blocks_adjusted` THEN + MP_TAC (SPECL [`num_blocks:int64`;`tail_len:int64`;`num_blocks_adjusted:int64`] + NUM_BLOCKS_ADJUSTED_LO_BOUND_1BLOCK_THM) THEN SIMP_TAC[] + ; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) <= 2 EXP 24` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_blocks:int64) <= 2 EXP 24` THEN + UNDISCH_TAC `~(val (num_blocks:int64) < 16)` THEN + UNDISCH_TAC `(if val (tail_len:int64) = 0x0 + then (num_blocks:int64) + else word_sub num_blocks (word 0x10)) = + num_blocks_adjusted` THEN + MP_TAC (SPECL [`num_blocks:int64`;`tail_len:int64`;`num_blocks_adjusted:int64`] + NUM_BLOCKS_ADJUSTED_HI_BOUND_THM) THEN SIMP_TAC[] + ; ALL_TAC] THEN + SUBGOAL_THEN `val (tail_len:int64) < 16` ASSUME_TAC THENL + [ EXPAND_TAC "tail_len" THEN + REWRITE_TAC[ARITH_RULE `0xf = 2 EXP 4 - 1`] THEN + REWRITE_TAC[VAL_WORD_AND_MASK_WORD] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SIMP_TAC[MOD_LT_EQ] THEN + CONV_TAC NUM_REDUCE_CONV + ; ALL_TAC] THEN + (* relationship between variables *) + SUBGOAL_THEN `val (num_blocks:int64) <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks" THEN SIMP_TAC[NUM_BLOCKS_LT_LEN_THM]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + COND_CASES_TAC THENL + [ ASM_SIMP_TAC[]; + UNDISCH_TAC `~(val (num_blocks:int64) < 16)` THEN + UNDISCH_TAC `word_and (len:int64) (word 0xfffffffffffffff0) = (num_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `num_blocks:int64`] NUM_BLOCKS_ADJUSTED_LT_LEN_THM) THEN + SIMP_TAC[]]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + REWRITE_TAC [VAL_WORD; DIMINDEX_64] THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + REWRITE_TAC [VAL_WORD; DIMINDEX_64] THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= val (len:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + + (* Prove more properties about num_blocks_adjusted and num_5blocks_adjusted *) + SUBGOAL_THEN `val (num_blocks_adjusted:int64) DIV 0x50 = val (num_5blocks_adjusted:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `0x10 divides val (num_blocks_adjusted:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + EXPAND_TAC "num_blocks" THEN + COND_CASES_TAC THENL + [ REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT; DIVIDES_RMUL; DIVIDES_REFL] THEN + MP_TAC (SPEC `len:int64` VAL_BOUND_64) THEN + ARITH_TAC; + + IMP_REWRITE_TAC[NUM_BLOCKS_MINUS1_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT; DIVIDES_RMUL; DIVIDES_REFL] THEN + MP_TAC (SPEC `len:int64` VAL_BOUND_64) THEN + ARITH_TAC]; ALL_TAC] THEN + + (* If no tail, execute to the end *) + ASM_CASES_TAC `val (tail_len:int64) = 0` THENL + [ + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--2) THEN + (* Discharge if condition *) + SUBGOAL_THEN `val (word_and (tail_len:int64) (word 0xf)) = 0x0` MP_TAC THENL + [ UNDISCH_TAC `val (tail_len:int64) = 0x0` THEN BITBLAST_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + + SUBGOAL_THEN `val (word (acc_len (num_5blocks_adjusted:int64) (num_blocks_adjusted:int64)):int64) = + acc_len num_5blocks_adjusted num_blocks_adjusted` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + MP_TAC (SPECL [`num_5blocks_adjusted:int64`; `num_blocks_adjusted:int64`; `2 EXP 64`] + BOUND_OF_ACC_LEN) THEN + ANTS_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[]; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + (* Prove that acc_len is equal to total len because there is no tail *) + SUBGOAL_THEN `val (len:int64) = + acc_len (num_5blocks_adjusted:int64) (num_blocks_adjusted:int64)` SUBST1_TAC THENL + [ SUBGOAL_THEN `len = (num_blocks:int64)` SUBST1_TAC THENL + [ EXPAND_TAC "len" THEN + SUBGOAL_THEN `tail_len:int64 = word 0` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM VAL_EQ_0] THEN ASM_REWRITE_TAC[]; ALL_TAC] THEN + REWRITE_TAC[ASSUME `tail_len:int64 = word 0`; WORD_ADD_0] + ; ALL_TAC] THEN + SUBGOAL_THEN `num_blocks = (num_blocks_adjusted:int64)` SUBST1_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + REWRITE_TAC[ASSUME `val (tail_len:int64) = 0`] + ; ALL_TAC] THEN + REWRITE_TAC[acc_len] THEN + REPEAT_N 4 (COND_CASES_TAC THENL[ASM_ARITH_TAC; ALL_TAC]) THEN + + CONV_TAC SYM_CONV THEN + REWRITE_TAC[ARITH_RULE `!a. 0x50 * a = a * 0x50`] THEN + MATCH_MP_TAC (SPECL [`val (num_blocks_adjusted:int64)`; `val (num_5blocks_adjusted:int64)`] DIVISION_BY_80_LEMMA) THEN + REPEAT CONJ_TAC THENL + [ + ASM_SIMP_TAC[]; + ASM_SIMP_TAC[]; + + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `~(val (num_5blocks_adjusted:int64) * 0x50 + 0x10 = val (num_blocks_adjusted:int64))` THEN + ARITH_TAC; + + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `~(val (num_5blocks_adjusted:int64) * 0x50 + 0x20 = val (num_blocks_adjusted:int64))` THEN + ARITH_TAC; + + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `~(val (num_5blocks_adjusted:int64) * 0x50 + 0x30 = val (num_blocks_adjusted:int64))` THEN + ARITH_TAC; + + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `~(val (num_5blocks_adjusted:int64) * 0x50 + 0x40 = val (num_blocks_adjusted:int64))` THEN + ARITH_TAC] + ; ALL_TAC] THEN + ASM_SIMP_TAC[] + ; ALL_TAC] THEN + + (* The cipher stealing branch *) + (* Break the rest of the program into two parts: before byte-swap and after. + This is because byte-swap needs another invariant proof. *) + ABBREV_TAC `curr_len = (acc_len (num_5blocks_adjusted:int64) (num_blocks_adjusted:int64)):num` THEN + ABBREV_TAC `curr_blocks = (acc_blocks (num_5blocks_adjusted:int64) (num_blocks_adjusted:int64) T):num` THEN + + SUBGOAL_THEN `curr_len + 0x10 <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "curr_len" THEN + MP_TAC (SPECL [`num_5blocks_adjusted:int64`; `num_blocks_adjusted:int64`] VALUE_OF_ACC_LEN) THEN + REPEAT_N 3 (ANTS_TAC THENL [ASM_ARITH_TAC ORELSE ASM_SIMP_TAC[]; ALL_TAC]) THEN + SIMP_TAC[] THEN DISCH_TAC THEN + EXPAND_TAC "num_blocks_adjusted" THEN + SIMP_TAC[ASSUME `~(val (tail_len:int64) = 0)`] THEN + UNDISCH_TAC `val (num_blocks:int64) <= val (len:int64)` THEN + SUBGOAL_THEN `val (num_blocks:int64) >= 16` MP_TAC THENL + [ASM_ARITH_TAC; ALL_TAC] THEN + WORD_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val ((word curr_len):int64) = curr_len` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + EXPAND_TAC "curr_len" THEN + MP_TAC (SPECL [`num_5blocks_adjusted:int64`; `num_blocks_adjusted:int64`; `2 EXP 64`] + BOUND_OF_ACC_LEN) THEN + ANTS_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[]; ALL_TAC] THEN + + ENSURES_SEQUENCE_TAC `pc + 0xab8` + `\s. + read X0 s = word_add (word_add ct_ptr (word curr_len)) (word 0x10) /\ + read X1 s = word_add pt_ptr (word curr_len) /\ + read X21 s = tail_len /\ + read Q6 s = calculate_tweak curr_blocks iv key2 /\ + read Q16 s = k00 /\ read Q17 s = k01 /\ read Q12 s = k02 /\ read Q13 s = k03 /\ + read Q14 s = k04 /\ read Q15 s = k05 /\ read Q4 s = k06 /\ read Q5 s = k07 /\ + read Q18 s = k08 /\ read Q19 s = k09 /\ read Q20 s = k0a /\ read Q21 s = k0b /\ + read Q22 s = k0c /\ read Q23 s = k0d /\ read Q7 s = k0e /\ + + byte_list_at ct ct_ptr len s /\ + byte_list_at (aes256_xts_decrypt ct curr_len iv key1 key2) pt_ptr (word curr_len) s /\ + read (memory :> bytes128 (word_add pt_ptr (word curr_len))) s = + aes256_xts_decrypt_round + (bytes_to_int128 (SUB_LIST (curr_len,0x10) ct)) + (calculate_tweak (curr_blocks + 0x1) iv key2) + key1` THEN + CONJ_TAC THENL + [ + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes128 (word_add pt_ptr (word curr_len))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + UNDISCH_THEN `val ((word curr_len):int64) = curr_len` + (fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN REWRITE_TAC[th]) THEN + + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--2) THEN + + (* Discharge if condition *) + SUBGOAL_THEN `~(val (word_and (tail_len:int64) (word 0xf)) = 0x0)` MP_TAC THENL + [ UNDISCH_TAC `~(val (tail_len:int64) = 0x0)` THEN + UNDISCH_TAC `val (tail_len:int64) < 16` THEN + MP_TAC (SPEC `tail_len:int64` WORD_AND_MASK16_EQ_0) THEN + SIMP_TAC[]; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + (* Decrypt last block *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (3--11) THEN + TWEAK_TAC `Q8:(armstate,int128)component` `(curr_blocks + 1):num` `curr_blocks:num` THEN + MP_TAC (SPECL [`ct_ptr:int64`; `curr_len:num`; `len:int64`; `ct:byte list`; `s11:armstate`] READ_LAST_LEMMA) THEN + ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (12--42) THEN + XTSDEC_TAC `Q26:(armstate,int128)component` `curr_len:num` `(curr_blocks + 1):num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (43--43) THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] + ; ALL_TAC + ] THEN + + ABBREV_TAC `PP = aes256_xts_decrypt_round + (bytes_to_int128 (SUB_LIST (curr_len,0x10) (ct:byte list))) + (calculate_tweak (curr_blocks + 0x1) (iv:int128) (key2:int128 list)) + (key1:int128 list)` THEN + SUBGOAL_THEN `curr_len + 16 + val (tail_len:int64) = val (len:int64)` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM (ASSUME `acc_len num_5blocks_adjusted num_blocks_adjusted = curr_len`)] THEN + MP_TAC (SPECL [`num_5blocks_adjusted:int64`; `num_blocks_adjusted:int64`] VALUE_OF_ACC_LEN) THEN + ANTS_TAC THENL[ASM_ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL[ASM_ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL[ASM_SIMP_TAC[]; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + EXPAND_TAC "num_blocks_adjusted" THEN + UNDISCH_TAC `~(val (tail_len:int64) = 0)` THEN + SIMP_TAC[] THEN DISCH_TAC THEN + ASM_SIMP_TAC[VAL_WORD_SUB; DIMINDEX_64; VAL_WORD; + ARITH_RULE `16 MOD 2 EXP 64 = 16`] THEN + MP_TAC (SPECL [`val (num_blocks:int64)`; `0x2 EXP 0x40`; `16`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL [ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; `val (num_blocks:int64) - 16`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + SIMP_TAC[ARITH_RULE `!x. 1 * x = x`] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[MOD_LT] THEN + CONJ_TAC THENL [ + SUBGOAL_THEN `val (num_blocks:int64) - 0x10 + 0x10 + val (tail_len:int64) + = val num_blocks + val tail_len` SUBST1_TAC THENL + [ IMP_REWRITE_TAC[ADD_ASSOC; SUB_ADD] THEN ASM_ARITH_TAC; ALL_TAC] THEN + EXPAND_TAC "len" THEN + REWRITE_TAC[VAL_WORD_ADD] THEN + IMP_REWRITE_TAC[MOD_LT; DIMINDEX_64] THEN + CONJ_TAC THENL [ARITH_TAC; ASM_ARITH_TAC]; + ALL_TAC + ] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + (* Invariant proof for .composite_dec_loop *) + (* Invariant: + X0 points to tail of ct + X1 points to starting of last full block of pt + X13 points to tail of pt + X20 points to tail of ct + X21 holds decreasing tail_len + Q6 holds second to last tweak + Q16 ... Q7 holds the key schedule for encryption + + Memory: ct_ptr points to the input + Memory: Up to the second to last block, the output matches the specification + Memory: For the last block, for each byte + [0,i) -- previous decryption result + [i,tail_len) -- equal corresponding ct tail bytes, Cm + [tail_len,16] -- previous decryption result + Memory: For the tail, for each byte + [i,tail_len) -- copied over from Pm block + *) + ENSURES_WHILE_PADOWN_TAC + `val (tail_len:int64)` + `0` + `pc + 0xac0` + `pc + 0xad4` + `\i s. + ( read X0 s = word_add (word_add ct_ptr (word curr_len)) (word 0x10) /\ + read X1 s = word_add pt_ptr (word curr_len) /\ + read X13 s = word_add (word_add pt_ptr (word curr_len)) (word 0x10) /\ + read X20 s = word_add (word_add ct_ptr (word curr_len)) (word 0x10) /\ + read X21 s = (word i):int64 /\ + read Q6 s = calculate_tweak curr_blocks iv key2 /\ + read Q16 s = k00 /\ read Q17 s = k01 /\ read Q12 s = k02 /\ read Q13 s = k03 /\ + read Q14 s = k04 /\ read Q15 s = k05 /\ read Q4 s = k06 /\ read Q5 s = k07 /\ + read Q18 s = k08 /\ read Q19 s = k09 /\ read Q20 s = k0a /\ read Q21 s = k0b /\ + read Q22 s = k0c /\ read Q23 s = k0d /\ read Q7 s = k0e /\ + byte_list_at ct ct_ptr len s /\ + byte_list_at (aes256_xts_decrypt ct curr_len iv key1 key2) pt_ptr (word curr_len) s /\ + + read (memory :> bytes128 (word_add pt_ptr (word curr_len))) s = + cipher_stealing_inv i curr_len (val (tail_len:int64)) PP ct /\ + + byte_list_at (SUB_LIST (i, val tail_len - i) (int128_to_bytes PP)) + (word_add pt_ptr (word (curr_len + 0x10 + i))) + (word ((val tail_len) - i)) s) /\ + // loop backedge condition + (read ZF s <=> i = 0) /\ + (read NF s <=> ival ((word i):int64) < &0) /\ + (read VF s <=> ~(ival ((word (i + 1)):int64) - &1 = ival ((word i):int64)))` THEN + ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL + [ + (* Subgoal1: 0 < val tail_len *) + ASM_ARITH_TAC; + + (* Subgoal2: invariant holds before entering loop *) + REWRITE_TAC[byte_list_at] THEN + UNDISCH_THEN `val ((word curr_len):int64) = curr_len` + (fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN REWRITE_TAC[th]) THEN + + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--2) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + REWRITE_TAC[WORD_VAL]; + + REWRITE_TAC[cipher_stealing_inv; SUB_REFL] THEN + SUBGOAL_THEN `SUB_LIST (val (tail_len:int64),0x0) (SUB_LIST (curr_len + 16,val tail_len) (ct:byte list)) = []` SUBST1_TAC THENL + [ REWRITE_TAC[SUB_LIST_CLAUSES]; ALL_TAC] THEN + REWRITE_TAC[CONJUNCT1 APPEND] THEN + SUBGOAL_THEN `APPEND (SUB_LIST (0x0,val (tail_len:int64)) (int128_to_bytes PP)) + (SUB_LIST (val tail_len,0x10 - val tail_len) (int128_to_bytes PP)) = + (int128_to_bytes PP)` SUBST1_TAC THENL + [ MP_TAC (ISPECL [`int128_to_bytes PP`; `val (tail_len:int64)`; `16 - val (tail_len:int64)`; `0`] (GSYM SUB_LIST_SPLIT)) THEN + IMP_REWRITE_TAC[ADD_CLAUSES; ARITH_RULE `!x. x < 16 ==> x + 16 - x = 16`] THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES; LENGTH_OF_INT128_TO_BYTES] + ; ALL_TAC] THEN + REWRITE_TAC[BYTES_TO_INT128_OF_INT128_TO_BYTES]; + + REWRITE_TAC[VAL_WORD_0] THEN ARITH_TAC + ]; + + (* Subgoal 3: inductive step *) + REPEAT STRIP_TAC THEN + + (* For non-overlapping and MAYCHANGE address reasoning *) + SUBGOAL_THEN `curr_len + 16 + i < val (len:int64)` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM (ASSUME `acc_len num_5blocks_adjusted num_blocks_adjusted = curr_len`)] THEN + MP_TAC (SPECL [`num_5blocks_adjusted:int64`; `num_blocks_adjusted:int64`] VALUE_OF_ACC_LEN) THEN + REPEAT_N 3 (ANTS_TAC THENL [ASM_ARITH_TAC ORELSE ASM_SIMP_TAC[]; ALL_TAC]) THEN + SIMP_TAC[] THEN DISCH_TAC THEN + EXPAND_TAC "num_blocks_adjusted" THEN + SIMP_TAC[ASSUME `~(val (tail_len:int64) = 0)`] THEN + REWRITE_TAC[VAL_WORD_SUB; DIMINDEX_64] THEN + MP_TAC (SPECL [`val (num_blocks:int64)`; `0x2 EXP 0x40`; `val ((word 0x10):int64)`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN ASM_ARITH_TAC + ; ALL_TAC] THEN + ANTS_TAC THENL [ WORD_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; `val (num_blocks:int64) - val ((word 0x10):int64)`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + SIMP_TAC[ARITH_RULE `!x. 1 * x = x`] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[MOD_LT] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + EXPAND_TAC "len" THEN + IMP_REWRITE_TAC[VAL_WORD_ADD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (num_blocks:int64) <= val (len:int64)` THEN + UNDISCH_TAC `~(val (num_blocks:int64) < 16)` THEN + UNDISCH_TAC `val (num_blocks:int64) <= 0x2 EXP 0x18` THEN + UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + ARITH_TAC + ; ALL_TAC] THEN + + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes8 (word_add pt_ptr (word (curr_len + 0x10 + i)))],, + MAYCHANGE [memory :> bytes8 (word_add pt_ptr (word (curr_len + i)))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + UNDISCH_THEN `val ((word curr_len):int64) = curr_len` + (fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN REWRITE_TAC[th]) THEN + ENSURES_INIT_TAC "s0" THEN + + SUBGOAL_THEN `val ((word (val (tail_len:int64) - i)):int64) = val tail_len - i` SUBST_ALL_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val ((word (val (tail_len:int64) - (i + 0x1))):int64) = val tail_len - (i + 1)` SUBST_ALL_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `word_sub ((word (i + 0x1)):int64) (word 0x1) = word i` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM VAL_EQ; VAL_WORD_SUB; DIMINDEX_64] THEN + MP_TAC (SPECL [`val ((word (i + 0x1)):int64)`; `0x2 EXP 0x40`; `val ((word 0x1):int64)`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN ASM_ARITH_TAC + ; ALL_TAC] THEN + ANTS_TAC THENL [ WORD_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; `val ((word (i + 0x1)):int64) - val ((word 0x1):int64)`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + SIMP_TAC[ARITH_RULE `!x. 1 * x = x`] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[MOD_LT] THEN + CONJ_TAC THENL + [ SUBGOAL_THEN `i + 1 < 2 EXP 64` MP_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + ARITH_TAC; + UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + WORD_ARITH_TAC] + ; ALL_TAC] THEN + + MP_TAC (SPECL [`(word_add pt_ptr (word curr_len)):int64`; `word i:int64`; `s0:armstate`; + `(cipher_stealing_inv (i + 0x1) curr_len (val (tail_len:int64)) PP ct):int128`] + SELECT_ONE_BYTE_FROM_BLOCK) THEN + + SUBGOAL_THEN `val ((word i):int64) < 0x10` ASSUME_TAC THENL + [ UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + WORD_ARITH_TAC; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + REPEAT STRIP_TAC THEN + + MP_TAC (SPECL [`ct_ptr:int64`; `len:int64`; + `(word_add (word (curr_len + 0x10)) (word i)):int64`; + `ct:byte list`; `s0:armstate`] SELECT_ONE_BYTE_FROM_FORALL) THEN + SUBGOAL_THEN `val (word_add ((word (curr_len + 0x10)):int64) (word i)) < val (len:int64)` ASSUME_TAC THENL + [ REWRITE_TAC[WORD_RULE `!a b. word_add ((word a):int64) (word b) = word (a + b)`] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + STRIP_TAC THEN + + (* Break the `read (memory :> bytes128 (word_add pt_ptr (word curr_len))) s0 + into bytes using BREAK_ONE_BLOCK_INTO_BYTES *) + MP_TAC (SPECL [`(word_add pt_ptr (word curr_len)):int64`; `s0:armstate`; + `(cipher_stealing_inv (i + 0x1) curr_len (val (tail_len:int64)) PP ct):int128`] + BREAK_ONE_BLOCK_INTO_BYTES) THEN + ASM_SIMP_TAC[] THEN REPEAT STRIP_TAC THEN + + (* For address matching when symbolic simulation *) + SUBGOAL_THEN `word_add (ct_ptr:int64) (word_add (word (curr_len + 0x10)) (word i)) = + word_add ct_ptr (word (curr_len + 16 + i))` SUBST_ALL_TAC THENL + [ REWRITE_TAC[WORD_RULE `!a b. word_add ((word a):int64) (word b) = word (a + b)`; ADD_ASSOC] + ; ALL_TAC] THEN + SUBGOAL_THEN `!x. word_add (word_add (pt_ptr:int64) (word curr_len)) (word x) = + word_add pt_ptr (word (curr_len + x))` ASSUME_TAC THENL + [ GEN_TAC THEN REWRITE_TAC[ + WORD_RULE `!(a:int64) b c. word_add (word_add a b) c = word_add a (word_add b c)`; + WORD_RULE `!a b. word_add ((word a):int64) (word b) = word (a + b)`] + ; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + (* case analysis based on i = 0 ... 14, because symbolic execution + needs to know which byte is being overwritten in pt_ptr to properly update the state. *) + MAP_EVERY (fun i -> TAIL_SWAP_ASM_CASES_TAC (mk_numeral (num i))) (0--14) THEN + UNDISCH_TAC `15 <= i` THEN + UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 16` THEN + ARITH_TAC; + + (* Subgoal 4: *) + REPEAT STRIP_TAC THEN + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--1) THEN + SUBGOAL_THEN `ival ((word i):int64) < &0x0 <=> + ~(ival ((word (i + 0x1)):int64) - &0x1 = ival ((word i):int64))` ASSUME_TAC THENL + [ SUBGOAL_THEN `ival ((word i):int64) = &i` ASSUME_TAC THENL + [ MATCH_MP_TAC IVAL_WORD_LT THEN + UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `ival ((word (i + 0x1)):int64) = &(i + 1)` ASSUME_TAC THENL + [ MATCH_MP_TAC IVAL_WORD_LT THEN + UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_SIMP_TAC[]; + + (* Subgoal 5: *) + REPEAT STRIP_TAC THEN + REWRITE_TAC[byte_list_at] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[cipher_stealing_inv; CONJUNCT1 SUB_LIST; CONJUNCT1 APPEND] THEN + REWRITE_TAC[SUB_0] THEN + ASM_REWRITE_TAC[] THEN + SUBGOAL_THEN `val ((word (val (tail_len:int64))):int64) = val tail_len` SUBST1_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `(SUB_LIST (0x0,val (tail_len:int64)) (SUB_LIST (curr_len + 16,val tail_len) (ct:byte list))) = + (SUB_LIST (curr_len + 16,val tail_len) ct)` SUBST1_TAC THENL + [ IMP_REWRITE_TAC[SUB_LIST_REFL] THEN + ASM_REWRITE_TAC[LENGTH_SUB_LIST; MIN] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes128 (word_add pt_ptr (word curr_len))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + ENSURES_INIT_TAC "s0" THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--32) THEN + ABBREV_TAC `combinedPP = bytes_to_int128 + (APPEND (SUB_LIST (curr_len + 16,val (tail_len:int64)) (ct:byte list)) + (SUB_LIST (val tail_len,0x10 - val tail_len) + (int128_to_bytes (PP:int128))))` THEN + FIRST_X_ASSUM(MP_TAC o SPEC `aes256_xts_decrypt_round combinedPP + (calculate_tweak curr_blocks iv key2) key1` o MATCH_MP (MESON[] + `read (Q26:(armstate,int128)component) (s:armstate) = a ==> !a'. a = a' ==> read Q26 s = a'`)) THEN + ANTS_TAC THENL + [ EXPAND_TAC "key1" THEN + CONV_TAC (RAND_CONV ( + REWRITE_CONV [aes256_xts_decrypt_round] THENC + DEPTH_CONV let_CONV)) THEN + AESDEC_TAC; DISCH_TAC ] THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (33--33) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_SIMP_TAC[] THEN + + UNDISCH_THEN `curr_len + 16 + val (tail_len:int64) = val (len:int64)` + (fun th -> SUBST1_TAC (GSYM th)) THEN + SUBGOAL_THEN `curr_len = 16 * curr_blocks` SUBST_ALL_TAC THENL + [ REWRITE_TAC[GSYM (ASSUME `acc_len num_5blocks_adjusted num_blocks_adjusted = curr_len`)] THEN + EXPAND_TAC "curr_blocks" THEN + REWRITE_TAC[acc_len; acc_blocks] THEN + COND_CASES_TAC THENL [SIMP_TAC[] THEN ARITH_TAC; ALL_TAC] THEN SIMP_TAC[] THEN + COND_CASES_TAC THENL [SIMP_TAC[] THEN ARITH_TAC; ALL_TAC] THEN SIMP_TAC[] THEN + COND_CASES_TAC THENL [SIMP_TAC[] THEN ARITH_TAC; ALL_TAC] THEN SIMP_TAC[] THEN + COND_CASES_TAC THENL [SIMP_TAC[] THEN ARITH_TAC; ALL_TAC] THEN SIMP_TAC[] THEN + ARITH_TAC; ALL_TAC] THEN + + MATCH_MP_TAC BREAK_DATA_INTO_PARTS_DECRYPT THEN + REPEAT CONJ_TAC THENL + [ + (* 0. Trivial *) + IMP_REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT] THEN ARITH_TAC; + + (* 1. Result correct up to curr_len *) + UNDISCH_TAC `forall i. + i < 16 * curr_blocks + ==> read (memory :> bytes8 (word_add (pt_ptr:int64) (word i))) s33 = + EL i (aes256_xts_decrypt (ct:byte list) (16 * curr_blocks) (iv:int128) + (key1:int128 list) (key2:int128 list))` THEN + MP_TAC (SPECL [`16 * curr_blocks:num`; `pt_ptr:int64`; + `(aes256_xts_decrypt ct (16 * curr_blocks + 0x10 + val (tail_len:int64)) iv key1 key2):byte list`; + `s33:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + IMP_REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT] THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + MP_TAC (SPECL [`16 * curr_blocks:num`; `pt_ptr:int64`; + `(aes256_xts_decrypt ct (16 * curr_blocks) iv key1 key2):byte list`; + `s33:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + AP_TERM_TAC THEN + MP_TAC (SPECL [`curr_blocks:num`; `ct:byte list`; `iv:int128`; + `key1:int128 list`; `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT] THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES]; + + (* 2. Last full block is correct *) + MP_TAC (SPECL [`16:num`; `(word_add pt_ptr (word (0x10 * curr_blocks))):int64`; + `(SUB_LIST (0x10 * curr_blocks,0x10 + val (tail_len:int64)) + (aes256_xts_decrypt ct (0x10 * curr_blocks + 0x10 + val tail_len) + iv key1 key2)):byte list`; + `s33:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[LENGTH_SUB_LIST] THEN + IMP_REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT] THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + (* Proving last full block correct *) + REWRITE_TAC[READ_MEMORY_BYTES_BYTES128] THEN + ASM_REWRITE_TAC[] THEN + REWRITE_TAC[SUB_LIST_MIN_RIGHT; MIN] THEN + SIMP_TAC[ARITH_RULE `!x. 0x10 <= 0x10 + x`] THEN + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `!x y. ~(x + 16 + y < 16)`] THEN + REWRITE_TAC[ARITH_RULE `0x10 * curr_blocks + 0x10 + val tail_len = + 0x10 * (curr_blocks + 1) + val tail_len`] THEN + REWRITE_TAC[MOD_MULT_ADD] THEN + ASM_SIMP_TAC[MOD_LT] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[ARITH_RULE + `((0x10 * (curr_blocks + 0x1) + val tail_len) - val tail_len) DIV 0x10 = + (0x10 * (curr_blocks + 0x1)) DIV 0x10`] THEN + IMP_REWRITE_TAC[DIV_MULT; ARITH_RULE `~(16 = 0)`] THEN + COND_CASES_TAC THENL + [ + SUBGOAL_THEN `curr_blocks = 0` SUBST_ALL_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + EXPAND_TAC "combinedPP" THEN + REWRITE_TAC[aes256_xts_decrypt_tail] THEN + ASM_SIMP_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [`(SUB_LIST (0,0x10) ct):byte list`; + `(SUB_LIST (0x10,val (tail_len:int64)) ct):byte list`; + `val (tail_len:int64)`; `iv:int128`; `0:num`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_FST_OF_CIPHER_STEALING) THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_LEFT; ARITH_RULE `16 <= 16`] THEN + + REWRITE_TAC[cipher_stealing; LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[SUB_LIST_OF_INT128_TO_BYTES; + NUM_OF_BYTELIST_OF_INT128_TO_BYTES; CALCULATE_TWEAK_EXPAND] THEN + EXPAND_TAC "combinedPP" THEN + EXPAND_TAC "PP" THEN + CONV_TAC NUM_REDUCE_CONV; + ALL_TAC + ] THEN + + SUBGOAL_THEN `curr_blocks >= 1` ASSUME_TAC THENL + [ UNDISCH_TAC `~(curr_blocks + 0x1 < 0x2)` THEN ARITH_TAC; ALL_TAC] THEN + + IMP_REWRITE_TAC[ADD_SUB; ARITH_RULE `((curr_blocks + 0x1) - 0x2) = curr_blocks - 1`] THEN + + MP_TAC (SPECL [`0:num`; `(curr_blocks - 1):num`; `ct:byte list`; `iv:int128`; + `key1:int128 list`; `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + ASM_SIMP_TAC[ARITH_RULE `curr_blocks >= 1 ==> ~(curr_blocks - 1 < 0)`] THEN + IMP_REWRITE_TAC[SUB_0; ARITH_RULE `curr_blocks >= 1 ==> curr_blocks - 1 + 1 = curr_blocks`] THEN + ONCE_REWRITE_TAC[ARITH_RULE `curr_blocks * 16 = 16 * curr_blocks`] THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN + + REWRITE_TAC[aes256_xts_decrypt_tail] THEN + ASM_SIMP_TAC[LET_DEF; LET_END_DEF] THEN + + MP_TAC (SPECL [`(SUB_LIST (curr_blocks * 0x10,0x10) ct):byte list`; + `(SUB_LIST ((curr_blocks + 0x1) * 0x10,val (tail_len:int64)) ct):byte list`; + `val (tail_len:int64)`; `iv:int128`; `curr_blocks:num`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_FST_OF_CIPHER_STEALING) THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_LEFT; ARITH_RULE `16 <= 16`] THEN + + REWRITE_TAC[cipher_stealing; LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[SUB_LIST_OF_INT128_TO_BYTES; + NUM_OF_BYTELIST_OF_INT128_TO_BYTES; CALCULATE_TWEAK_EXPAND; + ARITH_RULE `curr_blocks * 16 = 16 * curr_blocks`; + ARITH_RULE `0x10 * (curr_blocks + 0x1) = 16 * curr_blocks + 16`] THEN + EXPAND_TAC "combinedPP" THEN + EXPAND_TAC "PP" THEN + REFL_TAC; + + (* 3. Proving tail is correct *) + UNDISCH_TAC + `forall i. i < val (tail_len:int64) + ==> read (memory :> bytes8 + (word_add (word_add pt_ptr (word (0x10 * curr_blocks + 0x10))) + (word i))) s33 = + EL i (SUB_LIST (0x0,val tail_len) (int128_to_bytes PP))` THEN + MP_TAC (SPECL [`val (tail_len:int64):num`; `(word_add pt_ptr (word (0x10 * curr_blocks + 0x10))):int64`; + `(SUB_LIST (0x0,val (tail_len:int64)) (int128_to_bytes PP)):byte list`; + `s33:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + MP_TAC (SPECL [`val (tail_len:int64):num`; `(word_add pt_ptr (word (0x10 * curr_blocks + 0x10))):int64`; + `(SUB_LIST (0x10 * curr_blocks + 0x10,val (tail_len:int64)) + (aes256_xts_decrypt ct (0x10 * curr_blocks + 0x10 + val tail_len) iv key1 key2)):byte list`; + `s33:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[LENGTH_SUB_LIST] THEN + IMP_REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT] THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + AP_TERM_TAC THEN + REWRITE_TAC[SUB_LIST_IDEMPOTENT] THEN + REWRITE_TAC[SUB_LIST_MIN_RIGHT; MIN; LE_REFL] THEN + + REWRITE_TAC[aes256_xts_decrypt; + ARITH_RULE `~(0x10 * curr_blocks + 0x10 + val (tail_len:int64) < 0x10)`] THEN + REWRITE_TAC[ARITH_RULE `0x10 * curr_blocks + 0x10 + val tail_len = + 0x10 * (curr_blocks + 1) + val tail_len`] THEN + REWRITE_TAC[MOD_MULT_ADD] THEN + ASM_SIMP_TAC[MOD_LT] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[ARITH_RULE + `((0x10 * (curr_blocks + 0x1) + val tail_len) - val tail_len) DIV 0x10 = + (0x10 * (curr_blocks + 0x1)) DIV 0x10`] THEN + IMP_REWRITE_TAC[DIV_MULT; ARITH_RULE `~(16 = 0)`] THEN + COND_CASES_TAC THENL + [ + SUBGOAL_THEN `curr_blocks = 0` SUBST_ALL_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[aes256_xts_decrypt_tail] THEN + ASM_SIMP_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [`(SUB_LIST (0,0x10) ct):byte list`; + `(SUB_LIST (0x10,val (tail_len:int64)) ct):byte list`; + `val (tail_len:int64)`; `iv:int128`; `0:num`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_FST_OF_CIPHER_STEALING) THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA; ARITH_RULE `16 <= 16`] THEN + + REWRITE_TAC[cipher_stealing; LET_DEF; LET_END_DEF; SUB_LIST_IDEMPOTENT] THEN + EXPAND_TAC "PP" THEN + REWRITE_TAC[CALCULATE_TWEAK_EXPAND] THEN + CONV_TAC NUM_REDUCE_CONV; + ALL_TAC + ] THEN + + SUBGOAL_THEN `curr_blocks >= 1` ASSUME_TAC THENL + [ UNDISCH_TAC `~(curr_blocks + 0x1 < 0x2)` THEN ARITH_TAC; ALL_TAC] THEN + + IMP_REWRITE_TAC[ADD_SUB; ARITH_RULE `((curr_blocks + 0x1) - 0x2) = curr_blocks - 1`] THEN + + MP_TAC (ISPECL [`(aes256_xts_decrypt_rec 0x0 (curr_blocks - 0x1) ct iv key1 key2):byte list`; + `(aes256_xts_decrypt_tail curr_blocks (val (tail_len:int64)) ct iv key1 key2):byte list`; + `0x10 * curr_blocks + 0x10:num`; `val (tail_len:int64)`; `0x10 * curr_blocks:num` + ] SUB_LIST_APPEND_RIGHT_GENERAL) THEN + ANTS_TAC THENL + [ REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_REC] THEN + UNDISCH_TAC `curr_blocks >= 1` THEN + ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL [ ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + REWRITE_TAC[ARITH_RULE `(0x10 * curr_blocks + 0x10) - 0x10 * curr_blocks = 0x10`] THEN + REWRITE_TAC[aes256_xts_decrypt_tail] THEN + ASM_SIMP_TAC[LET_DEF; LET_END_DEF] THEN + + MP_TAC (SPECL [`(SUB_LIST (curr_blocks * 0x10,0x10) ct):byte list`; + `(SUB_LIST ((curr_blocks + 0x1) * 0x10,val (tail_len:int64)) ct):byte list`; + `val (tail_len:int64)`; `iv:int128`; `curr_blocks:num`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_FST_OF_CIPHER_STEALING) THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA; ARITH_RULE `16 <= 16`] THEN + + REWRITE_TAC[cipher_stealing; LET_DEF; LET_END_DEF; SUB_LIST_IDEMPOTENT] THEN + EXPAND_TAC "PP" THEN + REWRITE_TAC[ARITH_RULE `curr_blocks * 0x10 = 0x10 * curr_blocks`; + CALCULATE_TWEAK_EXPAND] + ] + ] +);; + +let CIPHER_STEALING_SAFE = time prove( + `exists f_events. + forall ct_ptr pt_ptr key1_ptr len pc + tail_len num_blocks num_blocks_adjusted num_5blocks_adjusted. + nonoverlapping (word pc, LENGTH aes_xts_decrypt_mc) (pt_ptr, val len) + /\ nonoverlapping (ct_ptr, val len) (pt_ptr, val len) + /\ nonoverlapping (key1_ptr, 260) (pt_ptr, val len) + /\ val len >= 16 /\ val len <= 2 EXP 24 + /\ word_add tail_len num_blocks = len + /\ word_and len (word 0xfffffffffffffff0) = num_blocks + /\ word_and len (word 0xf) = tail_len + /\ (if val tail_len = 0x0 then num_blocks else word_sub num_blocks (word 0x10)) = num_blocks_adjusted + /\ word (val num_blocks_adjusted DIV 0x50) = num_5blocks_adjusted + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes_xts_decrypt_mc /\ + read PC s = word (pc + 0xa0c) /\ + read X0 s = word_add ct_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X1 s = word_add pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X3 s = key1_ptr /\ + read X21 s = tail_len /\ + read X19 s = word 0x87 /\ + read events s = e) + (\s. read PC s = word (pc + 0xb58) /\ + exists e2. + read events s = APPEND e2 e /\ + e2 = f_events ct_ptr pt_ptr key1_ptr tail_len num_blocks_adjusted + num_5blocks_adjusted pc /\ + memaccess_inbounds e2 + [(ct_ptr, val len); (pt_ptr, val len); (key1_ptr, 260)] + [(pt_ptr, val len)]) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes(pt_ptr, val len)])`, + + CONCRETIZE_F_EVENTS_TAC + `\(ct_ptr:int64) (pt_ptr:int64) (key1_ptr:int64) (tail_len:int64) + (num_blocks_adjusted:int64) (num_5blocks_adjusted:int64) (pc:num). + if val (tail_len) = 0 then + f_ev_short ct_ptr pt_ptr key1_ptr tail_len num_blocks_adjusted + num_5blocks_adjusted pc + else + APPEND + (APPEND + (f_ev_epil ct_ptr pt_ptr key1_ptr tail_len num_blocks_adjusted + num_5blocks_adjusted pc) + (APPEND + (ENUMERATEL (val tail_len) + (f_ev_loop ct_ptr pt_ptr key1_ptr tail_len num_blocks_adjusted + num_5blocks_adjusted pc)) + (f_ev_prol ct_ptr pt_ptr key1_ptr tail_len num_blocks_adjusted + num_5blocks_adjusted pc)) + ) + (f_ev_pre ct_ptr pt_ptr key1_ptr tail_len num_blocks_adjusted + num_5blocks_adjusted pc) + :(uarch_event)list` THEN + REPEAT META_EXISTS_TAC THEN + + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + (* Prove once and for all the bounds for num_blocks, num_blocks_adjusted + and num_5blocks_adjusted *) + SUBGOAL_THEN `~(val (num_blocks:int64) < 16)` ASSUME_TAC THENL + [ SUBGOAL_THEN `~(val (len:int64) < 16)` MP_TAC THENL + [ASM_ARITH_TAC; ALL_TAC] THEN + UNDISCH_TAC `word_and len (word 0xfffffffffffffff0) = (num_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `num_blocks:int64`] NUM_BLOCKS_LO_BOUND_1BLOCK_THM) THEN + SIMP_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks:int64) <= 2 EXP 24` ASSUME_TAC THENL + [ UNDISCH_TAC `val (len:int64) <= 2 EXP 24` THEN + UNDISCH_TAC `word_and len (word 0xfffffffffffffff0) = (num_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `num_blocks:int64`] NUM_BLOCKS_HI_BOUND_THM) THEN + SIMP_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_blocks_adjusted:int64) < 0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (num_blocks:int64) < 16)` THEN + UNDISCH_TAC `(if val (tail_len:int64) = 0x0 + then (num_blocks:int64) + else word_sub num_blocks (word 0x10)) = + num_blocks_adjusted` THEN + MP_TAC (SPECL [`num_blocks:int64`;`tail_len:int64`;`num_blocks_adjusted:int64`] + NUM_BLOCKS_ADJUSTED_LO_BOUND_1BLOCK_THM) THEN SIMP_TAC[] + ; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) <= 2 EXP 24` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_blocks:int64) <= 2 EXP 24` THEN + UNDISCH_TAC `~(val (num_blocks:int64) < 16)` THEN + UNDISCH_TAC `(if val (tail_len:int64) = 0x0 + then (num_blocks:int64) + else word_sub num_blocks (word 0x10)) = + num_blocks_adjusted` THEN + MP_TAC (SPECL [`num_blocks:int64`;`tail_len:int64`;`num_blocks_adjusted:int64`] + NUM_BLOCKS_ADJUSTED_HI_BOUND_THM) THEN SIMP_TAC[] + ; ALL_TAC] THEN + SUBGOAL_THEN `val (tail_len:int64) < 16` ASSUME_TAC THENL + [ EXPAND_TAC "tail_len" THEN + REWRITE_TAC[ARITH_RULE `0xf = 2 EXP 4 - 1`] THEN + REWRITE_TAC[VAL_WORD_AND_MASK_WORD] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SIMP_TAC[MOD_LT_EQ] THEN + CONV_TAC NUM_REDUCE_CONV + ; ALL_TAC] THEN + (* relationship between variables *) + SUBGOAL_THEN `val (num_blocks:int64) <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks" THEN SIMP_TAC[NUM_BLOCKS_LT_LEN_THM]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + COND_CASES_TAC THENL + [ ASM_SIMP_TAC[]; + UNDISCH_TAC `~(val (num_blocks:int64) < 16)` THEN + UNDISCH_TAC `word_and (len:int64) (word 0xfffffffffffffff0) = (num_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `num_blocks:int64`] NUM_BLOCKS_ADJUSTED_LT_LEN_THM) THEN + SIMP_TAC[]]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + REWRITE_TAC [VAL_WORD; DIMINDEX_64] THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + REWRITE_TAC [VAL_WORD; DIMINDEX_64] THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= val (len:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + + (* Prove more properties about num_blocks_adjusted and num_5blocks_adjusted *) + SUBGOAL_THEN `val (num_blocks_adjusted:int64) DIV 0x50 = val (num_5blocks_adjusted:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `0x10 divides val (num_blocks_adjusted:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + EXPAND_TAC "num_blocks" THEN + COND_CASES_TAC THENL + [ REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT; DIVIDES_RMUL; DIVIDES_REFL] THEN + MP_TAC (SPEC `len:int64` VAL_BOUND_64) THEN + ARITH_TAC; + + IMP_REWRITE_TAC[NUM_BLOCKS_MINUS1_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT; DIVIDES_RMUL; DIVIDES_REFL] THEN + MP_TAC (SPEC `len:int64` VAL_BOUND_64) THEN + ARITH_TAC]; ALL_TAC] THEN + + (* If no tail, execute to the end *) + ASM_CASES_TAC `val (tail_len:int64) = 0` THENL + [ + ENSURES_INIT_TAC "s0" THEN + ARM_STEPS_TAC AES_XTS_DECRYPT_EXEC (1--2) THEN + (* Discharge if condition *) + SUBGOAL_THEN `val (word_and (tail_len:int64) (word 0xf)) = 0x0` MP_TAC THENL + [ UNDISCH_TAC `val (tail_len:int64) = 0x0` THEN BITBLAST_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + DISCHARGE_SAFETY_PROPERTY_TAC; + + ALL_TAC] THEN + + (* The cipher stealing branch *) + ASM_REWRITE_TAC[] THEN + (* Break the rest of the program into two parts: before byte-swap and after. + This is because byte-swap needs another invariant proof. *) + ABBREV_TAC `curr_len = (acc_len (num_5blocks_adjusted:int64) (num_blocks_adjusted:int64)):num` THEN + ABBREV_TAC `curr_blocks = (acc_blocks (num_5blocks_adjusted:int64) (num_blocks_adjusted:int64) T):num` THEN + + SUBGOAL_THEN `curr_len + 0x10 <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "curr_len" THEN + MP_TAC (SPECL [`num_5blocks_adjusted:int64`; `num_blocks_adjusted:int64`] VALUE_OF_ACC_LEN) THEN + REPEAT_N 3 (ANTS_TAC THENL [ASM_ARITH_TAC ORELSE ASM_SIMP_TAC[]; ALL_TAC]) THEN + SIMP_TAC[] THEN DISCH_TAC THEN + EXPAND_TAC "num_blocks_adjusted" THEN + SIMP_TAC[ASSUME `~(val (tail_len:int64) = 0)`] THEN + UNDISCH_TAC `val (num_blocks:int64) <= val (len:int64)` THEN + SUBGOAL_THEN `val (num_blocks:int64) >= 16` MP_TAC THENL + [ASM_ARITH_TAC; ALL_TAC] THEN + WORD_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val ((word curr_len):int64) = curr_len` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + EXPAND_TAC "curr_len" THEN + MP_TAC (SPECL [`num_5blocks_adjusted:int64`; `num_blocks_adjusted:int64`; `2 EXP 64`] + BOUND_OF_ACC_LEN) THEN + ANTS_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[]; ALL_TAC] THEN + + ENSURES_EVENTS_SEQUENCE_TAC `pc + 0xab8` + `\s. + read X0 s = word_add (word_add ct_ptr (word curr_len)) (word 0x10) /\ + read X1 s = word_add pt_ptr (word curr_len) /\ + read X21 s = tail_len` THEN + CONJ_TAC THENL + [ + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes128 (word_add pt_ptr (word curr_len))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + UNDISCH_THEN `val ((word curr_len):int64) = curr_len` + (fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN REWRITE_TAC[th]) THEN + + ENSURES_INIT_TAC "s0" THEN + ARM_STEPS_TAC AES_XTS_DECRYPT_EXEC (1--2) THEN + + (* Discharge if condition *) + SUBGOAL_THEN `~(val (word_and (tail_len:int64) (word 0xf)) = 0x0)` MP_TAC THENL + [ UNDISCH_TAC `~(val (tail_len:int64) = 0x0)` THEN + UNDISCH_TAC `val (tail_len:int64) < 16` THEN + MP_TAC (SPEC `tail_len:int64` WORD_AND_MASK16_EQ_0) THEN + SIMP_TAC[]; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + (* Decrypt last block *) + ARM_STEPS_TAC AES_XTS_DECRYPT_EXEC (3--11) THEN + ARM_STEPS_TAC AES_XTS_DECRYPT_EXEC (12--42) THEN + ARM_STEPS_TAC AES_XTS_DECRYPT_EXEC (43--43) THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + EXPAND_TAC "curr_len" THEN + ABBREV_TAC `vlen = val (len:int64)` THEN + DISCHARGE_SAFETY_PROPERTY_TAC; + + ALL_TAC + ] THEN + + SUBGOAL_THEN `curr_len + 16 + val (tail_len:int64) = val (len:int64)` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM (ASSUME `acc_len num_5blocks_adjusted num_blocks_adjusted = curr_len`)] THEN + MP_TAC (SPECL [`num_5blocks_adjusted:int64`; `num_blocks_adjusted:int64`] VALUE_OF_ACC_LEN) THEN + ANTS_TAC THENL[ASM_ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL[ASM_ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL[ASM_SIMP_TAC[]; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + EXPAND_TAC "num_blocks_adjusted" THEN + UNDISCH_TAC `~(val (tail_len:int64) = 0)` THEN + SIMP_TAC[] THEN DISCH_TAC THEN + ASM_SIMP_TAC[VAL_WORD_SUB; DIMINDEX_64; VAL_WORD; + ARITH_RULE `16 MOD 2 EXP 64 = 16`] THEN + MP_TAC (SPECL [`val (num_blocks:int64)`; `0x2 EXP 0x40`; `16`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL [ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; `val (num_blocks:int64) - 16`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + SIMP_TAC[ARITH_RULE `!x. 1 * x = x`] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[MOD_LT] THEN + CONJ_TAC THENL [ + SUBGOAL_THEN `val (num_blocks:int64) - 0x10 + 0x10 + val (tail_len:int64) + = val num_blocks + val tail_len` SUBST1_TAC THENL + [ IMP_REWRITE_TAC[ADD_ASSOC; SUB_ADD] THEN ASM_ARITH_TAC; ALL_TAC] THEN + EXPAND_TAC "len" THEN + REWRITE_TAC[VAL_WORD_ADD] THEN + IMP_REWRITE_TAC[MOD_LT; DIMINDEX_64] THEN + CONJ_TAC THENL [ARITH_TAC; ASM_ARITH_TAC]; + ALL_TAC + ] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + + (* Invariant proof for .composite_dec_loop *) + ENSURES_EVENTS_WHILE_UP2_TAC + `val (tail_len:int64)` + `pc + 0xac0` + `pc + 0xad8` + `\i s. + ( read X0 s = word_add (word_add ct_ptr (word curr_len)) (word 0x10) /\ + read X1 s = word_add pt_ptr (word curr_len) /\ + read X13 s = word_add (word_add pt_ptr (word curr_len)) (word 0x10) /\ + read X20 s = word_add (word_add ct_ptr (word curr_len)) (word 0x10) /\ + read X21 s = (word (val (tail_len:int64) - i)):int64)` THEN + ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL + [ + (* Subgoal 1: invariant holds before entering loop *) + REWRITE_TAC[byte_list_at] THEN + UNDISCH_THEN `val ((word curr_len):int64) = curr_len` + (fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN REWRITE_TAC[th]) THEN + + ENSURES_INIT_TAC "s0" THEN STRIP_EXISTS_ASSUM_TAC THEN + ARM_STEPS_TAC AES_XTS_DECRYPT_EXEC (1--2) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + REWRITE_TAC[WORD_VAL; SUB_0] THEN NO_TAC; + + DISCHARGE_SAFETY_PROPERTY_TAC + ]; + + (* Subgoal 2: inductive step *) + REWRITE_TAC[] THEN + REPEAT STRIP_TAC THEN + ABBREV_TAC `n = val (tail_len:int64)` THEN + + (* For non-overlapping and MAYCHANGE address reasoning *) + SUBGOAL_THEN `curr_len + 16 + (n - i - 1) < val (len:int64)` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM (ASSUME `acc_len num_5blocks_adjusted num_blocks_adjusted = curr_len`)] THEN + MP_TAC (SPECL [`num_5blocks_adjusted:int64`; `num_blocks_adjusted:int64`] VALUE_OF_ACC_LEN) THEN + REPEAT_N 3 (ANTS_TAC THENL [ASM_ARITH_TAC ORELSE ASM_SIMP_TAC[]; ALL_TAC]) THEN + SIMP_TAC[] THEN DISCH_TAC THEN + ASM_ARITH_TAC; + + ALL_TAC] THEN + + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes8 (word_add pt_ptr (word (curr_len + 0x10 + + (n - i - 1))))],, + MAYCHANGE [memory :> bytes8 (word_add pt_ptr (word (curr_len + + (n - i - 1))))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + UNDISCH_THEN `val ((word curr_len):int64) = curr_len` + (fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN REWRITE_TAC[th]) THEN + ENSURES_INIT_TAC "s0" THEN + STRIP_EXISTS_ASSUM_TAC THEN + + SUBGOAL_THEN `val ((word (n - i)):int64) = n - i` SUBST_ALL_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `i < n` THEN + UNDISCH_TAC `n < 0x10` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val ((word (n - (i + 0x1))):int64) = n - (i + 1)` SUBST_ALL_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `i < n` THEN + UNDISCH_TAC `n < 0x10` THEN + ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `word_sub ((word (i + 0x1)):int64) (word 0x1) = word i` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM VAL_EQ; VAL_WORD_SUB; DIMINDEX_64] THEN + MP_TAC (SPECL [`val ((word (i + 0x1)):int64)`; `0x2 EXP 0x40`; `val ((word 0x1):int64)`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN ASM_ARITH_TAC + ; ALL_TAC] THEN + ANTS_TAC THENL [ WORD_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; `val ((word (i + 0x1)):int64) - val ((word 0x1):int64)`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + SIMP_TAC[ARITH_RULE `!x. 1 * x = x`] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[MOD_LT] THEN + CONJ_TAC THENL + [ SUBGOAL_THEN `i + 1 < 2 EXP 64` MP_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + ARITH_TAC; + UNDISCH_TAC `i < n` THEN + UNDISCH_TAC `n < 0x10` THEN + WORD_ARITH_TAC] + ; ALL_TAC] THEN + + SUBGOAL_THEN `val ((word i):int64) < 0x10` ASSUME_TAC THENL + [ UNDISCH_TAC `i < n` THEN + UNDISCH_TAC `n < 0x10` THEN + WORD_ARITH_TAC; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + REPEAT STRIP_TAC THEN + + MP_TAC (SPECL [`ct_ptr:int64`; `len:int64`; + `(word_add (word (curr_len + 0x10)) (word i)):int64`; + `ct:byte list`; `s0:armstate`] SELECT_ONE_BYTE_FROM_FORALL) THEN + SUBGOAL_THEN `val (word_add ((word (curr_len + 0x10)):int64) (word i)) < val (len:int64)` ASSUME_TAC THENL + [ REWRITE_TAC[WORD_RULE `!a b. word_add ((word a):int64) (word b) = word (a + b)`] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + STRIP_TAC THEN + + (* For address matching when symbolic simulation *) + SUBGOAL_THEN `word_add (ct_ptr:int64) (word_add (word (curr_len + 0x10)) (word i)) = + word_add ct_ptr (word (curr_len + 16 + i))` SUBST_ALL_TAC THENL + [ REWRITE_TAC[WORD_RULE `!a b. word_add ((word a):int64) (word b) = word (a + b)`; ADD_ASSOC] + ; ALL_TAC] THEN + SUBGOAL_THEN `!x. word_add (word_add (pt_ptr:int64) (word curr_len)) (word x) = + word_add pt_ptr (word (curr_len + x))` ASSUME_TAC THENL + [ GEN_TAC THEN REWRITE_TAC[ + WORD_RULE `!(a:int64) b c. word_add (word_add a b) c = word_add a (word_add b c)`; + WORD_RULE `!a b. word_add ((word a):int64) (word b) = word (a + b)`] + ; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ARM_STEPS_TAC AES_XTS_DECRYPT_EXEC (1--6) THEN + (* Help MAYCHANGE predicate be syntactically similar to the MAYCHANGE conclusion *) + SUBGOAL_THEN `word_sub (word (n - i)) (word 1) = word (n - i - 1):int64` SUBST_ALL_TAC THENL [ + IMP_REWRITE_TAC[WORD_SUB2] THEN SIMPLE_ARITH_TAC; + ALL_TAC; + ] THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + CONJ_TAC THENL [ + (* Initial version of proof generated by Opus 4.6. :) *) + SUBGOAL_THEN `1 <= n - i /\ n - i <= 15` STRIP_ASSUME_TAC THENL + [SIMPLE_ARITH_TAC; ALL_TAC] THEN + VAL_INT64_TAC `n - i` THEN + VAL_INT64_TAC `n - i - 1` THEN + SUBGOAL_THEN `ival (word (n - i):int64) = &(n - i)` ASSUME_TAC THENL + [REWRITE_TAC[ival] THEN ASM_REWRITE_TAC[] THEN + REWRITE_TAC[DIMINDEX_64] THEN CONV_TAC NUM_REDUCE_CONV THEN + SIMPLE_ARITH_TAC; + ALL_TAC] THEN + SUBGOAL_THEN `ival (word (n - i - 1):int64) = &(n - i - 1)` + ASSUME_TAC THENL + [REWRITE_TAC[ival] THEN ASM_REWRITE_TAC[] THEN + REWRITE_TAC[DIMINDEX_64] THEN CONV_TAC NUM_REDUCE_CONV THEN + SIMPLE_ARITH_TAC; + ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + SUBGOAL_THEN `~(&(n - i - 1):int < &0)` (fun th -> REWRITE_TAC[th]) THENL + [REWRITE_TAC[INT_NOT_LT; INT_POS]; ALL_TAC] THEN + SUBGOAL_THEN `&(n - i) - &1:int = &(n - i - 1)` SUBST1_TAC THENL + [MP_TAC(SPECL [`1`; `n - i:num`] INT_OF_NUM_SUB) THEN + UNDISCH_TAC `1 <= n - i` THEN SIMP_TAC[] THEN INT_ARITH_TAC; + ALL_TAC] THEN + REWRITE_TAC[] THEN + ASM_CASES_TAC `n - i - 1 = 0` THENL + [ASM_REWRITE_TAC[] THEN + SUBGOAL_THEN `~(i + 1 < n)` (fun th -> REWRITE_TAC[th]) THEN SIMPLE_ARITH_TAC; + ASM_REWRITE_TAC[] THEN + SUBGOAL_THEN `i + 1 < n` (fun th -> REWRITE_TAC[th]) THEN SIMPLE_ARITH_TAC]; + + ALL_TAC + ] THEN + CONJ_TAC THENL [ + CONV_TAC WORD_RULE; ALL_TAC + ] THEN + CONJ_TAC THENL [ + AP_TERM_TAC THEN SIMPLE_ARITH_TAC; + ALL_TAC + ] THEN + (* Abbbreviate val(len) because it appears memaccess_inbounds and + existence of 'val' blocks reasoning of contained/nonoverlapping + predicates *) + ABBREV_TAC `m = val (len:int64)` THEN + DISCHARGE_SAFETY_PROPERTY_TAC + ~abbrevs_unfold_before_f_events_tac:[ + `acc_len num_5blocks_adjusted num_blocks_adjusted = curr_len`; + `val (tail_len:int64) = n`; + ]; + + (* Subgoal 3: *) + REWRITE_TAC[] THEN + ENSURES_INIT_TAC "s0" THEN STRIP_EXISTS_ASSUM_TAC THEN + ARM_STEPS_TAC AES_XTS_DECRYPT_EXEC (1--32) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + CONJ_TAC THENL [ + REWRITE_TAC[GSYM (ASSUME `acc_len num_5blocks_adjusted num_blocks_adjusted = curr_len`)] THEN + ABBREV_TAC `vlen = val (len:int64)` THEN + DISCHARGE_SAFETY_PROPERTY_TAC; + + (* Maychange *) + ABBREV_TAC `vallen = val (len:int64)` THEN + ABBREV_TAC `valcurlen = val (curr_len:int64)` THEN + MONOTONE_MAYCHANGE_TAC + ] + ] +);; + + +(* Proof: Less than 2 blocks *) +let AES_XTS_DECRYPT_LT_2BLOCK_CORRECT = time prove( + `!ct_ptr pt_ptr ct key1_ptr key2_ptr iv_ptr iv len + k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e + k10 k11 k12 k13 k14 k15 k16 k17 k18 k19 k1a k1b k1c k1d k1e + pc. + nonoverlapping (word pc, LENGTH aes_xts_decrypt_mc) (pt_ptr, val len) + /\ nonoverlapping (ct_ptr, val len) (pt_ptr, val len) + /\ nonoverlapping (key1_ptr, 260) (pt_ptr, val len) + /\ val len >= 16 /\ val len < 0x20 /\ LENGTH ct = val len + /\ [k00; k01; k02; k03; k04; k05; k06; k07; k08; k09; k0a; k0b; k0c; k0d; k0e] = key1 + /\ [k10; k11; k12; k13; k14; k15; k16; k17; k18; k19; k1a; k1b; k1c; k1d; k1e] = key2 + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes_xts_decrypt_mc /\ + read PC s = word (pc + 0x1c) /\ + C_ARGUMENTS [ct_ptr; pt_ptr; len; key1_ptr; key2_ptr; iv_ptr] s /\ + byte_list_at ct ct_ptr len s /\ + read(memory :> bytes128 iv_ptr) s = iv /\ + set_key_schedule s key1_ptr k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e /\ + set_key_schedule s key2_ptr k10 k11 k12 k13 k14 k15 k16 k17 k18 k19 k1a k1b k1c k1d k1e) + (\s. read PC s = word (pc + 0xb58) /\ + byte_list_at (aes256_xts_decrypt ct (val len) iv key1 key2) pt_ptr len s + ) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes(pt_ptr, val len)]) + `, + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + SUBGOAL_THEN `word_add (word_and len (word 0xf)) + (word_and len (word 0xfffffffffffffff0)) = len:int64` ASSUME_TAC THENL + [REWRITE_TAC[word_split_lemma]; ALL_TAC] THEN + ABBREV_TAC `num_blocks:int64 = word_and len (word 0xfffffffffffffff0)` THEN + ABBREV_TAC `tail_len:int64 = word_and len (word 0xf)` THEN + ABBREV_TAC `num_blocks_adjusted = if val (tail_len:int64) = 0 + then num_blocks else word_sub (num_blocks:int64) (word 0x10)` THEN + ABBREV_TAC `num_5blocks_adjusted = (word (val (num_blocks_adjusted:int64) DIV 0x50)):int64` THEN + + SUBGOAL_THEN `val (num_blocks:int64) = 16` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks" THEN + REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `val (len:int64) DIV 16 = 1` SUBST1_TAC THENL + [ MATCH_MP_TAC(MESON[LE_ANTISYM] `m <= n /\ n <= m ==> m = n`) THEN + CONJ_TAC THENL [ ASM_ARITH_TAC; ASM_ARITH_TAC]; + ALL_TAC] THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) < 0x20` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + COND_CASES_TAC THENL[ + ASM_ARITH_TAC; + UNDISCH_TAC `val (num_blocks:int64) = 0x10` THEN + WORD_ARITH_TAC] + ; ALL_TAC] THEN + + (* Prove property until start of cipher stealing. *) + ENSURES_SEQUENCE_TAC `pc + 0xa0c` + `\s. + read X0 s = word_add ct_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X1 s = word_add pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X3 s = key1_ptr /\ + read X21 s = tail_len /\ + read Q6 s = calculate_tweak (acc_blocks num_5blocks_adjusted num_blocks_adjusted T) iv key2 /\ + read X19 s = word 0x87 /\ + read Q16 s = k00 /\ read Q17 s = k01 /\ read Q12 s = k02 /\ read Q13 s = k03 /\ + read Q14 s = k04 /\ read Q15 s = k05 /\ read Q4 s = k06 /\ read Q5 s = k07 /\ + read Q18 s = k08 /\ read Q19 s = k09 /\ read Q20 s = k0a /\ read Q21 s = k0b /\ + read Q22 s = k0c /\ read Q23 s = k0d /\ read Q7 s = k0e /\ + byte_list_at ct ct_ptr len s /\ + byte_list_at (aes256_xts_decrypt ct (acc_len num_5blocks_adjusted num_blocks_adjusted) iv key1 key2) + pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) s` THEN + CONJ_TAC THENL + [ + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes128 pt_ptr]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--2) THEN + + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (len:int64) (word 0x10)) < &0x0 + <=> ~(ival (len:int64) - &0x10 = ival (word_sub (len:int64) (word 0x10)))` MP_TAC THENL + [ MP_TAC (BITBLAST_RULE + `val (len:int64) >= 0x10 ==> val len < 0x20 ==> + ival (word_sub len (word 0x10)) >= &0x0`) THEN + ASM_REWRITE_TAC[] THEN + MP_TAC (BITBLAST_RULE + `val (len:int64) >= 0x10 ==> val len < 0x20 ==> + ival (len:int64) - &0x10 = ival (word_sub len (word 0x10))`) THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; + ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + MP_TAC (SPECL [`ct_ptr:int64`; `len:int64`; `ct:byte list`; `s2:armstate`] READ_LT_2BLOCK) THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (3--69) THEN + (* Prove Q6 stores initial tweak *) + FIRST_X_ASSUM(MP_TAC o SPEC `(calculate_tweak 0 iv key2)` + o MATCH_MP (MESON[] `read Q6 s = a ==> !a'. a = a' ==> read Q6 s = a'`)) THEN + ANTS_TAC THENL + [ REWRITE_TAC[CONJUNCT1 calculate_tweak; xts_init_tweak] THEN + EXPAND_TAC "key2" THEN AESENC_TAC; DISCH_TAC] THEN + + (* Simulating until branch for num_blocks adjustment *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (70--89) THEN + + (* Case split on whether there is a tail *) + FIRST_X_ASSUM MP_TAC THEN + COND_CASES_TAC THENL + [ + DISCH_TAC THEN + + SUBGOAL_THEN `val (tail_len:int64) = 0` SUBST_ALL_TAC THENL + [ UNDISCH_TAC `val (word_and (tail_len:int64) (word 0xf)) = 0x0` THEN + MP_TAC (SPECL [`len:int64`; `tail_len:int64`] TAIL_LEN_BOUND_THM) THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + SUBGOAL_THEN `val (word_and (tail_len:int64) (word 15)) = val tail_len` SUBST1_TAC THENL + [ REWRITE_TAC[VAL_WORD_AND_MASK_WORD; ARITH_RULE `15 = 2 EXP 4 - 1`] THEN + CONV_TAC NUM_REDUCE_CONV THEN ASM_REWRITE_TAC[] THEN + IMP_REWRITE_TAC[MOD_LT]; + ALL_TAC] THEN + SIMP_TAC[]; ALL_TAC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + + SUBGOAL_THEN `val (num_blocks_adjusted:int64) = 16` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_REWRITE_TAC[] + ; ALL_TAC ] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) = 0` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) = 16` THEN + SIMP_TAC[] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[VAL_WORD_0] + ; ALL_TAC ] THEN + + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (90--126) THEN + XTSDEC_TAC `Q0:(armstate,int128)component` `0` `0` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (127--136) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `1:num` `0:num` THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_blocks] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`16:num`; `pt_ptr:int64`; `(aes256_xts_decrypt ct 16 iv key1 key2):byte list`; `s136:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + MP_TAC (SPECL [`1`; `ct:byte list`; `iv:int128`; + `key1:int128 list`; `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + ASM_REWRITE_TAC[] THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_1BLOCK] + ] + ; ALL_TAC] THEN + + (* There is a tail *) + DISCH_TAC THEN + (* Prove ~ tail_len = 0 *) + SUBGOAL_THEN `~(val (tail_len:int64) = 0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (word_and (tail_len:int64) (word 0xf)) = 0x0)` THEN + MP_TAC (SPECL [`len:int64`; `tail_len:int64`] TAIL_LEN_BOUND_THM) THEN + ASM_REWRITE_TAC[] THEN + SUBST1_TAC(ARITH_RULE `0xf = 2 EXP 4 - 1`) THEN + REWRITE_TAC[VAL_WORD_AND_MASK_WORD] THEN + NUM_REDUCE_TAC THEN IMP_REWRITE_TAC[MOD_LT] + ; ALL_TAC] THEN + (* Prove num_blocks_adjusted = word_sub num_blocks (word 0x10) *) + SUBGOAL_THEN `word_sub num_blocks (word 0x10) = num_blocks_adjusted:int64` ASSUME_TAC THENL + [ UNDISCH_TAC `(if val (tail_len:int64) = 0x0 + then (num_blocks:int64) + else word_sub num_blocks (word 0x10)) = num_blocks_adjusted` THEN + ASM_REWRITE_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) = 0` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + UNDISCH_TAC `val (num_blocks:int64) = 16` THEN + WORD_ARITH_TAC + ; ALL_TAC ] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) = 0` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + REWRITE_TAC[ASSUME `val (num_blocks_adjusted:int64) = 0`] THEN + WORD_ARITH_TAC + ; ALL_TAC ] THEN + + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (90--92) THEN + (* Discharge if condition *) + SUBGOAL_THEN + `~(ival (word_sub (num_blocks_adjusted:int64) (word 0x10)) < &0x0 <=> + ~(ival (num_blocks_adjusted:int64) - &0x10 = + ival (word_sub (num_blocks_adjusted:int64) (word 0x10))))` MP_TAC THENL + [ SUBGOAL_THEN `num_blocks_adjusted:int64 = (word 0)` SUBST1_TAC THENL + [ UNDISCH_TAC `val (num_blocks_adjusted:int64) = 0` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + WORD_ARITH_TAC + ; ALL_TAC] THEN + DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[WORD_ADD_0]; + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[WORD_ADD_0]; + ASM_REWRITE_TAC[acc_blocks] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MESON_TAC[ARITH_RULE `~(i < 0)`] + ] + ; ALL_TAC] THEN + + (* Reuse the cipher stealing proof *) + MP_TAC CIPHER_STEALING_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + EXISTS_TAC `(word 16):int64` THEN + ASM_SIMP_TAC[] THEN + SUBGOAL_THEN `num_blocks:int64 = word 0x10` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_blocks:int64) = 16` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + REPEAT CONJ_TAC THENL [ + ASM_ARITH_TAC; + EXPAND_TAC "len" THEN AP_TERM_TAC THEN + UNDISCH_TAC `val (num_blocks:int64) = 16` THEN + WORD_ARITH_TAC; + ASM_SIMP_TAC[]; + EXPAND_TAC "num_blocks_adjusted" THEN + REWRITE_TAC[ASSUME `num_blocks:int64 = word 16`] + ] +);; + + +(* Proof: less than 3 blocks *) +let AES_XTS_DECRYPT_LT_3BLOCK_CORRECT = time prove( + `!ct_ptr pt_ptr ct key1_ptr key2_ptr iv_ptr iv len + k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e + k10 k11 k12 k13 k14 k15 k16 k17 k18 k19 k1a k1b k1c k1d k1e + pc. + nonoverlapping (word pc, LENGTH aes_xts_decrypt_mc) (pt_ptr, val len) + /\ nonoverlapping (ct_ptr, val len) (pt_ptr, val len) + /\ nonoverlapping (key1_ptr, 260) (pt_ptr, val len) + /\ ~(val len < 0x20) /\ val len < 0x30 /\ LENGTH ct = val len + /\ [k00; k01; k02; k03; k04; k05; k06; k07; k08; k09; k0a; k0b; k0c; k0d; k0e] = key1 + /\ [k10; k11; k12; k13; k14; k15; k16; k17; k18; k19; k1a; k1b; k1c; k1d; k1e] = key2 + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes_xts_decrypt_mc /\ + read PC s = word (pc + 0x1c) /\ + C_ARGUMENTS [ct_ptr; pt_ptr; len; key1_ptr; key2_ptr; iv_ptr] s /\ + byte_list_at ct ct_ptr len s /\ + read(memory :> bytes128 iv_ptr) s = iv /\ + set_key_schedule s key1_ptr k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e /\ + set_key_schedule s key2_ptr k10 k11 k12 k13 k14 k15 k16 k17 k18 k19 k1a k1b k1c k1d k1e) + (\s. read PC s = word (pc + 0xb58) /\ + byte_list_at (aes256_xts_decrypt ct (val len) iv key1 key2) pt_ptr len s + ) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes(pt_ptr, val len)]) + `, + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + SUBGOAL_THEN `word_add (word_and len (word 0xf)) + (word_and len (word 0xfffffffffffffff0)) = len:int64` ASSUME_TAC THENL + [REWRITE_TAC[word_split_lemma]; ALL_TAC] THEN + ABBREV_TAC `num_blocks:int64 = word_and len (word 0xfffffffffffffff0)` THEN + ABBREV_TAC `tail_len:int64 = word_and len (word 0xf)` THEN + ABBREV_TAC `num_blocks_adjusted = if val (tail_len:int64) = 0 + then num_blocks else word_sub (num_blocks:int64) (word 0x10)` THEN + ABBREV_TAC `num_5blocks_adjusted = (word (val (num_blocks_adjusted:int64) DIV 0x50)):int64` THEN + + SUBGOAL_THEN `val (num_blocks:int64) = 32` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks" THEN + REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `val (len:int64) DIV 16 = 2` SUBST1_TAC THENL + [ MATCH_MP_TAC(MESON[LE_ANTISYM] `m <= n /\ n <= m ==> m = n`) THEN + CONJ_TAC THENL [ ASM_ARITH_TAC; ASM_ARITH_TAC]; + ALL_TAC] THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) < 0x30` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + COND_CASES_TAC THENL[ + ASM_ARITH_TAC; + UNDISCH_TAC `val (num_blocks:int64) = 0x20` THEN + WORD_ARITH_TAC] + ; ALL_TAC] THEN + + ENSURES_SEQUENCE_TAC `pc + 0xa0c` + `\s. + read X0 s = word_add ct_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X1 s = word_add pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X3 s = key1_ptr /\ + read X21 s = tail_len /\ + read Q6 s = calculate_tweak (acc_blocks num_5blocks_adjusted num_blocks_adjusted T) iv key2 /\ + read X19 s = word 0x87 /\ + read Q16 s = k00 /\ read Q17 s = k01 /\ read Q12 s = k02 /\ read Q13 s = k03 /\ + read Q14 s = k04 /\ read Q15 s = k05 /\ read Q4 s = k06 /\ read Q5 s = k07 /\ + read Q18 s = k08 /\ read Q19 s = k09 /\ read Q20 s = k0a /\ read Q21 s = k0b /\ + read Q22 s = k0c /\ read Q23 s = k0d /\ read Q7 s = k0e /\ + byte_list_at ct ct_ptr len s /\ + byte_list_at (aes256_xts_decrypt ct (acc_len num_5blocks_adjusted num_blocks_adjusted) iv key1 key2) + pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) s` THEN + CONJ_TAC THENL + [ + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes128 pt_ptr; memory :> bytes128 (word_add pt_ptr (word 16))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--2) THEN + + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (len:int64) (word 0x10)) < &0x0 + <=> ~(ival (len:int64) - &0x10 = ival (word_sub (len:int64) (word 0x10)))` MP_TAC THENL + [ MP_TAC (BITBLAST_RULE + `~(val (len:int64) < 0x20) ==> val len < 0x30 ==> + ival (word_sub len (word 0x10)) >= &0x0`) THEN + ASM_REWRITE_TAC[] THEN + MP_TAC (BITBLAST_RULE + `~(val (len:int64) < 0x20) ==> val len < 0x30 ==> + ival (len:int64) - &0x10 = ival (word_sub len (word 0x10))`) THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; + ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + MP_TAC (SPECL [`ct_ptr:int64`; `len:int64`; `ct:byte list`; `s2:armstate`] READ_LT_3BLOCK) THEN + ASM_SIMP_TAC[] THEN REPEAT STRIP_TAC THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (3--69) THEN + (* Prove Q6 stores initial tweak *) + FIRST_X_ASSUM(MP_TAC o SPEC `(calculate_tweak 0 iv key2)` + o MATCH_MP (MESON[] `read Q6 s = a ==> !a'. a = a' ==> read Q6 s = a'`)) THEN + ANTS_TAC THENL + [ REWRITE_TAC[CONJUNCT1 calculate_tweak; xts_init_tweak] THEN + EXPAND_TAC "key2" THEN AESENC_TAC; DISCH_TAC] THEN + + (* Simulating until branch for num_blocks adjustment *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (70--89) THEN + + (* Case split on whether there is a tail *) + FIRST_X_ASSUM MP_TAC THEN + COND_CASES_TAC THENL + [ + DISCH_TAC THEN + + SUBGOAL_THEN `val (tail_len:int64) = 0` SUBST_ALL_TAC THENL + [ UNDISCH_TAC `val (word_and (tail_len:int64) (word 0xf)) = 0x0` THEN + MP_TAC (SPECL [`len:int64`; `tail_len:int64`] TAIL_LEN_BOUND_THM) THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + SUBGOAL_THEN `val (word_and (tail_len:int64) (word 15)) = val tail_len` SUBST1_TAC THENL + [ REWRITE_TAC[VAL_WORD_AND_MASK_WORD; ARITH_RULE `15 = 2 EXP 4 - 1`] THEN + CONV_TAC NUM_REDUCE_CONV THEN ASM_REWRITE_TAC[] THEN + IMP_REWRITE_TAC[MOD_LT]; + ALL_TAC] THEN + SIMP_TAC[]; ALL_TAC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + + SUBGOAL_THEN `val (num_blocks_adjusted:int64) = 0x20` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_REWRITE_TAC[] + ; ALL_TAC ] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) = 0` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) = 0x20` THEN + SIMP_TAC[] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[VAL_WORD_0] + ; ALL_TAC ] THEN + + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (90--158) THEN + XTSDEC_TAC `Q0:(armstate,int128)component` `0` `0` THEN + XTSDEC_TAC `Q1:(armstate,int128)component` `0x10` `0x1` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (159--168) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `2:num` `1:num` THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_blocks] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0x20:num`; `pt_ptr:int64`; `(aes256_xts_decrypt ct 0x20 iv key1 key2):byte list`; + `s168:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + MP_TAC (SPECL [`2`; `ct:byte list`; `iv:int128`; + `key1:int128 list`; `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_2BLOCKS] + ]; ALL_TAC] THEN + + (* There is a tail *) + DISCH_TAC THEN + (* Prove ~ tail_len = 0 *) + SUBGOAL_THEN `~(val (tail_len:int64) = 0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (word_and (tail_len:int64) (word 0xf)) = 0x0)` THEN + MP_TAC (SPECL [`len:int64`; `tail_len:int64`] TAIL_LEN_BOUND_THM) THEN + ASM_REWRITE_TAC[] THEN + SUBST1_TAC(ARITH_RULE `0xf = 2 EXP 4 - 1`) THEN + REWRITE_TAC[VAL_WORD_AND_MASK_WORD] THEN + NUM_REDUCE_TAC THEN IMP_REWRITE_TAC[MOD_LT] + ; ALL_TAC] THEN + (* Prove num_blocks_adjusted = word_sub num_blocks (word 0x10) *) + SUBGOAL_THEN `word_sub num_blocks (word 0x10) = num_blocks_adjusted:int64` ASSUME_TAC THENL + [ UNDISCH_TAC `(if val (tail_len:int64) = 0x0 + then (num_blocks:int64) + else word_sub num_blocks (word 0x10)) = num_blocks_adjusted` THEN + ASM_REWRITE_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) = 0x10` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + UNDISCH_TAC `val (num_blocks:int64) = 0x20` THEN + WORD_ARITH_TAC + ; ALL_TAC ] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) = 0` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + REWRITE_TAC[ASSUME `val (num_blocks_adjusted:int64) = 0x10`] THEN + WORD_ARITH_TAC + ; ALL_TAC ] THEN + + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (90--92) THEN + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (num_blocks_adjusted:int64) (word 0x10)) < &0x0 <=> + ~(ival (num_blocks_adjusted:int64) - &0x10 = + ival (word_sub (num_blocks_adjusted:int64) (word 0x10)))` MP_TAC THENL + [ SUBGOAL_THEN `num_blocks_adjusted:int64 = (word 0x10)` SUBST1_TAC THENL + [ UNDISCH_TAC `val (num_blocks_adjusted:int64) = 0x10` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + WORD_ARITH_TAC + ; ALL_TAC] THEN + DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (93--129) THEN + XTSDEC_TAC `Q0:(armstate,int128)component` `0` `0` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (130--139) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `1:num` `0:num` THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[WORD_ADD_0]; + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[WORD_ADD_0]; + ASM_REWRITE_TAC[acc_blocks] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`16:num`; `pt_ptr:int64`; `(aes256_xts_decrypt ct 16 iv key1 key2):byte list`; + `s139:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + MP_TAC (SPECL [`1`; `ct:byte list`; `iv:int128`; + `key1:int128 list`; `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_1BLOCK] + ] + ; ALL_TAC] THEN + + (* Reuse the cipher stealing proof *) + MP_TAC CIPHER_STEALING_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + EXISTS_TAC `(word 0x20):int64` THEN + ASM_SIMP_TAC[] THEN + SUBGOAL_THEN `num_blocks:int64 = word 0x20` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_blocks:int64) = 0x20` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + REPEAT CONJ_TAC THENL [ + ASM_ARITH_TAC; + ASM_ARITH_TAC; + EXPAND_TAC "len" THEN AP_TERM_TAC THEN + UNDISCH_TAC `val (num_blocks:int64) = 0x20` THEN + WORD_ARITH_TAC; + ASM_SIMP_TAC[]; + EXPAND_TAC "num_blocks_adjusted" THEN + REWRITE_TAC[ASSUME `num_blocks:int64 = word 0x20`] + ] +);; + + +(* Proof: less than 4 blocks *) +let AES_XTS_DECRYPT_LT_4BLOCK_CORRECT = time prove( + `!ct_ptr pt_ptr ct key1_ptr key2_ptr iv_ptr iv len + k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e + k10 k11 k12 k13 k14 k15 k16 k17 k18 k19 k1a k1b k1c k1d k1e + pc. + nonoverlapping (word pc, LENGTH aes_xts_decrypt_mc) (pt_ptr, val len) + /\ nonoverlapping (ct_ptr, val len) (pt_ptr, val len) + /\ nonoverlapping (key1_ptr, 260) (pt_ptr, val len) + /\ ~(val len < 0x30) /\ val len < 0x40 /\ LENGTH ct = val len + /\ [k00; k01; k02; k03; k04; k05; k06; k07; k08; k09; k0a; k0b; k0c; k0d; k0e] = key1 + /\ [k10; k11; k12; k13; k14; k15; k16; k17; k18; k19; k1a; k1b; k1c; k1d; k1e] = key2 + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes_xts_decrypt_mc /\ + read PC s = word (pc + 0x1c) /\ + C_ARGUMENTS [ct_ptr; pt_ptr; len; key1_ptr; key2_ptr; iv_ptr] s /\ + byte_list_at ct ct_ptr len s /\ + read(memory :> bytes128 iv_ptr) s = iv /\ + set_key_schedule s key1_ptr k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e /\ + set_key_schedule s key2_ptr k10 k11 k12 k13 k14 k15 k16 k17 k18 k19 k1a k1b k1c k1d k1e) + (\s. read PC s = word (pc + 0xb58) /\ + byte_list_at (aes256_xts_decrypt ct (val len) iv key1 key2) pt_ptr len s + ) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes(pt_ptr, val len)]) + `, + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + SUBGOAL_THEN `word_add (word_and len (word 0xf)) + (word_and len (word 0xfffffffffffffff0)) = len:int64` ASSUME_TAC THENL + [REWRITE_TAC[word_split_lemma]; ALL_TAC] THEN + ABBREV_TAC `num_blocks:int64 = word_and len (word 0xfffffffffffffff0)` THEN + ABBREV_TAC `tail_len:int64 = word_and len (word 0xf)` THEN + ABBREV_TAC `num_blocks_adjusted = if val (tail_len:int64) = 0 + then num_blocks else word_sub (num_blocks:int64) (word 0x10)` THEN + ABBREV_TAC `num_5blocks_adjusted = (word (val (num_blocks_adjusted:int64) DIV 0x50)):int64` THEN + + SUBGOAL_THEN `val (num_blocks:int64) = 0x30` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks" THEN + REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `val (len:int64) DIV 16 = 3` SUBST1_TAC THENL + [ MATCH_MP_TAC(MESON[LE_ANTISYM] `m <= n /\ n <= m ==> m = n`) THEN + CONJ_TAC THENL [ ASM_ARITH_TAC; ASM_ARITH_TAC]; + ALL_TAC] THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) < 0x40` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + COND_CASES_TAC THENL[ + ASM_ARITH_TAC; + UNDISCH_TAC `val (num_blocks:int64) = 0x30` THEN + WORD_ARITH_TAC] + ; ALL_TAC] THEN + + ENSURES_SEQUENCE_TAC `pc + 0xa0c` + `\s. + read X0 s = word_add ct_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X1 s = word_add pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X3 s = key1_ptr /\ + read X21 s = tail_len /\ + read Q6 s = calculate_tweak (acc_blocks num_5blocks_adjusted num_blocks_adjusted T) iv key2 /\ + read X19 s = word 0x87 /\ + read Q16 s = k00 /\ read Q17 s = k01 /\ read Q12 s = k02 /\ read Q13 s = k03 /\ + read Q14 s = k04 /\ read Q15 s = k05 /\ read Q4 s = k06 /\ read Q5 s = k07 /\ + read Q18 s = k08 /\ read Q19 s = k09 /\ read Q20 s = k0a /\ read Q21 s = k0b /\ + read Q22 s = k0c /\ read Q23 s = k0d /\ read Q7 s = k0e /\ + byte_list_at ct ct_ptr len s /\ + byte_list_at (aes256_xts_decrypt ct (acc_len num_5blocks_adjusted num_blocks_adjusted) iv key1 key2) + pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) s` THEN + CONJ_TAC THENL + [ + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [ memory :> bytes128 pt_ptr; + memory :> bytes128 (word_add pt_ptr (word 16)); + memory :> bytes128 (word_add pt_ptr (word 32))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--2) THEN + + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (len:int64) (word 0x10)) < &0x0 + <=> ~(ival (len:int64) - &0x10 = ival (word_sub (len:int64) (word 0x10)))` MP_TAC THENL + [ MP_TAC (BITBLAST_RULE + `~(val (len:int64) < 0x30) ==> val len < 0x40 ==> + ival (word_sub len (word 0x10)) >= &0x0`) THEN + ASM_REWRITE_TAC[] THEN + MP_TAC (BITBLAST_RULE + `~(val (len:int64) < 0x30) ==> val len < 0x40 ==> + ival (len:int64) - &0x10 = ival (word_sub len (word 0x10))`) THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; + ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + MP_TAC (SPECL [`ct_ptr:int64`; `len:int64`; `ct:byte list`; `s2:armstate`] READ_LT_4BLOCK) THEN + ASM_SIMP_TAC[] THEN REPEAT STRIP_TAC THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (3--69) THEN + (* Prove Q6 stores initial tweak *) + FIRST_X_ASSUM(MP_TAC o SPEC `(calculate_tweak 0 iv key2)` + o MATCH_MP (MESON[] `read Q6 s = a ==> !a'. a = a' ==> read Q6 s = a'`)) THEN + ANTS_TAC THENL + [ REWRITE_TAC[CONJUNCT1 calculate_tweak; xts_init_tweak] THEN + EXPAND_TAC "key2" THEN AESENC_TAC; DISCH_TAC] THEN + + (* Simulating until branch for num_blocks adjustment *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (70--89) THEN + + (* Case split on whether there is a tail *) + FIRST_X_ASSUM MP_TAC THEN + COND_CASES_TAC THENL + [ + DISCH_TAC THEN + + SUBGOAL_THEN `val (tail_len:int64) = 0` SUBST_ALL_TAC THENL + [ UNDISCH_TAC `val (word_and (tail_len:int64) (word 0xf)) = 0x0` THEN + MP_TAC (SPECL [`len:int64`; `tail_len:int64`] TAIL_LEN_BOUND_THM) THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + SUBGOAL_THEN `val (word_and (tail_len:int64) (word 15)) = val tail_len` SUBST1_TAC THENL + [ REWRITE_TAC[VAL_WORD_AND_MASK_WORD; ARITH_RULE `15 = 2 EXP 4 - 1`] THEN + CONV_TAC NUM_REDUCE_CONV THEN ASM_REWRITE_TAC[] THEN + IMP_REWRITE_TAC[MOD_LT]; + ALL_TAC] THEN + SIMP_TAC[]; ALL_TAC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + + SUBGOAL_THEN `val (num_blocks_adjusted:int64) = 0x30` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_REWRITE_TAC[] + ; ALL_TAC ] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) = 0` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) = 0x30` THEN + SIMP_TAC[] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[VAL_WORD_0] + ; ALL_TAC ] THEN + + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (90--105) THEN + TWEAK_TAC `Q9:(armstate,int128)component` `2:num` `1:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (106--197) THEN + XTSDEC_TAC `Q0:(armstate,int128)component` `0` `0` THEN + XTSDEC_TAC `Q1:(armstate,int128)component` `0x10` `1` THEN + XTSDEC_TAC `Q24:(armstate,int128)component` `0x20` `2` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (198--208) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `3:num` `2:num` THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_blocks] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0x30:num`; `pt_ptr:int64`; `(aes256_xts_decrypt ct 0x30 iv key1 key2):byte list`; + `s208:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + MP_TAC (SPECL [`3`; `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_3BLOCKS] + ]; ALL_TAC + ] THEN + + (* There is a tail *) + DISCH_TAC THEN + (* Prove ~ tail_len = 0 *) + SUBGOAL_THEN `~(val (tail_len:int64) = 0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (word_and (tail_len:int64) (word 0xf)) = 0x0)` THEN + MP_TAC (SPECL [`len:int64`; `tail_len:int64`] TAIL_LEN_BOUND_THM) THEN + ASM_REWRITE_TAC[] THEN + SUBST1_TAC(ARITH_RULE `0xf = 2 EXP 4 - 1`) THEN + REWRITE_TAC[VAL_WORD_AND_MASK_WORD] THEN + NUM_REDUCE_TAC THEN IMP_REWRITE_TAC[MOD_LT] + ; ALL_TAC] THEN + (* Prove num_blocks_adjusted = word_sub num_blocks (word 0x10) *) + SUBGOAL_THEN `word_sub num_blocks (word 0x10) = num_blocks_adjusted:int64` ASSUME_TAC THENL + [ UNDISCH_TAC `(if val (tail_len:int64) = 0x0 + then (num_blocks:int64) + else word_sub num_blocks (word 0x10)) = num_blocks_adjusted` THEN + ASM_REWRITE_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) = 0x20` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + UNDISCH_TAC `val (num_blocks:int64) = 0x30` THEN + WORD_ARITH_TAC + ; ALL_TAC ] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) = 0` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + REWRITE_TAC[ASSUME `val (num_blocks_adjusted:int64) = 0x20`] THEN + WORD_ARITH_TAC + ; ALL_TAC ] THEN + + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (90--92) THEN + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (num_blocks_adjusted:int64) (word 0x10)) < &0x0 <=> + ~(ival (num_blocks_adjusted:int64) - &0x10 = + ival (word_sub (num_blocks_adjusted:int64) (word 0x10)))` MP_TAC THENL + [ SUBGOAL_THEN `num_blocks_adjusted:int64 = (word 0x20)` SUBST1_TAC THENL + [ UNDISCH_TAC `val (num_blocks_adjusted:int64) = 0x20` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + WORD_ARITH_TAC + ; ALL_TAC] THEN + DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (93--161) THEN + XTSDEC_TAC `Q0:(armstate,int128)component` `0` `0` THEN + XTSDEC_TAC `Q1:(armstate,int128)component` `0x10` `1` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (162--171) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `2:num` `1:num` THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_blocks] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0x20:num`; `pt_ptr:int64`; `(aes256_xts_decrypt ct 0x20 iv key1 key2):byte list`; + `s171:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + MP_TAC (SPECL [`2`; `ct:byte list`; `iv:int128`; + `key1:int128 list`; `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_2BLOCKS] + ]; ALL_TAC] THEN + + (* Reuse the cipher stealing proof *) + MP_TAC CIPHER_STEALING_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + EXISTS_TAC `(word 0x30):int64` THEN + ASM_SIMP_TAC[] THEN + SUBGOAL_THEN `num_blocks:int64 = word 0x30` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_blocks:int64) = 0x30` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + REPEAT CONJ_TAC THENL [ + ASM_ARITH_TAC; + ASM_ARITH_TAC; + EXPAND_TAC "len" THEN AP_TERM_TAC THEN + UNDISCH_TAC `val (num_blocks:int64) = 0x30` THEN + WORD_ARITH_TAC; + ASM_SIMP_TAC[]; + EXPAND_TAC "num_blocks_adjusted" THEN + REWRITE_TAC[ASSUME `num_blocks:int64 = word 0x30`] + ] +);; + + +(* Proof: less than 5 blocks *) +let AES_XTS_DECRYPT_LT_5BLOCK_CORRECT = time prove( + `!ct_ptr pt_ptr ct key1_ptr key2_ptr iv_ptr iv len + k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e + k10 k11 k12 k13 k14 k15 k16 k17 k18 k19 k1a k1b k1c k1d k1e + pc. + nonoverlapping (word pc, LENGTH aes_xts_decrypt_mc) (pt_ptr, val len) + /\ nonoverlapping (ct_ptr, val len) (pt_ptr, val len) + /\ nonoverlapping (key1_ptr, 260) (pt_ptr, val len) + /\ ~(val len < 0x40) /\ val len < 0x50 /\ LENGTH ct = val len + /\ [k00; k01; k02; k03; k04; k05; k06; k07; k08; k09; k0a; k0b; k0c; k0d; k0e] = key1 + /\ [k10; k11; k12; k13; k14; k15; k16; k17; k18; k19; k1a; k1b; k1c; k1d; k1e] = key2 + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes_xts_decrypt_mc /\ + read PC s = word (pc + 0x1c) /\ + C_ARGUMENTS [ct_ptr; pt_ptr; len; key1_ptr; key2_ptr; iv_ptr] s /\ + byte_list_at ct ct_ptr len s /\ + read(memory :> bytes128 iv_ptr) s = iv /\ + set_key_schedule s key1_ptr k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e /\ + set_key_schedule s key2_ptr k10 k11 k12 k13 k14 k15 k16 k17 k18 k19 k1a k1b k1c k1d k1e) + (\s. read PC s = word (pc + 0xb58) /\ + byte_list_at (aes256_xts_decrypt ct (val len) iv key1 key2) pt_ptr len s + ) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes(pt_ptr, val len)]) + `, + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + SUBGOAL_THEN `word_add (word_and len (word 0xf)) + (word_and len (word 0xfffffffffffffff0)) = len:int64` ASSUME_TAC THENL + [REWRITE_TAC[word_split_lemma]; ALL_TAC] THEN + ABBREV_TAC `num_blocks:int64 = word_and len (word 0xfffffffffffffff0)` THEN + ABBREV_TAC `tail_len:int64 = word_and len (word 0xf)` THEN + ABBREV_TAC `num_blocks_adjusted = if val (tail_len:int64) = 0 + then num_blocks else word_sub (num_blocks:int64) (word 0x10)` THEN + ABBREV_TAC `num_5blocks_adjusted = (word (val (num_blocks_adjusted:int64) DIV 0x50)):int64` THEN + + SUBGOAL_THEN `val (num_blocks:int64) = 0x40` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks" THEN + REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `val (len:int64) DIV 16 = 4` SUBST1_TAC THENL + [ MATCH_MP_TAC(MESON[LE_ANTISYM] `m <= n /\ n <= m ==> m = n`) THEN + CONJ_TAC THENL [ ASM_ARITH_TAC; ASM_ARITH_TAC]; + ALL_TAC] THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) < 0x50` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + COND_CASES_TAC THENL[ + ASM_ARITH_TAC; + UNDISCH_TAC `val (num_blocks:int64) = 0x40` THEN + WORD_ARITH_TAC] + ; ALL_TAC] THEN + + ENSURES_SEQUENCE_TAC `pc + 0xa0c` + `\s. + read X0 s = word_add ct_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X1 s = word_add pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X3 s = key1_ptr /\ + read X21 s = tail_len /\ + read Q6 s = calculate_tweak (acc_blocks num_5blocks_adjusted num_blocks_adjusted T) iv key2 /\ + read X19 s = word 0x87 /\ + read Q16 s = k00 /\ read Q17 s = k01 /\ read Q12 s = k02 /\ read Q13 s = k03 /\ + read Q14 s = k04 /\ read Q15 s = k05 /\ read Q4 s = k06 /\ read Q5 s = k07 /\ + read Q18 s = k08 /\ read Q19 s = k09 /\ read Q20 s = k0a /\ read Q21 s = k0b /\ + read Q22 s = k0c /\ read Q23 s = k0d /\ read Q7 s = k0e /\ + byte_list_at ct ct_ptr len s /\ + byte_list_at (aes256_xts_decrypt ct (acc_len num_5blocks_adjusted num_blocks_adjusted) iv key1 key2) + pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) s` THEN + CONJ_TAC THENL + [ + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [ memory :> bytes128 pt_ptr; + memory :> bytes128 (word_add pt_ptr (word 16)); + memory :> bytes128 (word_add pt_ptr (word 32)); + memory :> bytes128 (word_add pt_ptr (word 48))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--2) THEN + + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (len:int64) (word 0x10)) < &0x0 + <=> ~(ival (len:int64) - &0x10 = ival (word_sub (len:int64) (word 0x10)))` MP_TAC THENL + [ MP_TAC (BITBLAST_RULE + `~(val (len:int64) < 0x40) ==> val len < 0x50 ==> + ival (word_sub len (word 0x10)) >= &0x0`) THEN + ASM_REWRITE_TAC[] THEN + MP_TAC (BITBLAST_RULE + `~(val (len:int64) < 0x40) ==> val len < 0x50 ==> + ival (len:int64) - &0x10 = ival (word_sub len (word 0x10))`) THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; + ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + MP_TAC (SPECL [`ct_ptr:int64`; `len:int64`; `ct:byte list`; `s2:armstate`] READ_LT_5BLOCK) THEN + ASM_SIMP_TAC[] THEN REPEAT STRIP_TAC THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (3--69) THEN + (* Prove Q6 stores initial tweak *) + FIRST_X_ASSUM(MP_TAC o SPEC `(calculate_tweak 0 iv key2)` + o MATCH_MP (MESON[] `read Q6 s = a ==> !a'. a = a' ==> read Q6 s = a'`)) THEN + ANTS_TAC THENL + [ REWRITE_TAC[CONJUNCT1 calculate_tweak; xts_init_tweak] THEN + EXPAND_TAC "key2" THEN AESENC_TAC; DISCH_TAC] THEN + + (* Simulating until branch for num_blocks adjustment *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (70--89) THEN + + (* Case split on whether there is a tail *) + FIRST_X_ASSUM MP_TAC THEN + COND_CASES_TAC THENL + [ + DISCH_TAC THEN + + SUBGOAL_THEN `val (tail_len:int64) = 0` SUBST_ALL_TAC THENL + [ UNDISCH_TAC `val (word_and (tail_len:int64) (word 0xf)) = 0x0` THEN + MP_TAC (SPECL [`len:int64`; `tail_len:int64`] TAIL_LEN_BOUND_THM) THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + SUBGOAL_THEN `val (word_and (tail_len:int64) (word 15)) = val tail_len` SUBST1_TAC THENL + [ REWRITE_TAC[VAL_WORD_AND_MASK_WORD; ARITH_RULE `15 = 2 EXP 4 - 1`] THEN + CONV_TAC NUM_REDUCE_CONV THEN ASM_REWRITE_TAC[] THEN + IMP_REWRITE_TAC[MOD_LT]; + ALL_TAC] THEN + SIMP_TAC[]; ALL_TAC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + + SUBGOAL_THEN `val (num_blocks_adjusted:int64) = 0x40` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_REWRITE_TAC[] + ; ALL_TAC ] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) = 0` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) = 0x40` THEN + SIMP_TAC[] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[VAL_WORD_0] + ; ALL_TAC ] THEN + + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (90--105) THEN + TWEAK_TAC `Q9:(armstate,int128)component` `2:num` `1:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (106--113) THEN + TWEAK_TAC `Q10:(armstate,int128)component` `3:num` `2:num` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (114--235) THEN + XTSDEC_TAC `Q0:(armstate,int128)component` `0` `0` THEN + XTSDEC_TAC `Q1:(armstate,int128)component` `0x10` `1` THEN + XTSDEC_TAC `Q24:(armstate,int128)component` `0x20` `2` THEN + XTSDEC_TAC `Q25:(armstate,int128)component` `0x30` `3` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (236--246) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `4:num` `3:num` THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_blocks] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0x40:num`; `pt_ptr:int64`; `(aes256_xts_decrypt ct 0x40 iv key1 key2):byte list`; + `s246:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + MP_TAC (SPECL [`4`; `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_4BLOCKS] ] + ; ALL_TAC + ] THEN + + (* There is a tail *) + DISCH_TAC THEN + (* Prove ~ tail_len = 0 *) + SUBGOAL_THEN `~(val (tail_len:int64) = 0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (word_and (tail_len:int64) (word 0xf)) = 0x0)` THEN + MP_TAC (SPECL [`len:int64`; `tail_len:int64`] TAIL_LEN_BOUND_THM) THEN + ASM_REWRITE_TAC[] THEN + SUBST1_TAC(ARITH_RULE `0xf = 2 EXP 4 - 1`) THEN + REWRITE_TAC[VAL_WORD_AND_MASK_WORD] THEN + NUM_REDUCE_TAC THEN IMP_REWRITE_TAC[MOD_LT] + ; ALL_TAC] THEN + (* Prove num_blocks_adjusted = word_sub num_blocks (word 0x10) *) + SUBGOAL_THEN `word_sub num_blocks (word 0x10) = num_blocks_adjusted:int64` ASSUME_TAC THENL + [ UNDISCH_TAC `(if val (tail_len:int64) = 0x0 + then (num_blocks:int64) + else word_sub num_blocks (word 0x10)) = num_blocks_adjusted` THEN + ASM_REWRITE_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) = 0x30` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + UNDISCH_TAC `val (num_blocks:int64) = 0x40` THEN + WORD_ARITH_TAC + ; ALL_TAC ] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) = 0` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + REWRITE_TAC[ASSUME `val (num_blocks_adjusted:int64) = 0x30`] THEN + WORD_ARITH_TAC + ; ALL_TAC ] THEN + + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (90--92) THEN + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (num_blocks_adjusted:int64) (word 0x10)) < &0x0 <=> + ~(ival (num_blocks_adjusted:int64) - &0x10 = + ival (word_sub (num_blocks_adjusted:int64) (word 0x10)))` MP_TAC THENL + [ SUBGOAL_THEN `num_blocks_adjusted:int64 = (word 0x30)` SUBST1_TAC THENL + [ UNDISCH_TAC `val (num_blocks_adjusted:int64) = 0x30` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + WORD_ARITH_TAC + ; ALL_TAC] THEN + DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (93--108) THEN + TWEAK_TAC `Q9:(armstate,int128)component` `2:num` `1:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (109--200) THEN + XTSDEC_TAC `Q0:(armstate,int128)component` `0` `0` THEN + XTSDEC_TAC `Q1:(armstate,int128)component` `0x10` `1` THEN + XTSDEC_TAC `Q24:(armstate,int128)component` `0x20` `2` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (201--211) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `3:num` `2:num` THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_blocks] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0x30:num`; `pt_ptr:int64`; `(aes256_xts_decrypt ct 0x30 iv key1 key2):byte list`; + `s211:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + MP_TAC (SPECL [`3`; `ct:byte list`; `iv:int128`; + `key1:int128 list`; `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_3BLOCKS] + ]; ALL_TAC] THEN + + (* Reuse the cipher stealing proof *) + MP_TAC CIPHER_STEALING_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + EXISTS_TAC `(word 0x40):int64` THEN + ASM_SIMP_TAC[] THEN + SUBGOAL_THEN `num_blocks:int64 = word 0x40` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_blocks:int64) = 0x40` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + REPEAT CONJ_TAC THENL [ + ASM_ARITH_TAC; + ASM_ARITH_TAC; + EXPAND_TAC "len" THEN AP_TERM_TAC THEN + UNDISCH_TAC `val (num_blocks:int64) = 0x40` THEN + WORD_ARITH_TAC; + ASM_SIMP_TAC[]; + EXPAND_TAC "num_blocks_adjusted" THEN + REWRITE_TAC[ASSUME `num_blocks:int64 = word 0x40`] + ] +);; + + +(* Proof: less than 6 blocks *) +let AES_XTS_DECRYPT_LT_6BLOCK_CORRECT = time prove( + `!ct_ptr pt_ptr ct key1_ptr key2_ptr iv_ptr iv len + k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e + k10 k11 k12 k13 k14 k15 k16 k17 k18 k19 k1a k1b k1c k1d k1e + pc. + nonoverlapping (word pc, LENGTH aes_xts_decrypt_mc) (pt_ptr, val len) + /\ nonoverlapping (ct_ptr, val len) (pt_ptr, val len) + /\ nonoverlapping (key1_ptr, 260) (pt_ptr, val len) + /\ ~(val len < 0x50) /\ val len < 0x60 /\ LENGTH ct = val len + /\ [k00; k01; k02; k03; k04; k05; k06; k07; k08; k09; k0a; k0b; k0c; k0d; k0e] = key1 + /\ [k10; k11; k12; k13; k14; k15; k16; k17; k18; k19; k1a; k1b; k1c; k1d; k1e] = key2 + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes_xts_decrypt_mc /\ + read PC s = word (pc + 0x1c) /\ + C_ARGUMENTS [ct_ptr; pt_ptr; len; key1_ptr; key2_ptr; iv_ptr] s /\ + byte_list_at ct ct_ptr len s /\ + read(memory :> bytes128 iv_ptr) s = iv /\ + set_key_schedule s key1_ptr k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e /\ + set_key_schedule s key2_ptr k10 k11 k12 k13 k14 k15 k16 k17 k18 k19 k1a k1b k1c k1d k1e) + (\s. read PC s = word (pc + 0xb58) /\ + byte_list_at (aes256_xts_decrypt ct (val len) iv key1 key2) pt_ptr len s + ) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes(pt_ptr, val len)]) + `, + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + SUBGOAL_THEN `word_add (word_and len (word 0xf)) + (word_and len (word 0xfffffffffffffff0)) = len:int64` ASSUME_TAC THENL + [REWRITE_TAC[word_split_lemma]; ALL_TAC] THEN + ABBREV_TAC `num_blocks:int64 = word_and len (word 0xfffffffffffffff0)` THEN + ABBREV_TAC `tail_len:int64 = word_and len (word 0xf)` THEN + ABBREV_TAC `num_blocks_adjusted = if val (tail_len:int64) = 0 + then num_blocks else word_sub (num_blocks:int64) (word 0x10)` THEN + ABBREV_TAC `num_5blocks_adjusted = (word (val (num_blocks_adjusted:int64) DIV 0x50)):int64` THEN + + SUBGOAL_THEN `val (num_blocks:int64) = 0x50` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks" THEN + REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `val (len:int64) DIV 16 = 5` SUBST1_TAC THENL + [ MATCH_MP_TAC(MESON[LE_ANTISYM] `m <= n /\ n <= m ==> m = n`) THEN + CONJ_TAC THENL [ ASM_ARITH_TAC; ASM_ARITH_TAC]; + ALL_TAC] THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) < 0x60` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + COND_CASES_TAC THENL[ + ASM_ARITH_TAC; + UNDISCH_TAC `val (num_blocks:int64) = 0x50` THEN + WORD_ARITH_TAC] + ; ALL_TAC] THEN + + ENSURES_SEQUENCE_TAC `pc + 0xa0c` + `\s. + read X0 s = word_add ct_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X1 s = word_add pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X3 s = key1_ptr /\ + read X21 s = tail_len /\ + read Q6 s = calculate_tweak (acc_blocks num_5blocks_adjusted num_blocks_adjusted T) iv key2 /\ + read X19 s = word 0x87 /\ + read Q16 s = k00 /\ read Q17 s = k01 /\ read Q12 s = k02 /\ read Q13 s = k03 /\ + read Q14 s = k04 /\ read Q15 s = k05 /\ read Q4 s = k06 /\ read Q5 s = k07 /\ + read Q18 s = k08 /\ read Q19 s = k09 /\ read Q20 s = k0a /\ read Q21 s = k0b /\ + read Q22 s = k0c /\ read Q23 s = k0d /\ read Q7 s = k0e /\ + byte_list_at ct ct_ptr len s /\ + byte_list_at (aes256_xts_decrypt ct (acc_len num_5blocks_adjusted num_blocks_adjusted) iv key1 key2) + pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) s` THEN + CONJ_TAC THENL + [ + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [ memory :> bytes128 pt_ptr; + memory :> bytes128 (word_add pt_ptr (word 16)); + memory :> bytes128 (word_add pt_ptr (word 32)); + memory :> bytes128 (word_add pt_ptr (word 48)); + memory :> bytes128 (word_add pt_ptr (word 64))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--2) THEN + + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (len:int64) (word 0x10)) < &0x0 + <=> ~(ival (len:int64) - &0x10 = ival (word_sub (len:int64) (word 0x10)))` MP_TAC THENL + [ MP_TAC (BITBLAST_RULE + `~(val (len:int64) < 0x50) ==> val len < 0x60 ==> + ival (word_sub len (word 0x10)) >= &0x0`) THEN + ASM_REWRITE_TAC[] THEN + MP_TAC (BITBLAST_RULE + `~(val (len:int64) < 0x50) ==> val len < 0x60 ==> + ival (len:int64) - &0x10 = ival (word_sub len (word 0x10))`) THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; + ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + MP_TAC (SPECL [`ct_ptr:int64`; `len:int64`; `ct:byte list`; `s2:armstate`] READ_LT_6BLOCK) THEN + ASM_SIMP_TAC[] THEN REPEAT STRIP_TAC THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (3--69) THEN + (* Prove Q6 stores initial tweak *) + FIRST_X_ASSUM(MP_TAC o SPEC `(calculate_tweak 0 iv key2)` + o MATCH_MP (MESON[] `read Q6 s = a ==> !a'. a = a' ==> read Q6 s = a'`)) THEN + ANTS_TAC THENL + [ REWRITE_TAC[CONJUNCT1 calculate_tweak; xts_init_tweak] THEN + EXPAND_TAC "key2" THEN AESENC_TAC; DISCH_TAC] THEN + + (* Simulating until branch for num_blocks adjustment *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (70--89) THEN + + (* Case split on whether there is a tail *) + FIRST_X_ASSUM MP_TAC THEN + COND_CASES_TAC THENL + [ + DISCH_TAC THEN + + SUBGOAL_THEN `val (tail_len:int64) = 0` SUBST_ALL_TAC THENL + [ UNDISCH_TAC `val (word_and (tail_len:int64) (word 0xf)) = 0x0` THEN + MP_TAC (SPECL [`len:int64`; `tail_len:int64`] TAIL_LEN_BOUND_THM) THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + SUBGOAL_THEN `val (word_and (tail_len:int64) (word 15)) = val tail_len` SUBST1_TAC THENL + [ REWRITE_TAC[VAL_WORD_AND_MASK_WORD; ARITH_RULE `15 = 2 EXP 4 - 1`] THEN + CONV_TAC NUM_REDUCE_CONV THEN ASM_REWRITE_TAC[] THEN + IMP_REWRITE_TAC[MOD_LT]; + ALL_TAC] THEN + SIMP_TAC[]; ALL_TAC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + + SUBGOAL_THEN `val (num_blocks_adjusted:int64) = 0x50` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_REWRITE_TAC[] + ; ALL_TAC ] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) = 1` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) = 0x50` THEN + SIMP_TAC[] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[VAL_WORD_1] + ; ALL_TAC ] THEN + SUBGOAL_THEN `~(val (word_sub (word_sub (num_blocks:int64) (word 0x50)) (word 0x40)) = 0x0)` ASSUME_TAC THENL + [ SUBGOAL_THEN `num_blocks:int64 = word 0x50` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_blocks:int64) = 0x50` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + WORD_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (word_sub (word_sub (num_blocks:int64) (word 0x50)) (word 0x30)) = 0x0)` ASSUME_TAC THENL + [ SUBGOAL_THEN `num_blocks:int64 = word 0x50` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_blocks:int64) = 0x50` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + WORD_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (word_sub (word_sub (num_blocks:int64) (word 0x50)) (word 0x20)) = 0x0)` ASSUME_TAC THENL + [ SUBGOAL_THEN `num_blocks:int64 = word 0x50` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_blocks:int64) = 0x50` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + WORD_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (word_sub (word_sub (num_blocks:int64) (word 0x50)) (word 0x10)) = 0x0)` ASSUME_TAC THENL + [ SUBGOAL_THEN `num_blocks:int64 = word 0x50` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_blocks:int64) = 0x50` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + WORD_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val (word_sub (num_blocks:int64) (word 0x50)) = 0x0` ASSUME_TAC THENL + [ SUBGOAL_THEN `num_blocks:int64 = word 0x50` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_blocks:int64) = 0x50` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + WORD_ARITH_TAC; ALL_TAC] THEN + + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (90--105) THEN + TWEAK_TAC `Q9:(armstate,int128)component` `2:num` `1:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (106--113) THEN + TWEAK_TAC `Q10:(armstate,int128)component` `3:num` `2:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (114--119) THEN + TWEAK_TAC `Q11:(armstate,int128)component` `4:num` `3:num` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (120--273) THEN + XTSDEC_TAC `Q0:(armstate,int128)component` `0` `0` THEN + TWEAK_TAC `Q6:(armstate,int128)component` `5:num` `4:num` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (274--281) THEN + XTSDEC_TAC `Q1:(armstate,int128)component` `0x10` `1` THEN + TWEAK_TAC `Q8:(armstate,int128)component` `6:num` `5:num` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (282--289) THEN + XTSDEC_TAC `Q24:(armstate,int128)component` `0x20` `2` THEN + TWEAK_TAC `Q9:(armstate,int128)component` `7:num` `6:num` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (290--297) THEN + XTSDEC_TAC `Q25:(armstate,int128)component` `0x30` `3` THEN + TWEAK_TAC `Q10:(armstate,int128)component` `8:num` `7:num` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (298--305) THEN + XTSDEC_TAC `Q26:(armstate,int128)component` `0x40` `4` THEN + TWEAK_TAC `Q11:(armstate,int128)component` `9:num` `8:num` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (306--320) THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_blocks] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0x50:num`; `pt_ptr:int64`; `(aes256_xts_decrypt ct 0x50 iv key1 key2):byte list`; + `s320:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + MP_TAC (SPECL [`5`; `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_5BLOCKS] ] + ; ALL_TAC + ] THEN + + (* There is a tail *) + DISCH_TAC THEN + (* Prove ~ tail_len = 0 *) + SUBGOAL_THEN `~(val (tail_len:int64) = 0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (word_and (tail_len:int64) (word 0xf)) = 0x0)` THEN + MP_TAC (SPECL [`len:int64`; `tail_len:int64`] TAIL_LEN_BOUND_THM) THEN + ASM_REWRITE_TAC[] THEN + SUBST1_TAC(ARITH_RULE `0xf = 2 EXP 4 - 1`) THEN + REWRITE_TAC[VAL_WORD_AND_MASK_WORD] THEN + NUM_REDUCE_TAC THEN IMP_REWRITE_TAC[MOD_LT] + ; ALL_TAC] THEN + (* Prove num_blocks_adjusted = word_sub num_blocks (word 0x10) *) + SUBGOAL_THEN `word_sub num_blocks (word 0x10) = num_blocks_adjusted:int64` ASSUME_TAC THENL + [ UNDISCH_TAC `(if val (tail_len:int64) = 0x0 + then (num_blocks:int64) + else word_sub num_blocks (word 0x10)) = num_blocks_adjusted` THEN + ASM_REWRITE_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) = 0x40` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + UNDISCH_TAC `val (num_blocks:int64) = 0x50` THEN + WORD_ARITH_TAC + ; ALL_TAC ] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) = 0` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + REWRITE_TAC[ASSUME `val (num_blocks_adjusted:int64) = 0x40`] THEN + WORD_ARITH_TAC + ; ALL_TAC ] THEN + + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (90--92) THEN + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (num_blocks_adjusted:int64) (word 0x10)) < &0x0 <=> + ~(ival (num_blocks_adjusted:int64) - &0x10 = + ival (word_sub (num_blocks_adjusted:int64) (word 0x10)))` MP_TAC THENL + [ SUBGOAL_THEN `num_blocks_adjusted:int64 = (word 0x40)` SUBST1_TAC THENL + [ UNDISCH_TAC `val (num_blocks_adjusted:int64) = 0x40` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + WORD_ARITH_TAC + ; ALL_TAC] THEN + DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (93--108) THEN + TWEAK_TAC `Q9:(armstate,int128)component` `2:num` `1:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (109--116) THEN + TWEAK_TAC `Q10:(armstate,int128)component` `3:num` `2:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (117--238) THEN + XTSDEC_TAC `Q0:(armstate,int128)component` `0` `0` THEN + XTSDEC_TAC `Q1:(armstate,int128)component` `0x10` `1` THEN + XTSDEC_TAC `Q24:(armstate,int128)component` `0x20` `2` THEN + XTSDEC_TAC `Q25:(armstate,int128)component` `0x30` `3` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (239--249) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `4:num` `3:num` THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_blocks] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0x40:num`; `pt_ptr:int64`; `(aes256_xts_decrypt ct 0x40 iv key1 key2):byte list`; + `s249:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + MP_TAC (SPECL [`4`; `ct:byte list`; `iv:int128`; + `key1:int128 list`; `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_4BLOCKS] + ]; ALL_TAC + ] THEN + + (* Reuse the cipher stealing proof *) + MP_TAC CIPHER_STEALING_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + EXISTS_TAC `(word 0x50):int64` THEN + ASM_SIMP_TAC[] THEN + SUBGOAL_THEN `num_blocks:int64 = word 0x50` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_blocks:int64) = 0x50` THEN + WORD_ARITH_TAC; ALL_TAC] THEN + REPEAT CONJ_TAC THENL [ + ASM_ARITH_TAC; + ASM_ARITH_TAC; + EXPAND_TAC "len" THEN AP_TERM_TAC THEN + UNDISCH_TAC `val (num_blocks:int64) = 0x50` THEN + WORD_ARITH_TAC; + ASM_SIMP_TAC[]; + EXPAND_TAC "num_blocks_adjusted" THEN + REWRITE_TAC[ASSUME `num_blocks:int64 = word 0x50`] + ] +);; + + + +let AES_XTS_DECRYPT_CORRECT = time prove( + `!ct_ptr pt_ptr ct key1_ptr key2_ptr iv_ptr iv len + k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e + k10 k11 k12 k13 k14 k15 k16 k17 k18 k19 k1a k1b k1c k1d k1e + pc. + nonoverlapping (word pc, LENGTH aes_xts_decrypt_mc) (pt_ptr, val len) + /\ nonoverlapping (ct_ptr, val len) (pt_ptr, val len) + /\ nonoverlapping (key1_ptr, 260) (pt_ptr, val len) + /\ val len >= 16 /\ val len <= 2 EXP 24 /\ LENGTH ct = val len + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes_xts_decrypt_mc /\ + read PC s = word (pc + 0x1c) /\ + C_ARGUMENTS [ct_ptr; pt_ptr; len; key1_ptr; key2_ptr; iv_ptr] s /\ + byte_list_at ct ct_ptr len s /\ + read(memory :> bytes128 iv_ptr) s = iv /\ + set_key_schedule s key1_ptr k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e /\ + set_key_schedule s key2_ptr k10 k11 k12 k13 k14 k15 k16 k17 k18 k19 k1a k1b k1c k1d k1e) + (\s. read PC s = word (pc + 0xb58) /\ + byte_list_at (aes256_xts_decrypt ct (val len) iv + [k00; k01; k02; k03; k04; k05; k06; k07; k08; k09; k0a; k0b; k0c; k0d; k0e] + [k10; k11; k12; k13; k14; k15; k16; k17; k18; k19; k1a; k1b; k1c; k1d; k1e]) + pt_ptr len s + ) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes(pt_ptr, val len)]) + `, + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + (* Break len into full blocks and tail *) + SUBGOAL_THEN `word_add (word_and len (word 0xf)) + (word_and len (word 0xfffffffffffffff0)) = len:int64` ASSUME_TAC THENL + [REWRITE_TAC[word_split_lemma]; ALL_TAC] THEN + ABBREV_TAC `num_blocks:int64 = word_and len (word 0xfffffffffffffff0)` THEN + ABBREV_TAC `tail_len:int64 = word_and len (word 0xf)` THEN + ABBREV_TAC `key1:int128 list = [k00; k01; k02; k03; k04; k05; k06; k07; k08; k09; k0a; k0b; k0c; k0d; k0e]` THEN + ABBREV_TAC `key2:int128 list = [k10; k11; k12; k13; k14; k15; k16; k17; k18; k19; k1a; k1b; k1c; k1d; k1e]` THEN + + (* Case splits on length: + len < 16 -- error case + len < 32 -- one block, or one block and a tail + len < 48 -- two blocks, or two blocks and a tail + len < 64 -- three blocks, or three blocks and a tail + len < 80 -- four blocks, or four blocks and a tail + len < 96 -- five blocks, or five blocks and a tail + len >= 96 -- six blocks and up + + Note: for decrypt, because of cipherstealing, there needs to be one extra + block at the end together with the tail to be processed for cipherstealing + *) + ASM_CASES_TAC `val (len:int64) < 0x60` THENL [ + ASM_CASES_TAC `val (len:int64) < 0x20` THENL + [ + MP_TAC AES_XTS_DECRYPT_LT_2BLOCK_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + ASM_SIMP_TAC[]; + ALL_TAC + ] THEN + + ASM_CASES_TAC `val (len:int64) < 0x30` THENL + [ + MP_TAC AES_XTS_DECRYPT_LT_3BLOCK_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + ASM_SIMP_TAC[]; + ALL_TAC + ] THEN + + ASM_CASES_TAC `val (len:int64) < 0x40` THENL + [ + MP_TAC AES_XTS_DECRYPT_LT_4BLOCK_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + ASM_SIMP_TAC[]; + ALL_TAC + ] THEN + + ASM_CASES_TAC `val (len:int64) < 0x50` THENL + [ + MP_TAC AES_XTS_DECRYPT_LT_5BLOCK_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + ASM_SIMP_TAC[]; + ALL_TAC + ] THEN + + ASM_CASES_TAC `val (len:int64) < 0x60` THENL + [ + MP_TAC AES_XTS_DECRYPT_LT_6BLOCK_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + ASM_SIMP_TAC[]; + ALL_TAC + ] THEN + + ASM_ARITH_TAC + ; ALL_TAC] THEN + + ABBREV_TAC `num_blocks_adjusted = if val (tail_len:int64) = 0 + then num_blocks else word_sub (num_blocks:int64) (word 0x10)` THEN + ABBREV_TAC `num_5blocks_adjusted = (word (val (num_blocks_adjusted:int64) DIV 0x50)):int64` THEN + + (* Prove once and for all the bounds for num_blocks, num_blocks_adjusted + and num_5blocks_adjusted *) + SUBGOAL_THEN `~(val (num_blocks:int64) < 96)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (len:int64) < 0x60)` THEN + UNDISCH_TAC `word_and len (word 0xfffffffffffffff0) = (num_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `num_blocks:int64`] NUM_BLOCKS_LO_BOUND_THM) THEN + SIMP_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks:int64) <= 2 EXP 24` ASSUME_TAC THENL + [ UNDISCH_TAC `val (len:int64) <= 2 EXP 24` THEN + UNDISCH_TAC `word_and len (word 0xfffffffffffffff0) = (num_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `num_blocks:int64`] NUM_BLOCKS_HI_BOUND_THM) THEN + SIMP_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_blocks_adjusted:int64) < 80)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (num_blocks:int64) < 96)` THEN + UNDISCH_TAC `(if val (tail_len:int64) = 0x0 + then (num_blocks:int64) + else word_sub num_blocks (word 0x10)) = + num_blocks_adjusted` THEN + MP_TAC (SPECL [`num_blocks:int64`;`tail_len:int64`;`num_blocks_adjusted:int64`] + NUM_BLOCKS_ADJUSTED_LO_BOUND_THM) THEN SIMP_TAC[] + ; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) <= 2 EXP 24` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_blocks:int64) <= 2 EXP 24` THEN + SUBGOAL_THEN `~(val (num_blocks:int64) < 16)` MP_TAC THENL + [UNDISCH_TAC `~(val (num_blocks:int64) < 96)` THEN ARITH_TAC; ALL_TAC] THEN + UNDISCH_TAC `(if val (tail_len:int64) = 0x0 + then (num_blocks:int64) + else word_sub num_blocks (word 0x10)) = + num_blocks_adjusted` THEN + MP_TAC (SPECL [`num_blocks:int64`;`tail_len:int64`;`num_blocks_adjusted:int64`] + NUM_BLOCKS_ADJUSTED_HI_BOUND_THM) THEN SIMP_TAC[] + ; ALL_TAC] THEN + SUBGOAL_THEN `0 < val (num_5blocks_adjusted:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `word (val (num_blocks_adjusted:int64) DIV 0x50) = (num_5blocks_adjusted:int64)` THEN + UNDISCH_TAC `~(val (num_blocks_adjusted:int64) < 0x50)` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + MP_TAC (SPECL [`num_blocks_adjusted:int64`; `num_5blocks_adjusted:int64`] + NUM_5BLOCKS_ADJUSTED_LO_BOUND_THM) THEN SIMP_TAC[] + ; ALL_TAC] THEN + SUBGOAL_THEN `val (tail_len:int64) < 16` ASSUME_TAC THENL + [ EXPAND_TAC "tail_len" THEN + REWRITE_TAC[ARITH_RULE `0xf = 2 EXP 4 - 1`] THEN + REWRITE_TAC[VAL_WORD_AND_MASK_WORD] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SIMP_TAC[MOD_LT_EQ] THEN + CONV_TAC NUM_REDUCE_CONV + ; ALL_TAC] THEN + (* relationship between variables *) + SUBGOAL_THEN `val (num_blocks:int64) <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks" THEN SIMP_TAC[NUM_BLOCKS_LT_LEN_THM]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_blocks_adjusted:int64) <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_blocks_adjusted" THEN + COND_CASES_TAC THENL + [ ASM_SIMP_TAC[]; + SUBGOAL_THEN `~(val (num_blocks:int64) < 16)` MP_TAC THENL + [UNDISCH_TAC `~(val (num_blocks:int64) < 96)` THEN ARITH_TAC; ALL_TAC] THEN + UNDISCH_TAC `word_and (len:int64) (word 0xfffffffffffffff0) = (num_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `num_blocks:int64`] NUM_BLOCKS_ADJUSTED_LT_LEN_THM) THEN + SIMP_TAC[]]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + REWRITE_TAC [VAL_WORD; DIMINDEX_64] THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks_adjusted" THEN + REWRITE_TAC [VAL_WORD; DIMINDEX_64] THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= val (len:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + + (* Verify properties of the program until the beginning of the loop. + The properties include the invariant, and a bunch of other initial setup. + *) + ENSURES_SEQUENCE_TAC `pc + 0x170` + `\s. + read X0 s = ct_ptr /\ + read X1 s = pt_ptr /\ + read X2 s = num_blocks_adjusted /\ + read X3 s = key1_ptr /\ + read X21 s = tail_len /\ + read X8 s = num_5blocks_adjusted /\ + read Q6 s = calculate_tweak 0 iv key2 /\ + read Q8 s = calculate_tweak 1 iv key2 /\ + read Q9 s = calculate_tweak 2 iv key2 /\ + read Q10 s = calculate_tweak 3 iv key2 /\ + read Q11 s = calculate_tweak 4 iv key2 /\ + read X19 s = word 0x87 /\ + read X10 s = word_subword (calculate_tweak 4 iv key2) (64,64) /\ + read X9 s = word_zx (calculate_tweak 4 iv key2) /\ + read Q16 s = k00 /\ read Q17 s = k01 /\ read Q12 s = k02 /\ read Q13 s = k03 /\ + read Q14 s = k04 /\ read Q15 s = k05 /\ read Q4 s = k06 /\ read Q5 s = k07 /\ + read Q18 s = k08 /\ read Q19 s = k09 /\ read Q20 s = k0a /\ read Q21 s = k0b /\ + read Q22 s = k0c /\ read Q23 s = k0d /\ read Q7 s = k0e /\ + byte_list_at ct ct_ptr len s /\ + byte_list_at (aes256_xts_decrypt ct 0 iv key1 key2) pt_ptr (word 0) s /\ + set_key_schedule s key1_ptr k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e` THEN + CONJ_TAC THENL + [ + (* ===> Symbolic Simulation: Start symbolic simulation*) + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--2) THEN + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (len:int64) (word 0x10)) < &0x0 + <=> ~(ival (len:int64) - &0x10 = ival (word_sub (len:int64) (word 0x10)))` MP_TAC THENL + [ + MP_TAC (BITBLAST_RULE + `val (len:int64) >= 0x10 ==> val len <= 2 EXP 0x18 ==> + ival (word_sub len (word 0x10)) >= &0x0`) THEN + ASM_REWRITE_TAC[] THEN + MP_TAC (BITBLAST_RULE + `val (len:int64) >= 0x10 ==> val len <= 2 EXP 0x18 ==> + ival (len:int64) - &0x10 = ival (word_sub len (word 0x10))`) THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; + ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + (* ===> Symbolic Simulation: Symbolic execution for initialization of tweak *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (3--69) THEN + (* Prove Q6 stores initial tweak *) + FIRST_X_ASSUM(MP_TAC o SPEC `(calculate_tweak 0 iv key2)` + o MATCH_MP (MESON[] `read Q6 s = a ==> !a'. a = a' ==> read Q6 s = a'`)) THEN + ANTS_TAC THENL + [REWRITE_TAC[CONJUNCT1 calculate_tweak; xts_init_tweak] THEN + EXPAND_TAC "key2" THEN AESENC_TAC; DISCH_TAC] THEN + (* ===> Symbolic Simulation: Symbolic simulating untill next branch *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (70--89) THEN + (* Case split on whether there is a tail *) + FIRST_X_ASSUM MP_TAC THEN + COND_CASES_TAC THENL + [ + (* If there is no tail *) + DISCH_TAC THEN + (* Prove val tail_len = 0 and num_blocks = num_blocks_adjusted *) + SUBGOAL_THEN `val (tail_len:int64) = 0` ASSUME_TAC THENL + [ UNDISCH_TAC `val (word_and (tail_len:int64) (word 0xf)) = 0x0` THEN + MP_TAC (SPECL [`len:int64`; `tail_len:int64`] TAIL_LEN_BOUND_THM) THEN + ASM_REWRITE_TAC[] THEN + SUBST1_TAC(ARITH_RULE `0xf = 2 EXP 4 - 1`) THEN + REWRITE_TAC[VAL_WORD_AND_MASK_WORD] THEN + NUM_REDUCE_TAC THEN IMP_REWRITE_TAC[MOD_LT]; ALL_TAC] THEN + SUBGOAL_THEN `num_blocks_adjusted:int64 = num_blocks:int64` ASSUME_TAC THENL + [ UNDISCH_TAC `(if val (tail_len:int64) = 0x0 + then (num_blocks:int64) + else word_sub num_blocks (word 0x10)) = + num_blocks_adjusted` THEN + UNDISCH_TAC `val (tail_len:int64) = 0` THEN + SIMP_TAC[]; ALL_TAC] THEN + (* Prove x9, x10 stores lower and upper halves and Q8 stores the full tweak *) + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (90--93) THEN + (* Prove the optimized udiv is basically udiv *) + SUBGOAL_THEN `word_ushr + ((word ((val (num_blocks:int64) * 0xcccccccccccccccd) DIV 0x2 EXP 0x40)):int64) + 0x6 = + word ((val num_blocks) DIV 0x50)` ASSUME_TAC THENL + [ MP_TAC (BITBLAST_RULE `val (num_blocks:int64) < 2 EXP 64`) THEN + REWRITE_TAC[word_ushr] THEN + MP_TAC (SPECL [`val (num_blocks:int64)`] UDIV_OPT_THM) THEN SIMP_TAC[] + ; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + (* Eliminate 1 block case *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (94--95) THEN + SUBGOAL_THEN `~(val (num_blocks:int64) < 0x20)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (num_blocks:int64) < 0x60)` THEN ARITH_TAC + ; POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]))] THEN + (* Eliminate 2 blocks case *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (96--97) THEN + SUBGOAL_THEN `~(val (num_blocks:int64) < 0x30)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (num_blocks:int64) < 0x60)` THEN ARITH_TAC + ; POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]))] THEN + (* Eliminate 3 blocks case and prove Q9 stores tweak 2 *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (98--105) THEN + SUBGOAL_THEN `~(val (num_blocks:int64) < 0x40)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (num_blocks:int64) < 0x60)` THEN ARITH_TAC + ; POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]))] THEN + TWEAK_TAC `Q9:(armstate,int128)component` `2:num` `1:num` THEN + (* Eliminate 4 blocks case and Q10 stores tweak 3 *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (106--113) THEN + SUBGOAL_THEN `~(val (num_blocks:int64) < 0x50)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (num_blocks:int64) < 0x60)` THEN ARITH_TAC + ; POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]))] THEN + TWEAK_TAC `Q10:(armstate,int128)component` `3:num` `2:num` THEN + (* Must have 5 blocks, execute until start of loop. Q11 stores tweak 4 *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (114--122) THEN + TWEAK_TAC `Q11:(armstate,int128)component` `4:num` `3:num` THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + EXPAND_TAC "num_5blocks_adjusted" THEN + EXPAND_TAC "num_blocks_adjusted" THEN + ASM_REWRITE_TAC[]; + ASM_REWRITE_TAC[byte_list_at]; + REWRITE_TAC[aes256_xts_decrypt] THEN + CONV_TAC (DEPTH_CONV NUM_RED_CONV) THEN + ASM_REWRITE_TAC[byte_list_at] THEN + REWRITE_TAC[VAL_WORD_0] THEN ARITH_TAC; + ASM_REWRITE_TAC[set_key_schedule]] + ; ALL_TAC + ] THEN + (* If there is a tail *) + DISCH_TAC THEN + (* Prove ~ tail_len = 0 *) + SUBGOAL_THEN `~(val (tail_len:int64) = 0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (word_and (tail_len:int64) (word 0xf)) = 0x0)` THEN + MP_TAC (SPECL [`len:int64`; `tail_len:int64`] TAIL_LEN_BOUND_THM) THEN + ASM_REWRITE_TAC[] THEN + SUBST1_TAC(ARITH_RULE `0xf = 2 EXP 4 - 1`) THEN + REWRITE_TAC[VAL_WORD_AND_MASK_WORD] THEN + NUM_REDUCE_TAC THEN IMP_REWRITE_TAC[MOD_LT] + ; ALL_TAC] THEN + (* Prove num_blocks_adjusted = word_sub num_blocks (word 0x10) *) + SUBGOAL_THEN `word_sub num_blocks (word 0x10) = num_blocks_adjusted:int64` ASSUME_TAC THENL + [ UNDISCH_TAC `(if val (tail_len:int64) = 0x0 + then (num_blocks:int64) + else word_sub num_blocks (word 0x10)) = num_blocks_adjusted` THEN + ASM_REWRITE_TAC[]; ALL_TAC] THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (90--92) THEN + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (num_blocks_adjusted:int64) (word 0x10)) < &0x0 <=> + ~(ival (num_blocks_adjusted:int64) - &0x10 = + ival (word_sub (num_blocks_adjusted:int64) (word 0x10)))` MP_TAC THENL + [ + MP_TAC (BITBLAST_RULE + `~(val (num_blocks_adjusted:int64) < 0x50) ==> + val num_blocks_adjusted <= 2 EXP 0x18 ==> + ival (word_sub num_blocks_adjusted (word 0x10)) >= &0x0`) THEN + ASM_REWRITE_TAC[] THEN + MP_TAC (BITBLAST_RULE + `~(val (num_blocks_adjusted:int64) < 0x50) ==> + val num_blocks_adjusted <= 2 EXP 0x18 ==> + ival (num_blocks_adjusted:int64) - &0x10 = ival (word_sub num_blocks_adjusted (word 0x10))`) THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; + ALL_TAC] THEN + DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + (* Prove x9, x10 stores lower and upper halves and Q8 stores the full tweak *) + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (93--96) THEN + (* Prove the optimized udiv is basically udiv *) + SUBGOAL_THEN `word_ushr + ((word ((val (num_blocks_adjusted:int64) * 0xcccccccccccccccd) DIV 0x2 EXP 0x40)):int64) + 0x6 = word ((val num_blocks_adjusted) DIV 0x50)` ASSUME_TAC THENL + [ MP_TAC (BITBLAST_RULE `val (num_blocks_adjusted:int64) < 2 EXP 64`) THEN + REWRITE_TAC[word_ushr] THEN + MP_TAC (SPECL [`val (num_blocks_adjusted:int64)`] UDIV_OPT_THM) THEN SIMP_TAC[] + ; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + (* Eliminate 1 block case *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (97--98) THEN + SUBGOAL_THEN `~(val (num_blocks_adjusted:int64) < 0x20)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (num_blocks_adjusted:int64) < 0x50)` THEN ARITH_TAC + ; POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]))] THEN + (* Eliminate 2 blocks case *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (99--100) THEN + SUBGOAL_THEN `~(val (num_blocks_adjusted:int64) < 0x30)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (num_blocks_adjusted:int64) < 0x50)` THEN ARITH_TAC + ; POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]))] THEN + (* Eliminate 3 blocks case and prove Q9 stores tweak 2 *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (101--108) THEN + SUBGOAL_THEN `~(val (num_blocks_adjusted:int64) < 0x40)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (num_blocks_adjusted:int64) < 0x50)` THEN ARITH_TAC + ; POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]))] THEN + TWEAK_TAC `Q9:(armstate,int128)component` `2:num` `1:num` THEN + (* Eliminate 4 blocks case and Q10 stores tweak 3 *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (109--116) THEN + TWEAK_TAC `Q10:(armstate,int128)component` `3:num` `2:num` THEN + (* Must have 5 blocks, execute until start of loop. Q11 stores tweak 4 *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (117--125) THEN + TWEAK_TAC `Q11:(armstate,int128)component` `4:num` `3:num` THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ ASM_REWRITE_TAC[byte_list_at]; + REWRITE_TAC[aes256_xts_decrypt] THEN + CONV_TAC (DEPTH_CONV NUM_RED_CONV) THEN + ASM_REWRITE_TAC[byte_list_at] THEN + REWRITE_TAC [VAL_WORD_0] THEN ARITH_TAC; + ASM_REWRITE_TAC[set_key_schedule]] + ; ALL_TAC + ] THEN + + (* Prove property until right before cipher stealing *) + ENSURES_SEQUENCE_TAC `pc + 0xa0c` + `\s. + read X0 s = word_add ct_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X1 s = word_add pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) /\ + read X3 s = key1_ptr /\ + read X21 s = tail_len /\ + read Q6 s = calculate_tweak (acc_blocks num_5blocks_adjusted num_blocks_adjusted T) iv key2 /\ + read X19 s = word 0x87 /\ + read Q16 s = k00 /\ read Q17 s = k01 /\ read Q12 s = k02 /\ read Q13 s = k03 /\ + read Q14 s = k04 /\ read Q15 s = k05 /\ read Q4 s = k06 /\ read Q5 s = k07 /\ + read Q18 s = k08 /\ read Q19 s = k09 /\ read Q20 s = k0a /\ read Q21 s = k0b /\ + read Q22 s = k0c /\ read Q23 s = k0d /\ read Q7 s = k0e /\ + byte_list_at ct ct_ptr len s /\ + byte_list_at (aes256_xts_decrypt ct (acc_len num_5blocks_adjusted num_blocks_adjusted) iv key1 key2) + pt_ptr (word (acc_len num_5blocks_adjusted num_blocks_adjusted)) s` THEN + CONJ_TAC THENL + [ + (* Setting up the loop invariant *) + + (* Invariant: + X0 holds ct_ptr + i*0x50 + X1 hols pt_ptr + i*0x50 + X3 holds key1_ptr + X21 holds tail_len + + X2 holds number of blocks left + X8 holds number of 5xblocks left + Q6, Q8, Q9, Q10, Q11 holds the next 5 tweaks + X10 stores upper half of last tweak + X9 stores lower half of last tweak + X19 holds 0x87 + Q16, Q17, Q12, Q13, Q14, Q15, Q4, Q5, Q18, Q19, Q20, Q21, Q22, Q23, Q7 stores the key1 + Memory: ct_ptr points to the input data blocks + Memory: Up to the new five blocks in output pt_ptr matche the specification + *) + + ENSURES_WHILE_PAUP_TAC + `0` + `val (num_5blocks_adjusted:int64)` + `pc + 0x170` + `pc + 0x460` + `\i s. + (read X0 s = word_add ct_ptr (word_mul (word 0x50) (word i)) /\ + read X1 s = word_add pt_ptr (word_mul (word 0x50) (word i)) /\ + read X3 s = key1_ptr /\ + read X21 s = tail_len /\ + read X2 s = word_sub num_blocks_adjusted (word_mul (word 0x50) (word i)) /\ + read X8 s = word_sub num_5blocks_adjusted (word i) /\ + read Q6 s = calculate_tweak (i * 5) iv key2 /\ + read Q8 s = calculate_tweak (i * 5 + 1) iv key2 /\ + read Q9 s = calculate_tweak (i * 5 + 2) iv key2 /\ + read Q10 s = calculate_tweak (i * 5 + 3) iv key2 /\ + read Q11 s = calculate_tweak (i * 5 + 4) iv key2 /\ + read X19 s = word 0x87 /\ + read X10 s = word_subword (calculate_tweak (i * 5 + 4) iv key2) (64,64) /\ + read X9 s = word_zx (calculate_tweak (i * 5 + 4) iv key2) /\ + read Q16 s = k00 /\ read Q17 s = k01 /\ read Q12 s = k02 /\ read Q13 s = k03 /\ + read Q14 s = k04 /\ read Q15 s = k05 /\ read Q4 s = k06 /\ read Q5 s = k07 /\ + read Q18 s = k08 /\ read Q19 s = k09 /\ read Q20 s = k0a /\ read Q21 s = k0b /\ + read Q22 s = k0c /\ read Q23 s = k0d /\ read Q7 s = k0e /\ + byte_list_at ct ct_ptr len s /\ + byte_list_at (aes256_xts_decrypt ct (80 * i) iv key1 key2) pt_ptr (word (80 * i)) s) /\ + // loop backedge condition + (read ZF s <=> i = val (num_5blocks_adjusted:int64))` THEN + ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL + [ + (* Subgoal 1. Bound of loop is not zero -- automatically discharged by asm *) + (* Subgoal 2. Invariant holds before entering the loop *) + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + WORD_ARITH_TAC; WORD_ARITH_TAC; + WORD_ARITH_TAC; WORD_ARITH_TAC; + CONV_TAC NUM_REDUCE_CONV; + CONV_TAC NUM_REDUCE_CONV; + CONV_TAC NUM_REDUCE_CONV; + CONV_TAC NUM_REDUCE_CONV; + CONV_TAC NUM_REDUCE_CONV; + CONV_TAC NUM_REDUCE_CONV; + CONV_TAC NUM_REDUCE_CONV; + CONV_TAC (ONCE_DEPTH_CONV NUM_REDUCE_CONV) THEN REWRITE_TAC[VAL_WORD_0] THEN ARITH_TAC + ]; + + (* Subgoal 3: loop body *) + REPEAT STRIP_TAC THEN + + (* An arithmetic rule for discharging subgoal in the following ENSURES_FRAME_SUBSUMED tactic *) + SUBGOAL_THEN `i * 0x50 + 0x50 <= val (len:int64)` ASSUME_TAC THENL + [ SUBGOAL_THEN `i + 1 <= val (num_5blocks_adjusted:int64)` MP_TAC THENL + [ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `(i + 1) * 0x50 <= val (len:int64)` MP_TAC THENL + [ASM_ARITH_TAC; ALL_TAC] THEN + ARITH_TAC; ALL_TAC] THEN + + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes128 (word_add pt_ptr (word (0x50 * i))); + memory :> bytes128 (word_add pt_ptr (word (0x50 * i + 0x10))); + memory :> bytes128 (word_add pt_ptr (word (0x50 * i + 0x20))); + memory :> bytes128 (word_add pt_ptr (word (0x50 * i + 0x30))); + memory :> bytes128 (word_add pt_ptr (word (0x50 * i + 0x40)))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + (* ===> Symbolic Simulation: Start symbolic simulation*) + ASM_REWRITE_TAC[byte_list_at] THEN + + ENSURES_INIT_TAC "s0" THEN + (* List values for ct_ptr + [0 .. 0x40] *) + MP_TAC (SPECL [`ct_ptr:int64`; `i:num`; `len:int64`; `ct:byte list`; `s0:armstate`] READ_BL_LEMMA) THEN + ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--151) THEN + (* Prove Q0, Q1, Q24, Q25, Q26 stores correct plaintext *) + (* and prove Q6, Q8, Q9, Q10, Q11 stores correct tweak *) + XTSDEC_TAC `Q0:(armstate,int128)component` `i * 0x50` `i * 0x5` THEN + TWEAK_TAC `Q6:(armstate,int128)component` `i * 5 + 5` `i * 5 + 4` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (152--159) THEN + XTSDEC_TAC `Q1:(armstate,int128)component` `i * 0x50 + 0x10` `i * 0x5 + 0x1` THEN + TWEAK_TAC `Q8:(armstate,int128)component` `i * 5 + 6` `i * 5 + 5` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (160--167) THEN + XTSDEC_TAC `Q24:(armstate,int128)component` `i * 0x50 + 0x20` `i * 0x5 + 0x2` THEN + TWEAK_TAC `Q9:(armstate,int128)component` `i * 5 + 7` `i * 5 + 6` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (168--175) THEN + XTSDEC_TAC `Q25:(armstate,int128)component` `i * 0x50 + 0x30` `i * 0x5 + 0x3` THEN + TWEAK_TAC `Q10:(armstate,int128)component` `i * 5 + 8` `i * 5 + 7` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (176--183) THEN + XTSDEC_TAC `Q26:(armstate,int128)component` `i * 0x50 + 0x40` `i * 0x5 + 0x4` THEN + TWEAK_TAC `Q11:(armstate,int128)component` `i * 5 + 9` `i * 5 + 8` THEN + + (* The following lemmas are for NONSELFMODIFYING_STATE_UPDATE_TAC when store back to pt_ptr, + and for the MAYCHANGE clauses *) + RULE_ASSUM_TAC(REWRITE_RULE + [WORD_RULE `word_mul (word 0x50) (word i):int64 = word(0x50 * i)`]) THEN + + (* Rewrite to help reasoning about nonoverlapping + so that the universally quantified assumption stays. + See: https://hol-light.zulipchat.com/#narrow/channel/474190-s2n-bignum/topic/.E2.9C.94.20Symbolic.20simulation.20removed.20assumption/with/541554894 *) + SUBGOAL_THEN `val ((word (0x50 * i)):int64) = 0x50 * i` ASSUME_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN ASM_ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + (* Simulate until end of loop *) + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (184--188) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ REWRITE_TAC[WORD_RULE `word_mul (word 0x50) (word (i + 1)):int64 = word_add (word(0x50 * i)) (word 0x50)`] THEN + REWRITE_TAC[WORD_ADD_ASSOC]; + REWRITE_TAC[WORD_RULE `word_mul (word 0x50) (word (i + 1)):int64 = word_add (word(0x50 * i)) (word 0x50)`] THEN + REWRITE_TAC[WORD_ADD_ASSOC]; + REWRITE_TAC[WORD_RULE `word_mul (word 0x50) (word (i + 1)):int64 = word_add (word(0x50 * i)) (word 0x50)`] THEN + CONV_TAC WORD_RULE; + CONV_TAC WORD_RULE; + REWRITE_TAC[WORD_RULE `(i + 0x1) * 0x5 = i * 0x5 + 0x5`]; + REWRITE_TAC[WORD_RULE `(i + 0x1) * 0x5 + 0x1 = i * 0x5 + 0x6`]; + REWRITE_TAC[WORD_RULE `(i + 0x1) * 0x5 + 0x2 = i * 0x5 + 0x7`]; + REWRITE_TAC[WORD_RULE `(i + 0x1) * 0x5 + 0x3 = i * 0x5 + 0x8`]; + REWRITE_TAC[WORD_RULE `(i + 0x1) * 0x5 + 0x4 = i * 0x5 + 0x9`]; + REWRITE_TAC[WORD_RULE `(i + 0x1) * 0x5 + 0x4 = i * 0x5 + 0x9`]; + REWRITE_TAC[WORD_RULE `(i + 0x1) * 0x5 + 0x4 = i * 0x5 + 0x9`]; + (* The following is the main proof for inductive step *) + REWRITE_TAC[ARITH_RULE `0x50 * (i + 0x1) = 0x50 * i + 0x50`] THEN + SUBGOAL_THEN `val ((word (0x50 * i + 0x50)):int64) = 0x50 * i + 0x50` ASSUME_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `i * 0x50 + 0x50 <= val (len:int64)` THEN + UNDISCH_TAC `val (len:int64) <= 2 EXP 24` THEN + ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + + (* Remove quantifier *) + UNDISCH_TAC + `forall i'. + i' < 0x50 * i + ==> read (memory :> bytes8 (word_add pt_ptr (word i'))) s188 = + EL i' (aes256_xts_decrypt ct (0x50 * i) iv key1 key2)` THEN + MP_TAC (SPECL [`0x50 * i + 0x50:num`; `pt_ptr:int64`; `(aes256_xts_decrypt ct (0x50 * i + 0x50) iv key1 key2):byte list`; `s188:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x50 = 0x10 * (5 * i + 5)`; + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + MP_TAC (SPECL [`0x50 * i:num`; `pt_ptr:int64`; `(aes256_xts_decrypt ct (0x50 * i) iv key1 key2):byte list`; `s188:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + DISCH_TAC THEN + + (* Prove one block equivalence and reduce proving the following: + `read (memory :> bytes (pt_ptr,0x50 * i + 0x50)) s188 = + num_of_bytelist + (aes256_xts_decrypt ct (0x50 * i + 0x50) iv key1 key2)` + to: + `read (memory :> bytes (pt_ptr,0x10 * 0x5 * i + 0x40)) s188 = + num_of_bytelist + (aes256_xts_decrypt ct (0x10 * 0x5 * i + 0x40) iv key1 key2)` *) + IMP_REWRITE_TAC[ARITH_RULE `0x50 * i + 0x50 = (0x50 * i + 0x40) + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `(aes256_xts_decrypt ct (0x50 * i + 0x50) iv key1 key2)` THEN + REPEAT CONJ_TAC THENL [ + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x40) + 0x10 = 0x50 * i + 0x50`]; + + MP_TAC (SPECL [`0x5 * i + 0x5:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x50 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * i + 0x50) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 80 = 16 * (5 * i + 5)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x50) DIV 0x10 = 0x5 * i + 0x5`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x5 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x5) - 0x2 = 0x5 * i + 0x3`; + ARITH_RULE `(0x5 * i + 0x5) - 0x1 = 0x5 * i + 0x4`] THEN + + MP_TAC (SPECL [`0`;`5 * i + 3:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i + 3 < 0)`; + ARITH_RULE `((0x5 * i + 0x3) - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x40`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * i + 4:num`; `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 + 0x40 = (i * 0x5 + 0x4) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x40 = 0x10 * (5 * i + 4)`; + ARITH_RULE `0x50 * i + 0x50 = 0x10 * (5 * i + 4) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + IMP_REWRITE_TAC[ARITH_RULE `0x50 * i + 0x40 = (0x50 * i + 0x30) + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `(aes256_xts_decrypt ct (0x50 * i + 0x40) iv key1 key2)` THEN + REPEAT CONJ_TAC THENL [ + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x30) + 0x10 = 0x50 * i + 0x40`] THEN + + MP_TAC (SPECL [`0x5 * i + 0x4:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES]; + + MP_TAC (SPECL [`0x5 * i + 0x4:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x40 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * i + 0x40) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 64 = 16 * (5 * i + 4)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x40) DIV 0x10 = 0x5 * i + 0x4`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x4 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x4) - 0x2 = 0x5 * i + 0x2`; + ARITH_RULE `(0x5 * i + 0x4) - 0x1 = 0x5 * i + 0x3`] THEN + + MP_TAC (SPECL [`0`;`5 * i + 2:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i + 2 < 0)`; + ARITH_RULE `((0x5 * i + 0x2) - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x30`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * i + 3:num`; `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 + 0x30= (i * 0x5 + 0x3) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x30 = 0x10 * (5 * i + 3)`; + ARITH_RULE `0x50 * i + 0x40 = 0x10 * (5 * i + 3) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + IMP_REWRITE_TAC[ARITH_RULE `0x50 * i + 0x30 = (0x50 * i + 0x20) + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `(aes256_xts_decrypt ct (0x50 * i + 0x30) iv key1 key2)` THEN + REPEAT CONJ_TAC THENL [ + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x20) + 0x10 = 0x50 * i + 0x30`] THEN + + MP_TAC (SPECL [`0x5 * i + 0x3:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES]; + + MP_TAC (SPECL [`0x5 * i + 0x3:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x30 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * i + 0x30) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 48 = 16 * (5 * i + 3)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x30) DIV 0x10 = 0x5 * i + 0x3`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x3 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x3) - 0x2 = 0x5 * i + 0x1`; + ARITH_RULE `(0x5 * i + 0x3) - 0x1 = 0x5 * i + 0x2`] THEN + + MP_TAC (SPECL [`0`;`5 * i + 1:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i + 1 < 0)`] THEN + REWRITE_TAC[ARITH_RULE `((0x5 * i + 0x1) - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x20`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * i + 2:num`; `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 + 0x20 = (i * 0x5 + 0x2) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 2)`; + ARITH_RULE `0x50 * i + 0x30 = 0x10 * (5 * i + 2) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = (0x50 * i + 0x10) + 0x10`] THEN + (* Use SPECL to force IMP_REWRITE_TAC to apply once once *) + IMP_REWRITE_TAC[(SPECL [`pt_ptr:int64`; `(0x50 * i + 0x10):num`; + `x:byte list`; `s188:armstate`] READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `(aes256_xts_decrypt ct (0x50 * i + 0x20) iv key1 key2)` THEN + REPEAT CONJ_TAC THENL [ + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x10) + 0x10 = 0x50 * i + 0x20`] THEN + + MP_TAC (SPECL [`0x5 * i + 0x2:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + MP_TAC (SPECL [`0x5 * i + 0x2:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x20 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * i + 0x20) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 32 = 16 * (5 * i + 2)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x20) DIV 0x10 = 0x5 * i + 0x2`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x2 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x2) - 0x2 = 0x5 * i`; + ARITH_RULE `(0x5 * i + 0x2) - 0x1 = 0x5 * i + 0x1`] THEN + + MP_TAC (SPECL [`0`;`5 * i:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i < 0)`; + ARITH_RULE `(0x5 * i - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x10`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * i + 1:num`; `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 + 0x10 = (i * 0x5 + 0x1) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x10 = 0x10 * (5 * i + 1)`; + ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 1) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + IMP_REWRITE_TAC[(SPECL [`pt_ptr:int64`; `(0x50 * i):num`; + `(aes256_xts_decrypt ct (0x50 * i + 0x10) iv key1 key2):byte list`; `s188:armstate`] + READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `ct:byte list` THEN EXISTS_TAC `iv:int128` THEN + EXISTS_TAC `key1:int128 list` THEN EXISTS_TAC `key2:int128 list` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * i + 0x1:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + MP_TAC (SPECL [`0x5 * i + 0x1:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x10 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * i + 0x10) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 16 = 16 * (5 * i + 1)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x10) DIV 0x10 = 0x5 * i + 0x1`] THEN + (* Two cases: i = 0 then execute tail branch, else execute recursion branch *) + COND_CASES_TAC THENL + [ SUBGOAL_THEN `i = 0` SUBST1_TAC THENL + [ UNDISCH_TAC `5 * i + 1 < 2` THEN + UNDISCH_TAC `0 <= i` THEN + ARITH_TAC + ; ALL_TAC] THEN CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [`0x0:num`; `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[(ISPECL [`(aes256_xts_decrypt_tail 0x0 0x0 ct iv key1 key2):byte list`; + `0x10:num`] SUB_LIST_LENGTH_IMPLIES)] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + CONV_TAC NUM_REDUCE_CONV; + + SIMP_TAC[ARITH_RULE `(0x5 * i + 0x1) - 0x2 = 0x5 * i - 0x1`; + ARITH_RULE `(0x5 * i + 0x1) - 0x1 = 0x5 * i`] THEN + + MP_TAC (SPECL [`0`;`5 * i - 1:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SUBGOAL_THEN `~(0x5 * i - 0x1 < 0x0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(0x5 * i + 0x1 < 0x2)` THEN ARITH_TAC; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + IMP_REWRITE_TAC[ARITH_RULE `~(0x5 * i + 0x1 < 0x2) ==> (0x5 * i - 1 - 0x0 + 0x1) * 0x10 = 0x50 * i`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * i:num`; `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 = (i * 0x5) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + ARITH_RULE `0x50 * i + 0x10 = 0x10 * 5 * i + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] + ]; + + SUBGOAL_THEN `i + 1 < 2 EXP 64` ASSUME_TAC THENL + [ UNDISCH_TAC `i < val (num_5blocks_adjusted:int64)` THEN + EXPAND_TAC "num_5blocks_adjusted" THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + REWRITE_TAC [VAL_WORD; DIMINDEX_64] THEN ARITH_TAC; ALL_TAC] THEN + EQ_TAC THENL + [ REWRITE_TAC[WORD_RULE `!x:int64 a b. (word_sub (word_sub x a) b) = word_sub x (word_add a b)`] THEN + ASM_SIMP_TAC[WORD_RULE `!a b. a + b < 2 EXP 64 ==> (word_add (word a) (word b)) = word (a + b)`] THEN + REWRITE_TAC[VAL_EQ_0; WORD_SUB_EQ_0] THEN + DISCH_TAC THEN ASM_REWRITE_TAC[] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT]; + REWRITE_TAC[WORD_RULE `!x:int64 a b. (word_sub (word_sub x a) b) = word_sub x (word_add a b)`] THEN + ASM_SIMP_TAC[WORD_RULE `!a b. a + b < 2 EXP 64 ==> (word_add (word a) (word b)) = word (a + b)`] THEN + REWRITE_TAC[VAL_EQ_0; WORD_SUB_EQ_0; WORD_VAL]] + ]; + + + (* Subgoal 4: prove backedge is taken if i != val num_5blocks_adjusted *) + REPEAT STRIP_TAC THEN + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--1) THEN + SUBGOAL_THEN `~(val (word_sub (num_5blocks_adjusted:int64) (word i)) = 0x0)` ASSUME_TAC THENL + [ UNDISCH_TAC `i < val (num_5blocks_adjusted:int64)` THEN WORD_ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_SIMP_TAC[]; + + + (* Subgoal 5: Prove the invariant implies post-condition + Backedge instruction is executed here *) + REPEAT STRIP_TAC THEN + REWRITE_TAC[byte_list_at] THEN + SUBST_ALL_TAC (WORD_RULE `(word (val (num_5blocks_adjusted:int64))):int64 = num_5blocks_adjusted`) THEN + + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + if val (num_5blocks_adjusted:int64) * 0x50 + 0x40 = val (num_blocks_adjusted:int64) + then + MAYCHANGE [memory :> bytes128 (word_add pt_ptr (word (0x50 * val (num_5blocks_adjusted:int64)))); + memory :> bytes128 (word_add pt_ptr (word (0x50 * val num_5blocks_adjusted + 0x10))); + memory :> bytes128 (word_add pt_ptr (word (0x50 * val num_5blocks_adjusted + 0x20))); + memory :> bytes128 (word_add pt_ptr (word (0x50 * val num_5blocks_adjusted + 0x30)))] + else + (if val (num_5blocks_adjusted:int64) * 0x50 + 0x30 = val (num_blocks_adjusted:int64) + then + MAYCHANGE [memory :> bytes128 (word_add pt_ptr (word (0x50 * val (num_5blocks_adjusted:int64)))); + memory :> bytes128 (word_add pt_ptr (word (0x50 * val num_5blocks_adjusted + 0x10))); + memory :> bytes128 (word_add pt_ptr (word (0x50 * val num_5blocks_adjusted + 0x20)))] + else + (if val (num_5blocks_adjusted:int64) * 0x50 + 0x20 = val (num_blocks_adjusted:int64) + then + MAYCHANGE [memory :> bytes128 (word_add pt_ptr (word (0x50 * val (num_5blocks_adjusted:int64)))); + memory :> bytes128 (word_add pt_ptr (word (0x50 * val num_5blocks_adjusted + 0x10)))] + else + (if val (num_5blocks_adjusted:int64) * 0x50 + 0x10 = val (num_blocks_adjusted:int64) + then + MAYCHANGE [memory :> bytes128 (word_add pt_ptr (word (0x50 * val (num_5blocks_adjusted:int64))))] + else + MAYCHANGE [])))` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + REPEAT COND_CASES_TAC THENL + [ SUBGOAL_THEN `0x50 * val (num_5blocks_adjusted:int64) + 0x40 <= val (len:int64)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ABBREV_TAC `val5blocks = val (num_5blocks_adjusted:int64)` THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; + SUBGOAL_THEN `0x50 * val (num_5blocks_adjusted:int64) + 0x30 <= val (len:int64)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ABBREV_TAC `val5blocks = val (num_5blocks_adjusted:int64)` THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; + SUBGOAL_THEN `0x50 * val (num_5blocks_adjusted:int64) + 0x20 <= val (len:int64)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ABBREV_TAC `val5blocks = val (num_5blocks_adjusted:int64)` THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; + SUBGOAL_THEN `0x50 * val (num_5blocks_adjusted:int64) + 0x10 <= val (len:int64)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ABBREV_TAC `val5blocks = val (num_5blocks_adjusted:int64)` THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; + SUBSUMED_MAYCHANGE_TAC] + ; ALL_TAC] THEN + + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (1--3) THEN + FIRST_X_ASSUM MP_TAC THEN + COND_CASES_TAC THENL + [ (* Case: len % 0x50 = 0x40 *) + DISCH_TAC THEN + + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 + 0x40 = val (num_blocks_adjusted:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (word_sub + (word_sub (num_blocks_adjusted:int64) + (word_mul (word 0x50) (num_5blocks_adjusted:int64))) + (word 0x40)) = + 0x0` THEN + REWRITE_TAC [VAL_EQ_0; WORD_SUB_EQ_0] THEN + REWRITE_TAC [WORD_RULE `!x:int64. word_mul (word 0x50) x = word(val x * 0x50)`] THEN + REWRITE_TAC[GSYM VAL_EQ] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 < 2 EXP 64` MP_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 2 EXP 24` THEN + ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[VAL_WORD_SUB_CASES] THEN + SIMP_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + NUM_REDUCE_TAC THEN ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 + 0x40 <= val (len:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 + 0x40 = val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= val (len:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`ct_ptr:int64`; `num_5blocks_adjusted:int64`; `len:int64`; `ct:byte list`; `s3:armstate`] READ_TAIL4_LEMMA) THEN + ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN + + (* Assumptions that help with reasoning about nonoverlapping + so that the universally quantified assumption stays. + See: https://hol-light.zulipchat.com/#narrow/channel/474190-s2n-bignum/topic/.E2.9C.94.20Symbolic.20simulation.20removed.20assumption/with/541554894 *) + SUBGOAL_THEN `0x50 * (val (num_5blocks_adjusted:int64)) < 0x2 EXP 0x40` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val ((word (0x50 * val (num_5blocks_adjusted:int64))):int64) = 0x50 * val num_5blocks_adjusted` ASSUME_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN ASM_ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (4--125) THEN + XTSDEC_TAC `Q0:(armstate,int128)component` + `val (num_5blocks_adjusted:int64) * 0x50` `val (num_5blocks_adjusted:int64) * 0x5` THEN + XTSDEC_TAC `Q1:(armstate,int128)component` + `val (num_5blocks_adjusted:int64) * 0x50 + 0x10` `val (num_5blocks_adjusted:int64) * 0x5 + 0x1` THEN + XTSDEC_TAC `Q24:(armstate,int128)component` + `val (num_5blocks_adjusted:int64) * 0x50 + 0x20` `val (num_5blocks_adjusted:int64) * 0x5 + 0x2` THEN + XTSDEC_TAC `Q25:(armstate,int128)component` + `val (num_5blocks_adjusted:int64) * 0x50 + 0x30` `val (num_5blocks_adjusted:int64) * 0x5 + 0x3` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (126--133) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `val (num_5blocks_adjusted:int64) * 0x5 + 0x4` `val (num_5blocks_adjusted:int64) * 0x5 + 0x3` THEN + + (* The following lemmas are for NONSELFMODIFYING_STATE_UPDATE_TAC when store back to pt_ptr *) + CHANGED_TAC (RULE_ASSUM_TAC(REWRITE_RULE + [WORD_RULE `word_mul (word 0x50) num_5blocks_adjusted:int64 = word(0x50 * val num_5blocks_adjusted)`])) THEN + CHANGED_TAC (RULE_ASSUM_TAC(REWRITE_RULE + [WORD_RULE `!base m n. word_add (word_add base (word m)) (word n) = word_add base (word(m + n))`])) THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (134--134) THEN + (* Need to simplify the expression for X1 after the first store instruction *) + CHANGED_TAC (RULE_ASSUM_TAC(REWRITE_RULE + [WORD_RULE `!base m n. word_add (word_add base (word m)) (word n) = word_add base (word(m + n))`])) THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (135--136) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_blocks] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[LE_REFL] THEN + SUBGOAL_THEN `val ((word (0x50 * val (num_5blocks_adjusted:int64) + 0x40)):int64) = + 0x50 * val num_5blocks_adjusted + 0x40` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; MOD_LT; DIMINDEX_64] THEN + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 + 0x40 <= val (len:int64)` THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> REWRITE_TAC[th]) THEN + + (* Remove quantifier *) + UNDISCH_TAC + `forall i. + i < 0x50 * val (num_5blocks_adjusted:int64) + ==> read (memory :> bytes8 (word_add pt_ptr (word i))) s136 = + EL i (aes256_xts_decrypt ct (0x50 * val num_5blocks_adjusted) iv key1 key2)` THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks_adjusted:int64) + 0x40:num`; `pt_ptr:int64`; + `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64) + 0x40) iv key1 key2):byte list`; + `s136:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x40 = 0x10 * (5 * i + 4)`; + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks_adjusted:int64):num`; `pt_ptr:int64`; + `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64)) iv key1 key2):byte list`; + `s136:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + DISCH_TAC THEN + + IMP_REWRITE_TAC[ARITH_RULE `0x50 * i + 0x40 = (0x50 * i + 0x30) + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64) + 0x40) iv key1 key2)` THEN + REPEAT CONJ_TAC THENL [ + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x30) + 0x10 = 0x50 * i + 0x40`]; + + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x4:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + ASM_REWRITE_TAC[] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * val (num_5blocks_adjusted:int64) + 0x40 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks_adjusted:int64) + 0x40) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 64 = 16 * (5 * i + 4)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x40) DIV 0x10 = 0x5 * i + 0x4`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x4 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x4) - 0x2 = 0x5 * i + 0x2`; + ARITH_RULE `(0x5 * i + 0x4) - 0x1 = 0x5 * i + 0x3`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks_adjusted:int64) + 2:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i + 2 < 0)`; + ARITH_RULE `((0x5 * i + 0x2) - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x30`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks_adjusted:int64) + 3:num`; + `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + ASM_SIMP_TAC[ARITH_RULE `(i * 0x5 + 0x3) * 0x10 = i * 0x50 + 0x30`; + ARITH_RULE `5 * i + 3 = i * 5 + 3`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x30 = 0x10 * (5 * i + 3)`; + ARITH_RULE `0x50 * i + 0x40 = 0x10 * (5 * i + 3) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + IMP_REWRITE_TAC[ARITH_RULE `0x50 * i + 0x30 = (0x50 * i + 0x20) + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64) + 0x30) iv key1 key2)` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x3:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES]; + + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x20) + 0x10 = 0x50 * i + 0x30`] THEN + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x3:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x30 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks_adjusted:int64) + 0x30) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 48 = 16 * (5 * i + 3)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x30) DIV 0x10 = 0x5 * i + 0x3`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x3 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x3) - 0x2 = 0x5 * i + 0x1`; + ARITH_RULE `(0x5 * i + 0x3) - 0x1 = 0x5 * i + 0x2`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks_adjusted:int64) + 1:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i + 1 < 0)`] THEN + REWRITE_TAC[ARITH_RULE `((0x5 * i + 0x1) - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x20`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks_adjusted:int64) + 2:num`; `0x0:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + ASM_SIMP_TAC[ARITH_RULE `(i * 0x5 + 0x2) * 0x10 = i * 0x50 + 0x20`; + ARITH_RULE `5 * i + 2 = i * 5 + 2`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 2)`; + ARITH_RULE `0x50 * i + 0x30 = 0x10 * (5 * i + 2) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = (0x50 * i + 0x10) + 0x10`] THEN + (* Use SPECL to force IMP_REWRITE_TAC to apply once once *) + IMP_REWRITE_TAC[(SPECL [`pt_ptr:int64`; `(0x50 * val (num_5blocks_adjusted:int64) + 0x10):num`; + `x:byte list`; `s188:armstate`] READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64) + 0x20) iv key1 key2)` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x2:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x2:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x20 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks_adjusted:int64) + 0x20) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 32 = 16 * (5 * i + 2)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x20) DIV 0x10 = 0x5 * i + 0x2`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x2 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x2) - 0x2 = 0x5 * i`; + ARITH_RULE `(0x5 * i + 0x2) - 0x1 = 0x5 * i + 0x1`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks_adjusted:int64):num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i < 0)`; + ARITH_RULE `(0x5 * i - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x10`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks_adjusted:int64) + 1:num`; `0x0:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 + 0x10 = (i * 0x5 + 0x1) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x10 = 0x10 * (5 * i + 1)`; + ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 1) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + IMP_REWRITE_TAC[(SPECL [`pt_ptr:int64`; `(0x50 * val (num_5blocks_adjusted:int64)):num`; + `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64) + 0x10) iv key1 key2):byte list`; + `s188:armstate`] + READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `ct:byte list` THEN EXISTS_TAC `iv:int128` THEN + EXISTS_TAC `key1:int128 list` THEN EXISTS_TAC `key2:int128 list` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x1:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x1:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x10 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks_adjusted:int64) + 0x10) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 16 = 16 * (5 * i + 1)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x10) DIV 0x10 = 0x5 * i + 0x1`] THEN + (* Two cases: i = 0 then execute tail branch, else execute recursion branch *) + COND_CASES_TAC THENL + [ SUBGOAL_THEN `val (num_5blocks_adjusted:int64) = 0` SUBST1_TAC THENL + [ UNDISCH_TAC `5 * val (num_5blocks_adjusted:int64) + 1 < 2` THEN + UNDISCH_TAC `0 < val (num_5blocks_adjusted:int64)` THEN + ARITH_TAC + ; ALL_TAC] THEN CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [`0x0:num`; `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[(ISPECL [`(aes256_xts_decrypt_tail 0x0 0x0 ct iv key1 key2):byte list`; + `0x10:num`] SUB_LIST_LENGTH_IMPLIES)] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + CONV_TAC NUM_REDUCE_CONV; + + SIMP_TAC[ARITH_RULE `(0x5 * i + 0x1) - 0x2 = 0x5 * i - 0x1`; + ARITH_RULE `(0x5 * i + 0x1) - 0x1 = 0x5 * i`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks_adjusted:int64) - 1:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SUBGOAL_THEN `~(0x5 * val (num_5blocks_adjusted:int64) - 0x1 < 0x0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(0x5 * val (num_5blocks_adjusted:int64) + 0x1 < 0x2)` THEN ARITH_TAC; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + IMP_REWRITE_TAC[ARITH_RULE `~(0x5 * i + 0x1 < 0x2) ==> (0x5 * i - 1 - 0x0 + 0x1) * 0x10 = 0x50 * i`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks_adjusted:int64):num`; + `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 = (i * 0x5) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + ARITH_RULE `0x50 * i + 0x10 = 0x10 * 5 * i + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS]] + ] + ; ALL_TAC] THEN + + DISCH_TAC THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (4--5) THEN + FIRST_X_ASSUM MP_TAC THEN + COND_CASES_TAC THENL + [ (* Case: len % 0x50 = 0x30 *) + DISCH_TAC THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 + 0x30 = val (num_blocks_adjusted:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (word_sub + (word_sub (num_blocks_adjusted:int64) + (word_mul (word 0x50) (num_5blocks_adjusted:int64))) + (word 0x30)) = + 0x0` THEN + REWRITE_TAC [VAL_EQ_0; WORD_SUB_EQ_0] THEN + REWRITE_TAC [WORD_RULE `!x:int64. word_mul (word 0x50) x = word(val x * 0x50)`] THEN + REWRITE_TAC[GSYM VAL_EQ] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 < 2 EXP 64` MP_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 2 EXP 24` THEN + ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[VAL_WORD_SUB_CASES] THEN + SIMP_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + NUM_REDUCE_TAC THEN ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_5blocks_adjusted:int64) * 0x50 + 0x40 = val (num_blocks_adjusted:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 + 0x30 = val (num_blocks_adjusted:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 + 0x30 <= val (len:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 + 0x30 = val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= val (len:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`ct_ptr:int64`; `num_5blocks_adjusted:int64`; `len:int64`; `ct:byte list`; `s5:armstate`] READ_TAIL3_LEMMA) THEN + ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN + + (* Assumptions that help with reasoning about nonoverlapping + so that the universally quantified assumption stays. + See: https://hol-light.zulipchat.com/#narrow/channel/474190-s2n-bignum/topic/.E2.9C.94.20Symbolic.20simulation.20removed.20assumption/with/541554894 *) + SUBGOAL_THEN `0x50 * (val (num_5blocks_adjusted:int64)) < 0x2 EXP 0x40` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val ((word (0x50 * val (num_5blocks_adjusted:int64))):int64) = 0x50 * val num_5blocks_adjusted` ASSUME_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN ASM_ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (6--97) THEN + XTSDEC_TAC `Q0:(armstate,int128)component` + `val (num_5blocks_adjusted:int64) * 0x50` `val (num_5blocks_adjusted:int64) * 0x5` THEN + XTSDEC_TAC `Q1:(armstate,int128)component` + `val (num_5blocks_adjusted:int64) * 0x50 + 0x10` `val (num_5blocks_adjusted:int64) * 0x5 + 0x1` THEN + XTSDEC_TAC `Q24:(armstate,int128)component` + `val (num_5blocks_adjusted:int64) * 0x50 + 0x20` `val (num_5blocks_adjusted:int64) * 0x5 + 0x2` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (98--105) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `val (num_5blocks_adjusted:int64) * 0x5 + 0x3` `val (num_5blocks_adjusted:int64) * 0x5 + 0x2` THEN + + (* The following lemmas are for NONSELFMODIFYING_STATE_UPDATE_TAC when store back to pt_ptr *) + RULE_ASSUM_TAC(REWRITE_RULE + [WORD_RULE `word_mul (word 0x50) num_5blocks_adjusted:int64 = word(0x50 * val num_5blocks_adjusted)`]) THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (106--108) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_blocks] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[LE_REFL] THEN + SUBGOAL_THEN `val ((word (0x50 * val (num_5blocks_adjusted:int64) + 0x30)):int64) = + 0x50 * val num_5blocks_adjusted + 0x30` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; MOD_LT; DIMINDEX_64] THEN + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 + 0x30 <= val (len:int64)` THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> REWRITE_TAC[th]) THEN + + (* Remove quantifier *) + UNDISCH_TAC + `forall i. + i < 0x50 * val (num_5blocks_adjusted:int64) + ==> read (memory :> bytes8 (word_add pt_ptr (word i))) s108 = + EL i (aes256_xts_decrypt ct (0x50 * val num_5blocks_adjusted) iv key1 key2)` THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks_adjusted:int64) + 0x30:num`; `pt_ptr:int64`; + `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64) + 0x30) iv key1 key2):byte list`; + `s108:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x30 = 0x10 * (5 * i + 3)`; + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks_adjusted:int64):num`; `pt_ptr:int64`; + `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64)) iv key1 key2):byte list`; + `s108:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + DISCH_TAC THEN + + IMP_REWRITE_TAC[ARITH_RULE `0x50 * i + 0x30 = (0x50 * i + 0x20) + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64) + 0x30) iv key1 key2)` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x3:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES]; + + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x20) + 0x10 = 0x50 * i + 0x30`] THEN + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x3:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x30 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks_adjusted:int64) + 0x30) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 48 = 16 * (5 * i + 3)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x30) DIV 0x10 = 0x5 * i + 0x3`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x3 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x3) - 0x2 = 0x5 * i + 0x1`; + ARITH_RULE `(0x5 * i + 0x3) - 0x1 = 0x5 * i + 0x2`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks_adjusted:int64) + 1:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i + 1 < 0)`] THEN + REWRITE_TAC[ARITH_RULE `((0x5 * i + 0x1) - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x20`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks_adjusted:int64) + 2:num`; `0x0:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + ASM_SIMP_TAC[ARITH_RULE `(i * 0x5 + 0x2) * 0x10 = i * 0x50 + 0x20`; + ARITH_RULE `5 * i + 2 = i * 5 + 2`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 2)`; + ARITH_RULE `0x50 * i + 0x30 = 0x10 * (5 * i + 2) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = (0x50 * i + 0x10) + 0x10`] THEN + (* Use SPECL to force IMP_REWRITE_TAC to apply once once *) + IMP_REWRITE_TAC[(SPECL [`pt_ptr:int64`; `(0x50 * val (num_5blocks_adjusted:int64) + 0x10):num`; + `x:byte list`; `s108:armstate`] READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64) + 0x20) iv key1 key2)` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x2:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x2:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x20 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks_adjusted:int64) + 0x20) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 32 = 16 * (5 * i + 2)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x20) DIV 0x10 = 0x5 * i + 0x2`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x2 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x2) - 0x2 = 0x5 * i`; + ARITH_RULE `(0x5 * i + 0x2) - 0x1 = 0x5 * i + 0x1`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks_adjusted:int64):num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i < 0)`; + ARITH_RULE `(0x5 * i - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x10`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks_adjusted:int64) + 1:num`; `0x0:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 + 0x10 = (i * 0x5 + 0x1) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x10 = 0x10 * (5 * i + 1)`; + ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 1) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + IMP_REWRITE_TAC[(SPECL [`pt_ptr:int64`; `(0x50 * val (num_5blocks_adjusted:int64)):num`; + `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64) + 0x10) iv key1 key2):byte list`; + `s108:armstate`] + READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `ct:byte list` THEN EXISTS_TAC `iv:int128` THEN + EXISTS_TAC `key1:int128 list` THEN EXISTS_TAC `key2:int128 list` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x1:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x1:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x10 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks_adjusted:int64) + 0x10) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 16 = 16 * (5 * i + 1)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x10) DIV 0x10 = 0x5 * i + 0x1`] THEN + (* Two cases: i = 0 then execute tail branch, else execute recursion branch *) + COND_CASES_TAC THENL + [ SUBGOAL_THEN `val (num_5blocks_adjusted:int64) = 0` SUBST1_TAC THENL + [ UNDISCH_TAC `5 * val (num_5blocks_adjusted:int64) + 1 < 2` THEN + UNDISCH_TAC `0 < val (num_5blocks_adjusted:int64)` THEN + ARITH_TAC + ; ALL_TAC] THEN CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [`0x0:num`; `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[(ISPECL [`(aes256_xts_decrypt_tail 0x0 0x0 ct iv key1 key2):byte list`; + `0x10:num`] SUB_LIST_LENGTH_IMPLIES)] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + CONV_TAC NUM_REDUCE_CONV; + + SIMP_TAC[ARITH_RULE `(0x5 * i + 0x1) - 0x2 = 0x5 * i - 0x1`; + ARITH_RULE `(0x5 * i + 0x1) - 0x1 = 0x5 * i`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks_adjusted:int64) - 1:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SUBGOAL_THEN `~(0x5 * val (num_5blocks_adjusted:int64) - 0x1 < 0x0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(0x5 * val (num_5blocks_adjusted:int64) + 0x1 < 0x2)` THEN ARITH_TAC; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + IMP_REWRITE_TAC[ARITH_RULE `~(0x5 * i + 0x1 < 0x2) ==> (0x5 * i - 1 - 0x0 + 0x1) * 0x10 = 0x50 * i`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks_adjusted:int64):num`; + `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 = (i * 0x5) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + ARITH_RULE `0x50 * i + 0x10 = 0x10 * 5 * i + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS]] + ] + ; ALL_TAC ] THEN + + DISCH_TAC THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (6--7) THEN + FIRST_X_ASSUM MP_TAC THEN + COND_CASES_TAC THENL + [ (* Case: len % 0x50 = 0x20 *) + DISCH_TAC THEN + + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 + 0x20 = val (num_blocks_adjusted:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (word_sub + (word_sub (num_blocks_adjusted:int64) + (word_mul (word 0x50) (num_5blocks_adjusted:int64))) + (word 0x20)) = + 0x0` THEN + REWRITE_TAC [VAL_EQ_0; WORD_SUB_EQ_0] THEN + REWRITE_TAC [WORD_RULE `!x:int64. word_mul (word 0x50) x = word(val x * 0x50)`] THEN + REWRITE_TAC[GSYM VAL_EQ] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 < 2 EXP 64` MP_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 2 EXP 24` THEN + ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[VAL_WORD_SUB_CASES] THEN + SIMP_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + NUM_REDUCE_TAC THEN ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `~(val (num_5blocks_adjusted:int64) * 0x50 + 0x40 = val (num_blocks_adjusted:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 + 0x20 = val (num_blocks_adjusted:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_5blocks_adjusted:int64) * 0x50 + 0x30 = val (num_blocks_adjusted:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 + 0x20 = val (num_blocks_adjusted:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 + 0x20 <= val (len:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 + 0x20 = val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= val (len:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`ct_ptr:int64`; `num_5blocks_adjusted:int64`; `len:int64`; `ct:byte list`; `s7:armstate`] READ_TAIL2_LEMMA) THEN + ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN + + (* Assumptions that help with reasoning about nonoverlapping + so that the universally quantified assumption stays. + See: https://hol-light.zulipchat.com/#narrow/channel/474190-s2n-bignum/topic/.E2.9C.94.20Symbolic.20simulation.20removed.20assumption/with/541554894 *) + SUBGOAL_THEN `0x50 * (val (num_5blocks_adjusted:int64)) < 0x2 EXP 0x40` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val ((word (0x50 * val (num_5blocks_adjusted:int64))):int64) = 0x50 * val num_5blocks_adjusted` ASSUME_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN ASM_ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (8--68) THEN + XTSDEC_TAC `Q0:(armstate,int128)component` + `val (num_5blocks_adjusted:int64) * 0x50` `val (num_5blocks_adjusted:int64) * 0x5` THEN + XTSDEC_TAC `Q1:(armstate,int128)component` + `val (num_5blocks_adjusted:int64) * 0x50 + 0x10` `val (num_5blocks_adjusted:int64) * 0x5 + 0x1` THEN + + (* The following lemmas are for NONSELFMODIFYING_STATE_UPDATE_TAC when store back to pt_ptr *) + RULE_ASSUM_TAC(REWRITE_RULE + [WORD_RULE `word_mul (word 0x50) num_5blocks_adjusted:int64 = word(0x50 * val num_5blocks_adjusted)`]) THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (69--77) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `val (num_5blocks_adjusted:int64) * 0x5 + 0x2` `val (num_5blocks_adjusted:int64) * 0x5 + 0x1` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (78--78) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_blocks] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[LE_REFL] THEN + SUBGOAL_THEN `val ((word (0x50 * val (num_5blocks_adjusted:int64) + 0x20)):int64) = 0x50 * val num_5blocks_adjusted + 0x20` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; MOD_LT; DIMINDEX_64] THEN + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 + 0x20 <= val (len:int64)` THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> REWRITE_TAC[th]) THEN + + (* Remove quantifier *) + UNDISCH_TAC + `forall i. + i < 0x50 * val (num_5blocks_adjusted:int64) + ==> read (memory :> bytes8 (word_add pt_ptr (word i))) s78 = + EL i (aes256_xts_decrypt ct (0x50 * val num_5blocks_adjusted) iv key1 key2)` THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks_adjusted:int64) + 0x20:num`; `pt_ptr:int64`; + `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64) + 0x20) iv key1 key2):byte list`; + `s78:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 2)`; + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks_adjusted:int64):num`; `pt_ptr:int64`; + `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64)) iv key1 key2):byte list`; + `s78:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + DISCH_TAC THEN + + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = (0x50 * i + 0x10) + 0x10`] THEN + (* Use SPECL to force IMP_REWRITE_TAC to apply once once *) + IMP_REWRITE_TAC[(SPECL [`pt_ptr:int64`; `(0x50 * val (num_5blocks_adjusted:int64) + 0x10):num`; + `x:byte list`; `s78:armstate`] READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64) + 0x20) iv key1 key2)` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x2:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x2:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x20 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks_adjusted:int64) + 0x20) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 32 = 16 * (5 * i + 2)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x20) DIV 0x10 = 0x5 * i + 0x2`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x2 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x2) - 0x2 = 0x5 * i`; + ARITH_RULE `(0x5 * i + 0x2) - 0x1 = 0x5 * i + 0x1`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks_adjusted:int64):num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i < 0)`; + ARITH_RULE `(0x5 * i - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x10`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks_adjusted:int64) + 1:num`; `0x0:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 + 0x10 = (i * 0x5 + 0x1) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x10 = 0x10 * (5 * i + 1)`; + ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 1) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + IMP_REWRITE_TAC[(SPECL [`pt_ptr:int64`; `(0x50 * val (num_5blocks_adjusted:int64)):num`; + `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64) + 0x10) iv key1 key2):byte list`; + `s78:armstate`] + READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `ct:byte list` THEN EXISTS_TAC `iv:int128` THEN + EXISTS_TAC `key1:int128 list` THEN EXISTS_TAC `key2:int128 list` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x1:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x1:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x10 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks_adjusted:int64) + 0x10) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 16 = 16 * (5 * i + 1)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x10) DIV 0x10 = 0x5 * i + 0x1`] THEN + (* Two cases: i = 0 then execute tail branch, else execute recursion branch *) + COND_CASES_TAC THENL + [ SUBGOAL_THEN `val (num_5blocks_adjusted:int64) = 0` SUBST1_TAC THENL + [ UNDISCH_TAC `5 * val (num_5blocks_adjusted:int64) + 1 < 2` THEN + UNDISCH_TAC `0 < val (num_5blocks_adjusted:int64)` THEN + ARITH_TAC + ; ALL_TAC] THEN CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [`0x0:num`; `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[(ISPECL [`(aes256_xts_decrypt_tail 0x0 0x0 ct iv key1 key2):byte list`; + `0x10:num`] SUB_LIST_LENGTH_IMPLIES)] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + CONV_TAC NUM_REDUCE_CONV; + + SIMP_TAC[ARITH_RULE `(0x5 * i + 0x1) - 0x2 = 0x5 * i - 0x1`; + ARITH_RULE `(0x5 * i + 0x1) - 0x1 = 0x5 * i`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks_adjusted:int64) - 1:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SUBGOAL_THEN `~(0x5 * val (num_5blocks_adjusted:int64) - 0x1 < 0x0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(0x5 * val (num_5blocks_adjusted:int64) + 0x1 < 0x2)` THEN ARITH_TAC; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + IMP_REWRITE_TAC[ARITH_RULE `~(0x5 * i + 0x1 < 0x2) ==> (0x5 * i - 1 - 0x0 + 0x1) * 0x10 = 0x50 * i`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks_adjusted:int64):num`; + `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 = (i * 0x5) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + ARITH_RULE `0x50 * i + 0x10 = 0x10 * 5 * i + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS]] + ]; ALL_TAC] THEN + + DISCH_TAC THEN + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (8--9) THEN + FIRST_X_ASSUM MP_TAC THEN + COND_CASES_TAC THENL + [ (* Case: len % 0x50 = 0x10 *) + DISCH_TAC THEN + + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 + 0x10 = val (num_blocks_adjusted:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (word_sub + (word_sub (num_blocks_adjusted:int64) + (word_mul (word 0x50) (num_5blocks_adjusted:int64))) + (word 0x10)) = + 0x0` THEN + REWRITE_TAC [VAL_EQ_0; WORD_SUB_EQ_0] THEN + REWRITE_TAC [WORD_RULE `!x:int64. word_mul (word 0x50) x = word(val x * 0x50)`] THEN + REWRITE_TAC[GSYM VAL_EQ] THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 < 2 EXP 64` MP_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 2 EXP 24` THEN + ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[VAL_WORD_SUB_CASES] THEN + SIMP_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + NUM_REDUCE_TAC THEN ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `~(val (num_5blocks_adjusted:int64) * 0x50 + 0x40 = val (num_blocks_adjusted:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 + 0x10 = val (num_blocks_adjusted:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_5blocks_adjusted:int64) * 0x50 + 0x30 = val (num_blocks_adjusted:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 + 0x10 = val (num_blocks_adjusted:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_5blocks_adjusted:int64) * 0x50 + 0x20 = val (num_blocks_adjusted:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 + 0x10 = val (num_blocks_adjusted:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 + 0x10 <= val (len:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 + 0x10 = val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= val (len:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`ct_ptr:int64`; `num_5blocks_adjusted:int64`; `len:int64`; `ct:byte list`; `s9:armstate`] READ_TAIL1_LEMMA) THEN + ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN + + (* Assumptions that help with reasoning about nonoverlapping + so that the universally quantified assumption stays. + See: https://hol-light.zulipchat.com/#narrow/channel/474190-s2n-bignum/topic/.E2.9C.94.20Symbolic.20simulation.20removed.20assumption/with/541554894 *) + SUBGOAL_THEN `0x50 * (val (num_5blocks_adjusted:int64)) < 0x2 EXP 0x40` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val ((word (0x50 * val (num_5blocks_adjusted:int64))):int64) = 0x50 * val num_5blocks_adjusted` ASSUME_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN ASM_ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (10--40) THEN + XTSDEC_TAC `Q0:(armstate,int128)component` + `val (num_5blocks_adjusted:int64) * 0x50` `val (num_5blocks_adjusted:int64) * 0x5` THEN + + (* The following lemmas are for NONSELFMODIFYING_STATE_UPDATE_TAC when store back to pt_ptr *) + RULE_ASSUM_TAC(REWRITE_RULE + [WORD_RULE `word_mul (word 0x50) num_5blocks_adjusted:int64 = word(0x50 * val num_5blocks_adjusted)`]) THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (41--49) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `val (num_5blocks_adjusted:int64) * 0x5 + 0x1` `val (num_5blocks_adjusted:int64) * 0x5` THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (50--50) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_blocks] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[LE_REFL] THEN + SUBGOAL_THEN `val ((word (0x50 * val (num_5blocks_adjusted:int64) + 0x10)):int64) = + 0x50 * val num_5blocks_adjusted + 0x10` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; MOD_LT; DIMINDEX_64] THEN + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 + 0x10 <= val (len:int64)` THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> REWRITE_TAC[th]) THEN + + (* Remove quantifier *) + UNDISCH_TAC + `forall i. + i < 0x50 * val (num_5blocks_adjusted:int64) + ==> read (memory :> bytes8 (word_add pt_ptr (word i))) s50 = + EL i (aes256_xts_decrypt ct (0x50 * val num_5blocks_adjusted) iv key1 key2)` THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks_adjusted:int64) + 0x10:num`; `pt_ptr:int64`; + `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64) + 0x10) iv key1 key2):byte list`; + `s50:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x10 = 0x10 * (5 * i + 1)`; + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks_adjusted:int64):num`; `pt_ptr:int64`; + `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64)) iv key1 key2):byte list`; + `s50:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + DISCH_TAC THEN + + IMP_REWRITE_TAC[(SPECL [`pt_ptr:int64`; `(0x50 * val (num_5blocks_adjusted:int64)):num`; + `(aes256_xts_decrypt ct (0x50 * val (num_5blocks_adjusted:int64) + 0x10) iv key1 key2):byte list`; + `s50:armstate`] + READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `ct:byte list` THEN EXISTS_TAC `iv:int128` THEN + EXISTS_TAC `key1:int128 list` THEN EXISTS_TAC `key2:int128 list` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x1:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + MP_TAC (SPECL [`0x5 * val (num_5blocks_adjusted:int64) + 0x1:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; + `key2:int128 list`] LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_decrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x10 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks_adjusted:int64) + 0x10) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 16 = 16 * (5 * i + 1)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x10) DIV 0x10 = 0x5 * i + 0x1`] THEN + (* Two cases: i = 0 then execute tail branch, else execute recursion branch *) + COND_CASES_TAC THENL + [ SUBGOAL_THEN `val (num_5blocks_adjusted:int64) = 0` SUBST1_TAC THENL + [ UNDISCH_TAC `5 * val (num_5blocks_adjusted:int64) + 1 < 2` THEN + UNDISCH_TAC `0 < val (num_5blocks_adjusted:int64)` THEN + ARITH_TAC + ; ALL_TAC] THEN CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [`0x0:num`; `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[(ISPECL [`(aes256_xts_decrypt_tail 0x0 0x0 ct iv key1 key2):byte list`; + `0x10:num`] SUB_LIST_LENGTH_IMPLIES)] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + CONV_TAC NUM_REDUCE_CONV; + + SIMP_TAC[ARITH_RULE `(0x5 * i + 0x1) - 0x2 = 0x5 * i - 0x1`; + ARITH_RULE `(0x5 * i + 0x1) - 0x1 = 0x5 * i`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks_adjusted:int64) - 1:num`; + `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_REC) THEN + SUBGOAL_THEN `~(0x5 * val (num_5blocks_adjusted:int64) - 0x1 < 0x0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(0x5 * val (num_5blocks_adjusted:int64) + 0x1 < 0x2)` THEN ARITH_TAC; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + IMP_REWRITE_TAC[ARITH_RULE `~(0x5 * i + 0x1 < 0x2) ==> (0x5 * i - 1 - 0x0 + 0x1) * 0x10 = 0x50 * i`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks_adjusted:int64):num`; + `0x0:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_DECRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_DECRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 = (i * 0x5) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + ARITH_RULE `0x50 * i + 0x10 = 0x10 * 5 * i + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_DECRYPT_FULL_BLOCKS] THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_DECRYPT_FULL_BLOCKS]] + ] + ; ALL_TAC] THEN + + (* Case: len % 0x50 = 0 *) + DISCH_TAC THEN + SUBGOAL_THEN `val (num_5blocks_adjusted:int64) * 0x50 = val (num_blocks_adjusted:int64)` ASSUME_TAC THENL + [ MATCH_MP_TAC (SPECL [`val (num_blocks_adjusted:int64)`; `val (num_5blocks_adjusted:int64)`] DIVISION_BY_80_LEMMA) THEN + REPEAT CONJ_TAC THENL + [ + EXPAND_TAC "num_5blocks_adjusted" THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (num_blocks_adjusted:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; + + EXPAND_TAC "num_blocks_adjusted" THEN + EXPAND_TAC "num_blocks" THEN + COND_CASES_TAC THENL + [ + REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT; DIVIDES_RMUL; DIVIDES_REFL] THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; + + IMP_REWRITE_TAC[NUM_BLOCKS_MINUS1_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT; DIVIDES_RMUL; DIVIDES_REFL] THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC]; + + UNDISCH_TAC `~(val (word_sub + (word_sub (num_blocks_adjusted:int64) + (word_mul (word 0x50) (num_5blocks_adjusted:int64))) + (word 0x10)) = 0x0)` THEN + REWRITE_TAC[CONTRAPOS_THM] THEN + REWRITE_TAC[VAL_WORD_SUB_EQ_0; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x10 MOD 0x2 EXP 0x40 = 0x10`] THEN + REWRITE_TAC[VAL_WORD_SUB; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x50 MOD 0x2 EXP 0x40 = 0x50`] THEN + + SUBGOAL_THEN `0x50 * val (num_5blocks_adjusted:int64) < 2 EXP 64` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (len:int64)` THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks_adjusted:int64)`; `2 EXP 64`] MOD_LT) THEN + ANTS_TAC THENL [ASM_SIMP_TAC[]; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`val (num_blocks_adjusted:int64)`; `0x2 EXP 0x40`; + `0x50 * val (num_5blocks_adjusted:int64)`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + SIMP_TAC[MULT_SYM]; ALL_TAC] THEN + ANTS_TAC THENL [ + UNDISCH_TAC `0x50 * val (num_5blocks_adjusted:int64) < 2 EXP 64` THEN + ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; + `val (num_blocks_adjusted:int64) - 0x50 * val (num_5blocks_adjusted:int64)`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + REWRITE_TAC[ARITH_RULE `1 * 2 EXP 64 = 2 EXP 64`] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + SIMP_TAC[MULT_SYM] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV; + + UNDISCH_TAC `~(val (word_sub + (word_sub (num_blocks_adjusted:int64) + (word_mul (word 0x50) (num_5blocks_adjusted:int64))) + (word 0x20)) = 0x0)` THEN + REWRITE_TAC[CONTRAPOS_THM] THEN + REWRITE_TAC[VAL_WORD_SUB_EQ_0; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x20 MOD 0x2 EXP 0x40 = 0x20`] THEN + REWRITE_TAC[VAL_WORD_SUB; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x50 MOD 0x2 EXP 0x40 = 0x50`] THEN + + SUBGOAL_THEN `0x50 * val (num_5blocks_adjusted:int64) < 2 EXP 64` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (len:int64)` THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks_adjusted:int64)`; `2 EXP 64`] MOD_LT) THEN + ANTS_TAC THENL [ASM_SIMP_TAC[]; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`val (num_blocks_adjusted:int64)`; `0x2 EXP 0x40`; + `0x50 * val (num_5blocks_adjusted:int64)`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + SIMP_TAC[MULT_SYM]; ALL_TAC] THEN + ANTS_TAC THENL [ + UNDISCH_TAC `0x50 * val (num_5blocks_adjusted:int64) < 2 EXP 64` THEN + ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; + `val (num_blocks_adjusted:int64) - 0x50 * val (num_5blocks_adjusted:int64)`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + REWRITE_TAC[ARITH_RULE `1 * 2 EXP 64 = 2 EXP 64`] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + SIMP_TAC[MULT_SYM] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV; + + UNDISCH_TAC `~(val (word_sub + (word_sub (num_blocks_adjusted:int64) + (word_mul (word 0x50) (num_5blocks_adjusted:int64))) + (word 0x30)) = 0x0)` THEN + REWRITE_TAC[CONTRAPOS_THM] THEN + REWRITE_TAC[VAL_WORD_SUB_EQ_0; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x30 MOD 0x2 EXP 0x40 = 0x30`] THEN + REWRITE_TAC[VAL_WORD_SUB; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x50 MOD 0x2 EXP 0x40 = 0x50`] THEN + + SUBGOAL_THEN `0x50 * val (num_5blocks_adjusted:int64) < 2 EXP 64` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (len:int64)` THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks_adjusted:int64)`; `2 EXP 64`] MOD_LT) THEN + ANTS_TAC THENL [ASM_SIMP_TAC[]; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`val (num_blocks_adjusted:int64)`; `0x2 EXP 0x40`; + `0x50 * val (num_5blocks_adjusted:int64)`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + SIMP_TAC[MULT_SYM]; ALL_TAC] THEN + ANTS_TAC THENL [ + UNDISCH_TAC `0x50 * val (num_5blocks_adjusted:int64) < 2 EXP 64` THEN + ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; + `val (num_blocks_adjusted:int64) - 0x50 * val (num_5blocks_adjusted:int64)`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + REWRITE_TAC[ARITH_RULE `1 * 2 EXP 64 = 2 EXP 64`] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + SIMP_TAC[MULT_SYM] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV; + + UNDISCH_TAC `~(val (word_sub + (word_sub (num_blocks_adjusted:int64) + (word_mul (word 0x50) (num_5blocks_adjusted:int64))) + (word 0x40)) = 0x0)` THEN + REWRITE_TAC[CONTRAPOS_THM] THEN + REWRITE_TAC[VAL_WORD_SUB_EQ_0; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x40 MOD 0x2 EXP 0x40 = 0x40`] THEN + REWRITE_TAC[VAL_WORD_SUB; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x50 MOD 0x2 EXP 0x40 = 0x50`] THEN + + SUBGOAL_THEN `0x50 * val (num_5blocks_adjusted:int64) < 2 EXP 64` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (len:int64)` THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks_adjusted:int64)`; `2 EXP 64`] MOD_LT) THEN + ANTS_TAC THENL [ASM_SIMP_TAC[]; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`val (num_blocks_adjusted:int64)`; `0x2 EXP 0x40`; + `0x50 * val (num_5blocks_adjusted:int64)`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ + UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 <= val (num_blocks_adjusted:int64)` THEN + SIMP_TAC[MULT_SYM]; ALL_TAC] THEN + ANTS_TAC THENL [ + UNDISCH_TAC `0x50 * val (num_5blocks_adjusted:int64) < 2 EXP 64` THEN + ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; + `val (num_blocks_adjusted:int64) - 0x50 * val (num_5blocks_adjusted:int64)`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + REWRITE_TAC[ARITH_RULE `1 * 2 EXP 64 = 2 EXP 64`] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + SIMP_TAC[MULT_SYM] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV + ] + ; ALL_TAC] THEN + + SUBGOAL_THEN `~(val (num_5blocks_adjusted:int64) * 0x50 + 0x40 = val (num_blocks_adjusted:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 = val (num_blocks_adjusted:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_5blocks_adjusted:int64) * 0x50 + 0x30 = val (num_blocks_adjusted:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 = val (num_blocks_adjusted:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_5blocks_adjusted:int64) * 0x50 + 0x20 = val (num_blocks_adjusted:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 = val (num_blocks_adjusted:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_5blocks_adjusted:int64) * 0x50 + 0x10 = val (num_blocks_adjusted:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks_adjusted:int64) * 0x50 = val (num_blocks_adjusted:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + + ARM_ACCSTEPS_TAC AES_XTS_DECRYPT_EXEC [] (10--10) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_blocks] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[LE_REFL] + ] + ] (* End of loop invariant proof *) + ; ALL_TAC] THEN + + MP_TAC CIPHER_STEALING_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes_xts_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes_xts_decrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; C_ARGUMENTS; SOME_FLAGS; + NONOVERLAPPING_CLAUSES; byte_list_at; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + EXISTS_TAC `num_blocks:int64` THEN + ASM_SIMP_TAC[] +);; + + +let AES_XTS_DECRYPT_SUBROUTINE_CORRECT = time prove + (`!ct_ptr pt_ptr ct key1_ptr key2_ptr iv_ptr iv len + k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e + k10 k11 k12 k13 k14 k15 k16 k17 k18 k19 k1a k1b k1c k1d k1e + pc stackpointer returnaddress. + aligned 16 stackpointer + /\ ALL (nonoverlapping (word_sub stackpointer (word 96), 96)) + [ (word pc, LENGTH aes_xts_decrypt_mc); + (ct_ptr, val len); (key1_ptr, 260); + (key2_ptr, 260); (iv_ptr, 16); + (pt_ptr, val len)] + /\ nonoverlapping (word pc, LENGTH aes_xts_decrypt_mc) (pt_ptr, val len) + /\ nonoverlapping (ct_ptr, val len) (pt_ptr, val len) + /\ nonoverlapping (key1_ptr, 260) (pt_ptr, val len) + /\ val len >= 16 /\ val len <= 2 EXP 24 /\ LENGTH ct = val len + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes_xts_decrypt_mc /\ + read PC s = word pc /\ + read SP s = stackpointer /\ + read X30 s = returnaddress /\ + C_ARGUMENTS [ct_ptr; pt_ptr; len; key1_ptr; key2_ptr; iv_ptr] s /\ + byte_list_at ct ct_ptr len s /\ + read(memory :> bytes128 iv_ptr) s = iv /\ + set_key_schedule s key1_ptr k00 k01 k02 k03 k04 k05 k06 k07 k08 k09 k0a k0b k0c k0d k0e /\ + set_key_schedule s key2_ptr k10 k11 k12 k13 k14 k15 k16 k17 k18 k19 k1a k1b k1c k1d k1e) + (\s. read PC s = returnaddress /\ + byte_list_at (aes256_xts_decrypt ct (val len) iv + [k00; k01; k02; k03; k04; k05; k06; k07; k08; k09; k0a; k0b; k0c; k0d; k0e] + [k10; k11; k12; k13; k14; k15; k16; k17; k18; k19; k1a; k1b; k1c; k1d; k1e]) + pt_ptr len s + ) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [memory :> bytes(pt_ptr, val len); + memory :> bytes(word_sub stackpointer (word 96), 96)])`, + REWRITE_TAC[byte_list_at; set_key_schedule; + fst AES_XTS_DECRYPT_EXEC] THEN + (* ~pre_post_nsteps:(7,7): 7 instructions before and after program body + for handling stack. + 96: the byte size occupied on stack for storing preserved registers *) + ARM_ADD_RETURN_STACK_TAC + ~pre_post_nsteps:(7,7) AES_XTS_DECRYPT_EXEC + (REWRITE_RULE[byte_list_at; set_key_schedule; + fst AES_XTS_DECRYPT_EXEC] AES_XTS_DECRYPT_CORRECT) + `[X19; X20; X21; X22; D8; D9; D10; D11; D12; D13; D14; D15]` 96 + );; diff --git a/arm/proofs/aes_xts_encrypt.ml b/arm/proofs/aes_xts_encrypt.ml new file mode 100644 index 000000000..289b8e612 --- /dev/null +++ b/arm/proofs/aes_xts_encrypt.ml @@ -0,0 +1,5983 @@ +(* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0 + *) +(* ========================================================================= *) +(* AES-256-XTS encryption. *) +(* ========================================================================= *) + +needs "arm/proofs/utils/aes_xts_common.ml";; +needs "arm/proofs/consttime.ml";; + +(* print_literal_from_elf "arm/aes-xts/aes_xts_encrypt.o";; *) +let aes256_xts_encrypt_mc = define_assert_from_elf "aes256_xts_encrypt_mc" "arm/aes-xts/aes_xts_encrypt.o" +[ + 0xd10183ff; (* arm_SUB SP SP (rvalue (word 0x60)) *) + 0x6d0227e8; (* arm_STP D8 D9 SP (Immediate_Offset (iword (&0x20))) *) + 0x6d032fea; (* arm_STP D10 D11 SP (Immediate_Offset (iword (&0x30))) *) + 0x6d0437ec; (* arm_STP D12 D13 SP (Immediate_Offset (iword (&0x40))) *) + 0x6d053fee; (* arm_STP D14 D15 SP (Immediate_Offset (iword (&0x50))) *) + 0xa90053f3; (* arm_STP X19 X20 SP (Immediate_Offset (iword (&0x0))) *) + 0xa9015bf5; (* arm_STP X21 X22 SP (Immediate_Offset (iword (&0x10))) *) + 0xf100405f; (* arm_CMP X2 (rvalue (word 0x10)) *) + 0x5400536b; (* arm_BLT (word 0xa6c) *) + 0xd503201f; (* arm_NOP *) + 0xd503201f; (* arm_NOP *) + 0xd503201f; (* arm_NOP *) + + (* // Lxts_enc_big_size: *) + 0x92400c55; (* arm_AND X21 X2 (rvalue (word 0xf)) *) + 0x927cec42; (* arm_AND X2 X2 (rvalue (word 0xfffffffffffffff0)) *) + + (* // Firstly, encrypt the iv with key2 *) + 0xb940f086; (* arm_LDR W6 X4 (Immediate_Offset (word 0xf0)) *) + 0x4cdf7880; (* arm_LDR Q0 X4 (Postimmediate_Offset (word 0x10)) *) + 0x4c4070a6; (* arm_LDR Q6 X5 No_Offset *) + 0x510008c6; (* arm_SUB W6 W6 (rvalue (word 0x2)) *) + 0x4cdf7881; (* arm_LDR Q1 X4 (Postimmediate_Offset (word 0x10)) *) + 0x4e284806; (* arm_AESE Q6 Q0 *) + 0x4e2868c6; (* arm_AESMC Q6 Q6 *) + 0x4cdf7880; (* arm_LDR Q0 X4 (Postimmediate_Offset (word 0x10)) *) + 0x710008c6; (* arm_SUBS W6 W6 (rvalue (word 0x2)) *) + 0x4e284826; (* arm_AESE Q6 Q1 *) + 0x4e2868c6; (* arm_AESMC Q6 Q6 *) + 0x4cdf7881; (* arm_LDR Q1 X4 (Postimmediate_Offset (word 0x10)) *) + 0x54ffff2c; (* arm_BGT (word 0x1fffe4) *) + 0x4e284806; (* arm_AESE Q6 Q0 *) + 0x4e2868c6; (* arm_AESMC Q6 Q6 *) + 0x4c407880; (* arm_LDR Q0 X4 No_Offset *) + 0x4e284826; (* arm_AESE Q6 Q1 *) + 0x6e201cc6; (* arm_EOR_VEC Q6 Q6 Q0 0x80 *) + + (* Load key schedule *) + (* pc + 0x80 *) + 0xaa0303e7; (* arm_MOV X7 X3 *) + 0x4cdfa8f0; (* arm_LDP Q16 Q17 X7 (Postimmediate_Offset (word 0x20)) *) + 0x4cdfa8ec; (* arm_LDP Q12 Q13 X7 (Postimmediate_Offset (word 0x20)) *) + 0x4cdfa8ee; (* arm_LDP Q14 Q15 X7 (Postimmediate_Offset (word 0x20)) *) + 0x4cdfa8e4; (* arm_LDP Q4 Q5 X7 (Postimmediate_Offset (word 0x20)) *) + 0x4cdfa8f2; (* arm_LDP Q18 Q19 X7 (Postimmediate_Offset (word 0x20)) *) + 0x4cdfa8f4; (* arm_LDP Q20 Q21 X7 (Postimmediate_Offset (word 0x20)) *) + 0x4cdfa8f6; (* arm_LDP Q22 Q23 X7 (Postimmediate_Offset (word 0x20)) *) + 0x4c4078e7; (* arm_LDR Q7 X7 No_Offset *) + + (* Lxts_enc: *) + (* pc + 0xa4 *) + 0x528010f3; (* arm_MOV W19 (rvalue (word 0x87)) *) + 0xf100805f; (* arm_CMP X2 (rvalue (word 0x20)) *) + 0x54004463; (* arm_BCC (word 0x88c) *) + 0x9e6600c9; (* arm_FMOV_FtoI X9 Q6 0x0 0x40 *) + 0x9eae00ca; (* arm_FMOV_FtoI X10 Q6 0x1 0x40 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670128; (* arm_FMOV_ItoF Q8 X9 0x0 *) + 0x9eaf0148; (* arm_FMOV_ItoF Q8 X10 0x1 *) + 0xf100c05f; (* arm_CMP X2 (rvalue (word 0x30)) *) + 0x54003a43; (* arm_BCC (word 0x748) *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670129; (* arm_FMOV_ItoF Q9 X9 0x0 *) + 0x9eaf0149; (* arm_FMOV_ItoF Q9 X10 0x1 *) + 0xf101005f; (* arm_CMP X2 (rvalue (word 0x40)) *) + 0x54002c63; (* arm_BCC (word 0x58c) *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e67012a; (* arm_FMOV_ItoF Q10 X9 0x0 *) + 0x9eaf014a; (* arm_FMOV_ItoF Q10 X10 0x1 *) + 0xf101405f; (* arm_CMP X2 (rvalue (word 0x50)) *) + 0x54001a63; (* arm_BCC (word 0x34c) *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e67012b; (* arm_FMOV_ItoF Q11 X9 0x0 *) + 0x9eaf014b; (* arm_FMOV_ItoF Q11 X10 0x1 *) + 0xb202e7e8; (* arm_MOV X8 (rvalue (word 0xcccccccccccccccc)) *) + 0xf29999a8; (* arm_MOVK X8 (word 0xcccd) 0x0 *) + 0x9bc87c48; (* arm_UMULH X8 X2 X8 *) + 0xd346fd08; (* arm_LSR X8 X8 0x6 *) + + (* .Loop5x_xts_enc: *) + (* pc + 0x140 *) + 0xacc28400; (* arm_LDP Q0 Q1 X0 (Postimmediate_Offset (iword (&0x50))) *) + 0xad7ee418; (* arm_LDP Q24 Q25 X0 (Immediate_Offset (iword (-- &0x30))) *) + 0x3cdf001a; (* arm_LDR Q26 X0 (Immediate_Offset (word 0xfffffffffffffff0)) *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x6e291f18; (* arm_EOR_VEC Q24 Q24 Q9 0x80 *) + 0x6e2a1f39; (* arm_EOR_VEC Q25 Q25 Q10 0x80 *) + 0x6e2b1f5a; (* arm_EOR_VEC Q26 Q26 Q11 0x80 *) + 0x4e284a00; (* arm_AESE Q0 Q16 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a01; (* arm_AESE Q1 Q16 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a18; (* arm_AESE Q24 Q16 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284a19; (* arm_AESE Q25 Q16 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284a1a; (* arm_AESE Q26 Q16 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284a20; (* arm_AESE Q0 Q17 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a21; (* arm_AESE Q1 Q17 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a38; (* arm_AESE Q24 Q17 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284a39; (* arm_AESE Q25 Q17 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284a3a; (* arm_AESE Q26 Q17 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284980; (* arm_AESE Q0 Q12 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284981; (* arm_AESE Q1 Q12 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284998; (* arm_AESE Q24 Q12 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284999; (* arm_AESE Q25 Q12 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e28499a; (* arm_AESE Q26 Q12 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e2849a0; (* arm_AESE Q0 Q13 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849a1; (* arm_AESE Q1 Q13 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2849b8; (* arm_AESE Q24 Q13 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e2849b9; (* arm_AESE Q25 Q13 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e2849ba; (* arm_AESE Q26 Q13 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e2849c0; (* arm_AESE Q0 Q14 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849c1; (* arm_AESE Q1 Q14 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2849d8; (* arm_AESE Q24 Q14 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e2849d9; (* arm_AESE Q25 Q14 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e2849da; (* arm_AESE Q26 Q14 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e2849e0; (* arm_AESE Q0 Q15 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849e1; (* arm_AESE Q1 Q15 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2849f8; (* arm_AESE Q24 Q15 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e2849f9; (* arm_AESE Q25 Q15 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e2849fa; (* arm_AESE Q26 Q15 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284880; (* arm_AESE Q0 Q4 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284881; (* arm_AESE Q1 Q4 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284898; (* arm_AESE Q24 Q4 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284899; (* arm_AESE Q25 Q4 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e28489a; (* arm_AESE Q26 Q4 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e2848a0; (* arm_AESE Q0 Q5 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2848a1; (* arm_AESE Q1 Q5 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2848b8; (* arm_AESE Q24 Q5 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e2848b9; (* arm_AESE Q25 Q5 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e2848ba; (* arm_AESE Q26 Q5 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284a40; (* arm_AESE Q0 Q18 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a41; (* arm_AESE Q1 Q18 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a58; (* arm_AESE Q24 Q18 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284a59; (* arm_AESE Q25 Q18 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284a5a; (* arm_AESE Q26 Q18 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284a60; (* arm_AESE Q0 Q19 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a61; (* arm_AESE Q1 Q19 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a78; (* arm_AESE Q24 Q19 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284a79; (* arm_AESE Q25 Q19 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284a7a; (* arm_AESE Q26 Q19 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284a80; (* arm_AESE Q0 Q20 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a81; (* arm_AESE Q1 Q20 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a98; (* arm_AESE Q24 Q20 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284a99; (* arm_AESE Q25 Q20 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284a9a; (* arm_AESE Q26 Q20 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284aa0; (* arm_AESE Q0 Q21 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284aa1; (* arm_AESE Q1 Q21 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284ab8; (* arm_AESE Q24 Q21 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284ab9; (* arm_AESE Q25 Q21 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284aba; (* arm_AESE Q26 Q21 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284ac0; (* arm_AESE Q0 Q22 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284ac1; (* arm_AESE Q1 Q22 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284ad8; (* arm_AESE Q24 Q22 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284ad9; (* arm_AESE Q25 Q22 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284ada; (* arm_AESE Q26 Q22 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284ae0; (* arm_AESE Q0 Q23 *) + 0x4e284ae1; (* arm_AESE Q1 Q23 *) + 0x4e284af8; (* arm_AESE Q24 Q23 *) + 0x4e284af9; (* arm_AESE Q25 Q23 *) + 0x4e284afa; (* arm_AESE Q26 Q23 *) + 0x6e271c00; (* arm_EOR_VEC Q0 Q0 Q7 0x80 *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670126; (* arm_FMOV_ItoF Q6 X9 0x0 *) + 0x9eaf0146; (* arm_FMOV_ItoF Q6 X10 0x1 *) + 0x6e271c21; (* arm_EOR_VEC Q1 Q1 Q7 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670128; (* arm_FMOV_ItoF Q8 X9 0x0 *) + 0x9eaf0148; (* arm_FMOV_ItoF Q8 X10 0x1 *) + 0x6e271f18; (* arm_EOR_VEC Q24 Q24 Q7 0x80 *) + 0x6e291f18; (* arm_EOR_VEC Q24 Q24 Q9 0x80 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670129; (* arm_FMOV_ItoF Q9 X9 0x0 *) + 0x9eaf0149; (* arm_FMOV_ItoF Q9 X10 0x1 *) + 0x6e271f39; (* arm_EOR_VEC Q25 Q25 Q7 0x80 *) + 0x6e2a1f39; (* arm_EOR_VEC Q25 Q25 Q10 0x80 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e67012a; (* arm_FMOV_ItoF Q10 X9 0x0 *) + 0x9eaf014a; (* arm_FMOV_ItoF Q10 X10 0x1 *) + 0x6e271f5a; (* arm_EOR_VEC Q26 Q26 Q7 0x80 *) + 0x6e2b1f5a; (* arm_EOR_VEC Q26 Q26 Q11 0x80 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e67012b; (* arm_FMOV_ItoF Q11 X9 0x0 *) + 0x9eaf014b; (* arm_FMOV_ItoF Q11 X10 0x1 *) + 0xac828420; (* arm_STP Q0 Q1 X1 (Postimmediate_Offset (iword (&0x50))) *) + 0xad3ee438; (* arm_STP Q24 Q25 X1 (Immediate_Offset (iword (-- &0x30))) *) + 0x3c9f003a; (* arm_STR Q26 X1 (Immediate_Offset (word 0xfffffffffffffff0)) *) + 0xd1014042; (* arm_SUB X2 X2 (rvalue (word 0x50)) *) + 0xf1000508; (* arm_SUBS X8 X8 (rvalue (word 0x1)) *) + 0xb5ffe888; (* arm_CBNZ X8 (word 0x1ffd10) *) + + (* .Loop5x_enc_after: *) + (* pc + 0x434 *) + 0xf101005f; (* arm_CMP X2 (rvalue (word 0x40)) *) + 0x54000140; (* arm_BEQ (word 0x28) *) + 0xf100c05f; (* arm_CMP X2 (rvalue (word 0x30)) *) + 0x54001200; (* arm_BEQ (word 0x240) *) + 0xf100805f; (* arm_CMP X2 (rvalue (word 0x20)) *) + 0x54001ea0; (* arm_BEQ (word 0x3d4) *) + 0xf100405f; (* arm_CMP X2 (rvalue (word 0x10)) *) + 0x54002740; (* arm_BEQ (word 0x4e8) *) + 0x14000163; (* arm_B (word 0x58c) *) + 0xd503201f; (* arm_NOP *) + 0xd503201f; (* arm_NOP *) + 0x4cdf7000; (* arm_LDR Q0 X0 (Postimmediate_Offset (word 0x10)) *) + 0x4cdf7001; (* arm_LDR Q1 X0 (Postimmediate_Offset (word 0x10)) *) + 0x4cdf7018; (* arm_LDR Q24 X0 (Postimmediate_Offset (word 0x10)) *) + 0x4cdf7019; (* arm_LDR Q25 X0 (Postimmediate_Offset (word 0x10)) *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x6e291f18; (* arm_EOR_VEC Q24 Q24 Q9 0x80 *) + 0x6e2a1f39; (* arm_EOR_VEC Q25 Q25 Q10 0x80 *) + 0x4e284a00; (* arm_AESE Q0 Q16 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a01; (* arm_AESE Q1 Q16 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a18; (* arm_AESE Q24 Q16 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284a19; (* arm_AESE Q25 Q16 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284a20; (* arm_AESE Q0 Q17 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a21; (* arm_AESE Q1 Q17 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a38; (* arm_AESE Q24 Q17 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284a39; (* arm_AESE Q25 Q17 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284980; (* arm_AESE Q0 Q12 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284981; (* arm_AESE Q1 Q12 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284998; (* arm_AESE Q24 Q12 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284999; (* arm_AESE Q25 Q12 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e2849a0; (* arm_AESE Q0 Q13 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849a1; (* arm_AESE Q1 Q13 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2849b8; (* arm_AESE Q24 Q13 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e2849b9; (* arm_AESE Q25 Q13 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e2849c0; (* arm_AESE Q0 Q14 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849c1; (* arm_AESE Q1 Q14 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2849d8; (* arm_AESE Q24 Q14 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e2849d9; (* arm_AESE Q25 Q14 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e2849e0; (* arm_AESE Q0 Q15 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849e1; (* arm_AESE Q1 Q15 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2849f8; (* arm_AESE Q24 Q15 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e2849f9; (* arm_AESE Q25 Q15 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284880; (* arm_AESE Q0 Q4 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284881; (* arm_AESE Q1 Q4 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284898; (* arm_AESE Q24 Q4 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284899; (* arm_AESE Q25 Q4 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e2848a0; (* arm_AESE Q0 Q5 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2848a1; (* arm_AESE Q1 Q5 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2848b8; (* arm_AESE Q24 Q5 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e2848b9; (* arm_AESE Q25 Q5 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284a40; (* arm_AESE Q0 Q18 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a41; (* arm_AESE Q1 Q18 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a58; (* arm_AESE Q24 Q18 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284a59; (* arm_AESE Q25 Q18 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284a60; (* arm_AESE Q0 Q19 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a61; (* arm_AESE Q1 Q19 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a78; (* arm_AESE Q24 Q19 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284a79; (* arm_AESE Q25 Q19 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284a80; (* arm_AESE Q0 Q20 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a81; (* arm_AESE Q1 Q20 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a98; (* arm_AESE Q24 Q20 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284a99; (* arm_AESE Q25 Q20 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284aa0; (* arm_AESE Q0 Q21 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284aa1; (* arm_AESE Q1 Q21 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284ab8; (* arm_AESE Q24 Q21 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284ab9; (* arm_AESE Q25 Q21 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284ac0; (* arm_AESE Q0 Q22 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284ac1; (* arm_AESE Q1 Q22 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284ad8; (* arm_AESE Q24 Q22 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284ad9; (* arm_AESE Q25 Q22 *) + 0x4e286b39; (* arm_AESMC Q25 Q25 *) + 0x4e284ae0; (* arm_AESE Q0 Q23 *) + 0x4e284ae1; (* arm_AESE Q1 Q23 *) + 0x4e284af8; (* arm_AESE Q24 Q23 *) + 0x4e284af9; (* arm_AESE Q25 Q23 *) + 0x6e271c00; (* arm_EOR_VEC Q0 Q0 Q7 0x80 *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x6e271c21; (* arm_EOR_VEC Q1 Q1 Q7 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x6e271f18; (* arm_EOR_VEC Q24 Q24 Q7 0x80 *) + 0x6e291f18; (* arm_EOR_VEC Q24 Q24 Q9 0x80 *) + 0x6e271f39; (* arm_EOR_VEC Q25 Q25 Q7 0x80 *) + 0x6e2a1f39; (* arm_EOR_VEC Q25 Q25 Q10 0x80 *) + 0x4c9fa020; (* arm_STP Q0 Q1 X1 (Postimmediate_Offset (word 0x20)) *) + 0x4c9fa038; (* arm_STP Q24 Q25 X1 (Postimmediate_Offset (word 0x20)) *) + 0x9e660149; (* arm_FMOV_FtoI X9 Q10 0x0 0x40 *) + 0x9eae014a; (* arm_FMOV_FtoI X10 Q10 0x1 0x40 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670126; (* arm_FMOV_ItoF Q6 X9 0x0 *) + 0x9eaf0146; (* arm_FMOV_ItoF Q6 X10 0x1 *) + 0x140000da; (* arm_B (word 0x368) *) + 0xd503201f; (* arm_NOP *) + 0x4cdfa000; (* arm_LDP Q0 Q1 X0 (Postimmediate_Offset (word 0x20)) *) + 0x4cdf7018; (* arm_LDR Q24 X0 (Postimmediate_Offset (word 0x10)) *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x6e291f18; (* arm_EOR_VEC Q24 Q24 Q9 0x80 *) + 0x4e284a00; (* arm_AESE Q0 Q16 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a01; (* arm_AESE Q1 Q16 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a18; (* arm_AESE Q24 Q16 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284a20; (* arm_AESE Q0 Q17 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a21; (* arm_AESE Q1 Q17 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a38; (* arm_AESE Q24 Q17 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284980; (* arm_AESE Q0 Q12 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284981; (* arm_AESE Q1 Q12 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284998; (* arm_AESE Q24 Q12 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e2849a0; (* arm_AESE Q0 Q13 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849a1; (* arm_AESE Q1 Q13 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2849b8; (* arm_AESE Q24 Q13 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e2849c0; (* arm_AESE Q0 Q14 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849c1; (* arm_AESE Q1 Q14 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2849d8; (* arm_AESE Q24 Q14 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e2849e0; (* arm_AESE Q0 Q15 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849e1; (* arm_AESE Q1 Q15 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2849f8; (* arm_AESE Q24 Q15 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284880; (* arm_AESE Q0 Q4 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284881; (* arm_AESE Q1 Q4 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284898; (* arm_AESE Q24 Q4 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e2848a0; (* arm_AESE Q0 Q5 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2848a1; (* arm_AESE Q1 Q5 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2848b8; (* arm_AESE Q24 Q5 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284a40; (* arm_AESE Q0 Q18 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a41; (* arm_AESE Q1 Q18 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a58; (* arm_AESE Q24 Q18 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284a60; (* arm_AESE Q0 Q19 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a61; (* arm_AESE Q1 Q19 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a78; (* arm_AESE Q24 Q19 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284a80; (* arm_AESE Q0 Q20 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a81; (* arm_AESE Q1 Q20 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a98; (* arm_AESE Q24 Q20 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284aa0; (* arm_AESE Q0 Q21 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284aa1; (* arm_AESE Q1 Q21 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284ab8; (* arm_AESE Q24 Q21 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284ac0; (* arm_AESE Q0 Q22 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284ac1; (* arm_AESE Q1 Q22 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284ad8; (* arm_AESE Q24 Q22 *) + 0x4e286b18; (* arm_AESMC Q24 Q24 *) + 0x4e284ae0; (* arm_AESE Q0 Q23 *) + 0x4e284ae1; (* arm_AESE Q1 Q23 *) + 0x4e284af8; (* arm_AESE Q24 Q23 *) + 0x6e271c00; (* arm_EOR_VEC Q0 Q0 Q7 0x80 *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x6e271c21; (* arm_EOR_VEC Q1 Q1 Q7 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x6e271f18; (* arm_EOR_VEC Q24 Q24 Q7 0x80 *) + 0x6e291f18; (* arm_EOR_VEC Q24 Q24 Q9 0x80 *) + 0x4c9fa020; (* arm_STP Q0 Q1 X1 (Postimmediate_Offset (word 0x20)) *) + 0x4c9f7038; (* arm_STR Q24 X1 (Postimmediate_Offset (word 0x10)) *) + 0x9e660129; (* arm_FMOV_FtoI X9 Q9 0x0 0x40 *) + 0x9eae012a; (* arm_FMOV_FtoI X10 Q9 0x1 0x40 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670126; (* arm_FMOV_ItoF Q6 X9 0x0 *) + 0x9eaf0146; (* arm_FMOV_ItoF Q6 X10 0x1 *) + 0x14000072; (* arm_B (word 0x1c8) *) + 0x4cdfa000; (* arm_LDP Q0 Q1 X0 (Postimmediate_Offset (word 0x20)) *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x4e284a00; (* arm_AESE Q0 Q16 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a01; (* arm_AESE Q1 Q16 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a20; (* arm_AESE Q0 Q17 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a21; (* arm_AESE Q1 Q17 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284980; (* arm_AESE Q0 Q12 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284981; (* arm_AESE Q1 Q12 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2849a0; (* arm_AESE Q0 Q13 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849a1; (* arm_AESE Q1 Q13 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2849c0; (* arm_AESE Q0 Q14 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849c1; (* arm_AESE Q1 Q14 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2849e0; (* arm_AESE Q0 Q15 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849e1; (* arm_AESE Q1 Q15 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284880; (* arm_AESE Q0 Q4 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284881; (* arm_AESE Q1 Q4 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e2848a0; (* arm_AESE Q0 Q5 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2848a1; (* arm_AESE Q1 Q5 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a40; (* arm_AESE Q0 Q18 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a41; (* arm_AESE Q1 Q18 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a60; (* arm_AESE Q0 Q19 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a61; (* arm_AESE Q1 Q19 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284a80; (* arm_AESE Q0 Q20 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a81; (* arm_AESE Q1 Q20 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284aa0; (* arm_AESE Q0 Q21 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284aa1; (* arm_AESE Q1 Q21 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284ac0; (* arm_AESE Q0 Q22 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284ac1; (* arm_AESE Q1 Q22 *) + 0x4e286821; (* arm_AESMC Q1 Q1 *) + 0x4e284ae0; (* arm_AESE Q0 Q23 *) + 0x4e284ae1; (* arm_AESE Q1 Q23 *) + 0x6e271c00; (* arm_EOR_VEC Q0 Q0 Q7 0x80 *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x6e271c21; (* arm_EOR_VEC Q1 Q1 Q7 0x80 *) + 0x6e281c21; (* arm_EOR_VEC Q1 Q1 Q8 0x80 *) + 0x4c9fa020; (* arm_STP Q0 Q1 X1 (Postimmediate_Offset (word 0x20)) *) + 0x9e660109; (* arm_FMOV_FtoI X9 Q8 0x0 0x40 *) + 0x9eae010a; (* arm_FMOV_FtoI X10 Q8 0x1 0x40 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670126; (* arm_FMOV_ItoF Q6 X9 0x0 *) + 0x9eaf0146; (* arm_FMOV_ItoF Q6 X10 0x1 *) + 0x1400002b; (* arm_B (word 0xac) *) + + (* Lxts_enc_tail1x: *) + (* pc + 0x938 *) + 0x4cdf7000; (* arm_LDR Q0 X0 (Postimmediate_Offset (word 0x10)) *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x4e284a00; (* arm_AESE Q0 Q16 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a20; (* arm_AESE Q0 Q17 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284980; (* arm_AESE Q0 Q12 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849a0; (* arm_AESE Q0 Q13 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849c0; (* arm_AESE Q0 Q14 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2849e0; (* arm_AESE Q0 Q15 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284880; (* arm_AESE Q0 Q4 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e2848a0; (* arm_AESE Q0 Q5 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a40; (* arm_AESE Q0 Q18 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a60; (* arm_AESE Q0 Q19 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284a80; (* arm_AESE Q0 Q20 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284aa0; (* arm_AESE Q0 Q21 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284ac0; (* arm_AESE Q0 Q22 *) + 0x4e286800; (* arm_AESMC Q0 Q0 *) + 0x4e284ae0; (* arm_AESE Q0 Q23 *) + 0x6e271c00; (* arm_EOR_VEC Q0 Q0 Q7 0x80 *) + 0x6e261c00; (* arm_EOR_VEC Q0 Q0 Q6 0x80 *) + 0x4c9f7020; (* arm_STR Q0 X1 (Postimmediate_Offset (word 0x10)) *) + 0x9e6600c9; (* arm_FMOV_FtoI X9 Q6 0x0 0x40 *) + 0x9eae00ca; (* arm_FMOV_FtoI X10 Q6 0x1 0x40 *) + 0x93ca8156; (* arm_ROR X22 X10 0x20 *) + 0x93c9fd4a; (* arm_EXTR X10 X10 X9 0x3f *) + 0x0a967e6b; (* arm_AND W11 W19 (Shiftedreg W22 ASR 0x1f) *) + 0xca090569; (* arm_EOR X9 X11 (Shiftedreg X9 LSL 0x1) *) + 0x9e670126; (* arm_FMOV_ItoF Q6 X9 0x0 *) + 0x9eaf0146; (* arm_FMOV_ItoF Q6 X10 0x1 *) + 0x14000002; (* arm_B (word 0x8) *) + 0xd503201f; (* arm_NOP *) + + (* Lxts_enc_done: *) + (* pc + 0x9e0 *) + 0xf2400ebf; (* arm_TST X21 (rvalue (word 0xf)) *) + 0x54000540; (* arm_BEQ (word 0xa8) *) + 0xaa0003f4; (* arm_MOV X20 X0 *) + 0xaa0103ed; (* arm_MOV X13 X1 *) + 0xd1004021; (* arm_SUB X1 X1 (rvalue (word 0x10)) *) + 0xf10006b5; (* arm_SUBS X21 X21 (rvalue (word 0x1)) *) + 0x3875682f; (* arm_LDRB W15 X1 (Register_Offset X21) *) + 0x38756a8e; (* arm_LDRB W14 X20 (Register_Offset X21) *) + 0x383569af; (* arm_STRB W15 X13 (Register_Offset X21) *) + 0x3835682e; (* arm_STRB W14 X1 (Register_Offset X21) *) + 0x54ffff6c; (* arm_BGT (word 0x1fffec) *) + 0x4c40703a; (* arm_LDR Q26 X1 No_Offset *) + 0x6e261f5a; (* arm_EOR_VEC Q26 Q26 Q6 0x80 *) + + 0x4e284a1a; (* arm_AESE Q26 Q16 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284a3a; (* arm_AESE Q26 Q17 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e28499a; (* arm_AESE Q26 Q12 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e2849ba; (* arm_AESE Q26 Q13 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e2849da; (* arm_AESE Q26 Q14 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e2849fa; (* arm_AESE Q26 Q15 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e28489a; (* arm_AESE Q26 Q4 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e2848ba; (* arm_AESE Q26 Q5 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284a5a; (* arm_AESE Q26 Q18 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284a7a; (* arm_AESE Q26 Q19 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284a9a; (* arm_AESE Q26 Q20 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284aba; (* arm_AESE Q26 Q21 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284ada; (* arm_AESE Q26 Q22 *) + 0x4e286b5a; (* arm_AESMC Q26 Q26 *) + 0x4e284afa; (* arm_AESE Q26 Q23 *) + 0x6e271f5a; (* arm_EOR_VEC Q26 Q26 Q7 0x80 *) + + 0x6e261f5a; (* arm_EOR_VEC Q26 Q26 Q6 0x80 *) + 0x4c00703a; (* arm_STR Q26 X1 No_Offset *) + 0xa94053f3; (* arm_LDP X19 X20 SP (Immediate_Offset (iword (&0x0))) *) + 0xa9415bf5; (* arm_LDP X21 X22 SP (Immediate_Offset (iword (&0x10))) *) + 0x6d4227e8; (* arm_LDP D8 D9 SP (Immediate_Offset (iword (&0x20))) *) + 0x6d432fea; (* arm_LDP D10 D11 SP (Immediate_Offset (iword (&0x30))) *) + 0x6d4437ec; (* arm_LDP D12 D13 SP (Immediate_Offset (iword (&0x40))) *) + 0x6d453fee; (* arm_LDP D14 D15 SP (Immediate_Offset (iword (&0x50))) *) + 0x910183ff; (* arm_ADD SP SP (rvalue (word 0x60)) *) + 0xd65f03c0 (* arm_RET X30 *) +];; + +let AES256_XTS_ENCRYPT_EXEC = ARM_MK_EXEC_RULE aes256_xts_encrypt_mc;; + +(**********************************************************************) +(** Encrypt-specific lemmas **) + +let LENGTH_OF_AES256_XTS_ENCRYPT_REC = prove( + `!(i:num) (m:num) (P:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + LENGTH(aes256_xts_encrypt_rec i m P iv key1 key2) = (if m < i then 0 else (m - i + 1) * 0x10)`, + REPEAT GEN_TAC THEN + (* Wellfounded induction with measure (m + 1) - i + Note that the parentheses are essential because of the precedence of + and - *) + WF_INDUCT_TAC `(m + 1) - i` THEN + ONCE_REWRITE_TAC[aes256_xts_encrypt_rec] THEN + COND_CASES_TAC THENL + [ SIMP_TAC[LENGTH_EQ_NIL]; + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[LENGTH_APPEND] THEN + SUBGOAL_THEN `~(m < i) ==> (m + 1) - (i + 1) < (m + 1) - i` ASSUME_TAC THENL + [ ASM_ARITH_TAC ; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + COND_CASES_TAC THENL + [ASM_ARITH_TAC; ASM_ARITH_TAC]] +);; + +let LENGTH_OF_FST_OF_ENC_CIPHER_STEALING = prove( + `!(block:byte list) (tail:byte list) (tail_len:num) + (iv:int128) (i:num) (key1:int128 list) (key2:int128 list). + LENGTH (FST (cipher_stealing_encrypt block tail tail_len iv i key1 key2)) = 16`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[cipher_stealing_encrypt] THEN + ASM_REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] +);; + +let LENGTH_OF_SND_OF_ENC_CIPHER_STEALING = prove( + `!(block:byte list) (tail:byte list) (tail_len:num) + (iv:int128) (i:num) (key1:int128 list) (key2:int128 list). + LENGTH (SND (cipher_stealing_encrypt block tail tail_len iv i key1 key2)) = MIN tail_len 16`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[cipher_stealing_encrypt] THEN + ASM_REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[LENGTH_SUB_LIST] THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[MIN] THEN + CONV_TAC NUM_REDUCE_CONV +);; + +let LENGTH_OF_AES256_XTS_ENCRYPT_TAIL = prove( + `! (i:num) (tail_len:num) (P:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + LENGTH(aes256_xts_encrypt_tail i tail_len P iv key1 key2) = 0x10 + MIN tail_len 16`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[aes256_xts_encrypt_tail] THEN + COND_CASES_TAC THENL [ + ASM_REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[ADD_CLAUSES; MIN] THEN + CONV_TAC NUM_REDUCE_CONV; + + REWRITE_TAC[LET_DEF; LET_END_DEF; LENGTH_APPEND] THEN + REWRITE_TAC[LENGTH_OF_FST_OF_ENC_CIPHER_STEALING] THEN + REWRITE_TAC[LENGTH_OF_SND_OF_ENC_CIPHER_STEALING]] +);; + +let LENGTH_OF_AES256_XTS_ENCRYPT_REC_TRIVIAL = prove( + `!(pt:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + LENGTH (aes256_xts_encrypt_rec 0x0 0x0 pt iv key1 key2) = 16`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_REC] THEN + CONV_TAC NUM_REDUCE_CONV +);; + +let LENGTH_OF_AES256_XTS_ENCRYPT_TAIL_TRIVIAL = prove( + `!(pt:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + LENGTH(aes256_xts_encrypt_tail 0 0 pt iv key1 key2) = 16`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_TAIL] THEN + CONV_TAC NUM_REDUCE_CONV +);; + +let AES256_XTS_ENCRYPT_REC_EQ_TAIL_TRIVIAL = prove( + `!(pt:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + aes256_xts_encrypt_rec 0x0 0x0 ct iv key1 key2 = + aes256_xts_encrypt_tail 0x0 0x0 ct iv key1 key2`, + REPEAT STRIP_TAC THEN + ONCE_REWRITE_TAC[aes256_xts_encrypt_rec] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + ONCE_REWRITE_TAC[aes256_xts_encrypt_rec] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[APPEND_NIL] THEN + + REWRITE_TAC[aes256_xts_encrypt_tail] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV +);; + +let LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS = prove( + `! (i:num) (pt:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + LENGTH(aes256_xts_encrypt pt (0x10 * i) iv key1 key2) = 0x10 * i`, + REPEAT STRIP_TAC THEN + SPEC_TAC (`i:num`, `i:num`) THEN + INDUCT_TAC THENL + [ + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[aes256_xts_encrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LENGTH_EQ_NIL]; + ALL_TAC] THEN + + REWRITE_TAC[ADD1; LEFT_ADD_DISTRIB] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[aes256_xts_encrypt] THEN + + ASM_CASES_TAC `i = 0` THENL + [ ASM_SIMP_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[LET_DEF;LET_END_DEF;SUB_0] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_TAIL_TRIVIAL] + ; ALL_TAC + ] THEN + + SUBGOAL_THEN `~(0x10 * i + 0x10 < 0x10)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC ] THEN ASM_SIMP_TAC[] THEN + REWRITE_TAC[ARITH_RULE `0x10 * i + 0x10 = 0x10 * (i + 1)`; MOD_MULT] THEN + IMP_REWRITE_TAC[LET_DEF; LET_END_DEF;SUB_0;DIV_MULT] THEN + CONJ_TAC THENL [ALL_TAC; ARITH_TAC] THEN + SUBGOAL_THEN `~(i + 0x1 < 0x2)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN ASM_SIMP_TAC[] THEN + REWRITE_TAC[LENGTH_APPEND] THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_REC] THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_TAIL] THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_ARITH_TAC +);; + +let LENGTH_OF_AES256_XTS_ENCRYPT = prove( + `! (i:num) (tail_len:num) (pt:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + ~(tail_len = 0) /\ tail_len < 16 ==> + LENGTH(aes256_xts_encrypt pt (16 * i + 16 + tail_len) iv key1 key2) = 16 * i + 16 + tail_len`, + REPEAT STRIP_TAC THEN + (* Case 1: i = 0 *) + ASM_CASES_TAC `i = 0` THENL + [ + ASM_SIMP_TAC[ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[aes256_xts_encrypt] THEN + SUBGOAL_THEN `~(0x10 + tail_len < 0x10)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `(0x10 + tail_len) MOD 0x10 = tail_len` ASSUME_TAC THENL + [ REWRITE_TAC[ARITH_RULE `0x10 + tail_len = 1 * 16 + tail_len`] THEN + IMP_REWRITE_TAC[MOD_MULT_ADD; MOD_LT]; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + SUBGOAL_THEN `((0x10 + tail_len) - tail_len) DIV 0x10 = 1` SUBST1_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC ] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_TAIL] THEN + ASM_ARITH_TAC; + ALL_TAC + ] THEN + + (* Case 2: i >= 1 *) + ASM_CASES_TAC `i >= 1` THENL + [ + REWRITE_TAC[aes256_xts_encrypt] THEN + SUBGOAL_THEN `(0x10 * i + 0x10 + tail_len) MOD 0x10 = tail_len` SUBST1_TAC THENL + [ REWRITE_TAC[ADD_ASSOC; ARITH_RULE `0x10 * i + 0x10 = 16 * (i + 1)`] THEN + IMP_REWRITE_TAC[MOD_MULT_ADD; MOD_LT]; ALL_TAC] THEN + SUBGOAL_THEN `~(0x10 * i + 0x10 + tail_len < 0x10)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + SUBGOAL_THEN `((0x10 * i + 0x10 + tail_len) - tail_len) DIV 0x10 = i + 1` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `(0x10 * i + 0x10 + tail_len) - tail_len = 16 * (i + 1)`] THEN + IMP_REWRITE_TAC[DIV_MULT] THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(i + 1 < 2)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + IMP_REWRITE_TAC[ARITH_RULE `(i + 1) - 2 = i - 1`; ADD_SUB] THEN + REWRITE_TAC[LENGTH_APPEND] THEN + IMP_REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_REC] THEN + IMP_REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_TAIL] THEN + ASM_ARITH_TAC; + ALL_TAC + ] THEN + + ASM_ARITH_TAC +);; + +let AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK = prove( + `!(n:num) (pt:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + bytes_to_int128 + (aes256_xts_encrypt_tail n 0x0 pt iv key1 key2) = + aes256_xts_encrypt_round + (bytes_to_int128 (SUB_LIST (n * 0x10,0x10) pt)) + (calculate_tweak n iv key2) key1`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[aes256_xts_encrypt_tail] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[BYTES_TO_INT128_OF_INT128_TO_BYTES] +);; + +let AES256_XTS_ENCRYPT_REC_EQ_TAIL = prove( + `!(i:num) (k:num) (pt:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + k >= i ==> + aes256_xts_encrypt_rec i (k + 1) pt iv key1 key2 = + APPEND (aes256_xts_encrypt_rec i k pt iv key1 key2) + (aes256_xts_encrypt_tail (k + 1) 0x0 pt iv key1 key2)`, + REPEAT GEN_TAC THEN + WF_INDUCT_TAC `(k + 1) - i` THEN + STRIP_TAC THEN + GEN_REWRITE_TAC (RATOR_CONV o ONCE_DEPTH_CONV) [aes256_xts_encrypt_rec] THEN + SUBGOAL_THEN `~(k + 0x1 < i)` ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + SUBGOAL_THEN `(k + 1) - (i + 1) < (k + 1) - i` ASSUME_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + FIRST_X_ASSUM (MP_TAC o SPECL [`k:num`; `i + 1:num`]) THEN + ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + ASM_CASES_TAC `k >= i + 1` THENL + [ + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + REWRITE_TAC[APPEND_ASSOC] THEN + AP_THM_TAC THEN + GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [aes256_xts_encrypt_rec] THEN + SUBGOAL_THEN `~(k < i)` ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF]; ALL_TAC + ] THEN + SUBGOAL_THEN `k:num = i` ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + STRIP_TAC THEN ASM_REWRITE_TAC[] THEN + ONCE_REWRITE_TAC[aes256_xts_encrypt_rec] THEN + REWRITE_TAC[LT_REFL; LET_DEF; LET_END_DEF] THEN + ONCE_REWRITE_TAC[aes256_xts_encrypt_rec] THEN + REWRITE_TAC[ARITH_RULE `i < i + 1`; APPEND_NIL] THEN + AP_TERM_TAC THEN + REWRITE_TAC[aes256_xts_encrypt_tail; LET_DEF; LET_END_DEF] +);; + +let SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS = prove( + `!(i:num) (pt:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + (SUB_LIST (0,16 * i) + (aes256_xts_encrypt pt (16 * i + 16) iv key1 key2)) + = aes256_xts_encrypt pt (16 * i) iv key1 key2`, + REPEAT STRIP_TAC THEN + + (* when i = 0, trivial *) + ASM_CASES_TAC `i = 0` THENL + [ + ASM_REWRITE_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[CONJUNCT1 SUB_LIST; aes256_xts_encrypt] THEN + CONV_TAC NUM_REDUCE_CONV; + ALL_TAC + ] THEN + + (* when i = 1, using aes256_xts_encrypt_tail *) + ASM_CASES_TAC `i = 1` THENL + [ + ASM_REWRITE_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[aes256_xts_encrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`pt:byte list`; `iv:int128`; `key1: int128 list`; `key2: int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC_TRIVIAL) THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_LEFT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + REWRITE_TAC[AES256_XTS_ENCRYPT_REC_EQ_TAIL_TRIVIAL]; + ALL_TAC + ] THEN + + (* when i >= 2, using aes256_xts_encrypt_rec *) + REWRITE_TAC[aes256_xts_encrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `~(0x10 * i < 0x10)` ASSUME_TAC THENL + [ ASM_ARITH_TAC ; ALL_TAC] THEN + SUBGOAL_THEN `~(0x10 * i + 0x10 < 0x10)` ASSUME_TAC THENL + [ ASM_ARITH_TAC ; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + REWRITE_TAC[ARITH_RULE `16 * i + 16 = 16 * (i + 1)`; MOD_MULT] THEN + IMP_REWRITE_TAC[LET_DEF;LET_END_DEF;SUB_0;DIV_MULT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `~(i < 0x2)` ASSUME_TAC THENL + [ ASM_ARITH_TAC ; ALL_TAC] THEN + SUBGOAL_THEN `~(i + 1 < 0x2)` ASSUME_TAC THENL + [ ASM_ARITH_TAC ; ALL_TAC] THEN + ASM_SIMP_TAC[ARITH_RULE `(i + 0x1) - 0x2 = i - 1`; ADD_SUB] THEN + SUBGOAL_THEN `LENGTH (aes256_xts_encrypt_rec 0x0 (i - 0x1) pt iv key1 key2) = 16 * i` ASSUME_TAC THENL + [ REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_REC] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_LEFT; SUB_LIST_LENGTH_IMPLIES] THEN + CONJ_TAC THENL [ALL_TAC; ARITH_TAC] THEN + SUBGOAL_THEN `i - 1 = i - 2 + 1` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC ] THEN + ASM_REWRITE_TAC[] THEN + IMP_REWRITE_TAC[AES256_XTS_ENCRYPT_REC_EQ_TAIL] THEN + ASM_ARITH_TAC +);; + +let SUB_LIST_OF_AES256_XTS_ENCRYPT = prove( + `!(i:num) (tail_len:num) (pt:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + ~(tail_len = 0) /\ tail_len < 16 ==> + (SUB_LIST (0,16 * i) + (aes256_xts_encrypt pt (16 * i + 16 + tail_len) iv key1 key2)) + = aes256_xts_encrypt pt (16 * i) iv key1 key2`, + REPEAT STRIP_TAC THEN + (* Case 1: i = 0 *) + ASM_CASES_TAC `i = 0` THENL + [ + ASM_REWRITE_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[ADD; SUB_LIST_CLAUSES; aes256_xts_encrypt] THEN + CONV_TAC NUM_REDUCE_CONV; + ALL_TAC + ] THEN + (* Case 2: i = 1 *) + ASM_CASES_TAC `i = 1` THENL + [ + ASM_REWRITE_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[aes256_xts_encrypt; ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `~(0x20 + tail_len < 0x10)` ASSUME_TAC THENL [ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `(0x20 + tail_len) MOD 0x10 = tail_len` ASSUME_TAC THENL + [ ASM_SIMP_TAC[ARITH_RULE `32 = 2 * 16`; MOD_MULT_ADD] THEN + IMP_REWRITE_TAC[MOD_LT] + ; ALL_TAC] THEN + SUBGOAL_THEN `((0x20 + tail_len) - (0x20 + tail_len) MOD 0x10) DIV 0x10 = 0x2` ASSUME_TAC THENL + [ ASM_REWRITE_TAC[ADD_ASSOC; ADD_SUB] THEN + ARITH_TAC ; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_REWRITE_TAC[] THEN + MP_TAC (SPECL [`pt:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_REC_TRIVIAL) THEN + DISCH_TAC THEN IMP_REWRITE_TAC[SUB_LIST_APPEND_LEFT] THEN + REWRITE_TAC[AES256_XTS_ENCRYPT_REC_EQ_TAIL_TRIVIAL] THEN + MP_TAC (SPECL [`pt:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_TAIL_TRIVIAL) THEN + DISCH_TAC THEN IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + ARITH_TAC; + ALL_TAC + ] THEN + + (* Case 3: i >= 2 *) + ASM_CASES_TAC `i >= 2` THENL + [ + ASM_REWRITE_TAC[ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[aes256_xts_encrypt] THEN + SUBGOAL_THEN `~(0x10 * i < 0x10)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~((0x10 * i + 0x10) + tail_len < 0x10)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[LET_DEF; LET_END_DEF] THEN + SUBGOAL_THEN `((0x10 * i + 0x10) + tail_len) MOD 0x10 = tail_len` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `0x10 * i + 0x10 = 16 * (i + 1)`] THEN + IMP_REWRITE_TAC[MOD_MULT_ADD; MOD_LT] + ; ALL_TAC] THEN + REWRITE_TAC[ADD_SUB; MOD_MULT; SUB_0; + ARITH_RULE `0x10 * i + 0x10 = 16 * (i + 1)`] THEN + IMP_REWRITE_TAC[DIV_MULT] THEN + SUBGOAL_THEN `~(i + 1 < 2)` ASSUME_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(i < 2)` ASSUME_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[ADD_SUB; ARITH_RULE `(i + 1) - 2 = i - 1`] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0:num`; `(i - 1):num`; `pt:byte list`; `iv:int128`; + `key1:int128 list`; `key2:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SUBGOAL_THEN `~((i - 1) < 0)` ASSUME_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + IMP_REWRITE_TAC[ARITH_RULE `i >= 2 ==> i - 0x1 - 0x0 + 0x1 = i`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_LEFT] THEN + SIMP_TAC[ARITH_RULE `16 * i <= i * 16`] THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + SIMP_TAC[ARITH_RULE `i * 16 = 16 * i`] THEN + DISCH_TAC THEN + MP_TAC (SPECL [`0`; `(i-2):num`; `pt:byte list`; `iv:int128`; + `key1:int128 list`; `key2:int128 list`] AES256_XTS_ENCRYPT_REC_EQ_TAIL) THEN + ANTS_TAC THENL [ ASM_ARITH_TAC; ALL_TAC ] THEN + IMP_REWRITE_TAC[ARITH_RULE `i >= 2 ==> i - 0x2 + 0x1 = i - 1`]; + ALL_TAC + ] THEN + + ASM_ARITH_TAC +);; + +let READ_BYTES_EQ_READ_BYTE128_1BLOCK_ENC = prove( + `!(ptr:int64) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list) s. + (read (memory :> bytes128 pt_ptr) s = + aes256_xts_encrypt_round (bytes_to_int128 (SUB_LIST (0x0,0x10) ct)) + (calculate_tweak 0x0 iv key2) + key1) ==> + read (memory :> bytes (pt_ptr,0x10)) s = + num_of_bytelist (SUB_LIST (0x0,0x10) (aes256_xts_encrypt ct 0x10 iv key1 key2))`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[READ_MEMORY_BYTES_BYTES128] THEN + ASM_REWRITE_TAC[] THEN + REWRITE_TAC[aes256_xts_encrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[aes256_xts_encrypt_tail] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[SUB_LIST_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[NUM_OF_BYTELIST_OF_INT128_TO_BYTES] +);; + +let READ_BYTES_EQ_READ_BYTE128_2BLOCKS_ENC = prove( + `!(ptr:int64) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list) s. + (read (memory :> bytes128 pt_ptr) s = + aes256_xts_encrypt_round (bytes_to_int128 (SUB_LIST (0x0,0x10) ct)) + (calculate_tweak 0x0 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x10))) s = + aes256_xts_encrypt_round (bytes_to_int128 (SUB_LIST (0x10,0x10) ct)) + (calculate_tweak 0x1 iv key2) + key1) ==> + read (memory :> bytes (pt_ptr,0x20)) s = + num_of_bytelist (SUB_LIST (0x0,0x20) (aes256_xts_encrypt ct 0x20 iv key1 key2))`, + REPEAT STRIP_TAC THEN + IMP_REWRITE_TAC[ARITH_RULE `0x20 = 0x10 + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `aes256_xts_encrypt ct 0x20 iv key1 key2` THEN + REPEAT CONJ_TAC THENL + [ + CONV_TAC NUM_REDUCE_CONV; + + MP_TAC (SPECL [`2:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + ARITH_TAC; + + REWRITE_TAC[aes256_xts_encrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC_TRIVIAL) THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + REWRITE_TAC[aes256_xts_encrypt_tail] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[SUB_LIST_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[NUM_OF_BYTELIST_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[BYTES_TO_INT128_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV; + + MP_TAC (SPECL [`1:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + CONV_TAC NUM_REDUCE_CONV THEN + SIMP_TAC[] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_1BLOCK_ENC] THEN + MP_TAC (SPECL [`1:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] + ] +);; + +let READ_BYTES_EQ_READ_BYTE128_3BLOCKS_ENC = prove( + `!(ptr:int64) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list) s. + (read (memory :> bytes128 pt_ptr) s = + aes256_xts_encrypt_round (bytes_to_int128 (SUB_LIST (0x0,0x10) ct)) + (calculate_tweak 0x0 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x10))) s = + aes256_xts_encrypt_round (bytes_to_int128 (SUB_LIST (0x10,0x10) ct)) + (calculate_tweak 0x1 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x20))) s = + aes256_xts_encrypt_round (bytes_to_int128 (SUB_LIST (0x20,0x10) ct)) + (calculate_tweak 0x2 iv key2) + key1) ==> + read (memory :> bytes (pt_ptr,0x30)) s = + num_of_bytelist (SUB_LIST (0x0,0x30) (aes256_xts_encrypt ct 0x30 iv key1 key2))`, + REPEAT STRIP_TAC THEN + IMP_REWRITE_TAC[ARITH_RULE `0x30 = 0x20 + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `aes256_xts_encrypt ct 0x30 iv key1 key2` THEN + REPEAT CONJ_TAC THENL + [ + CONV_TAC NUM_REDUCE_CONV; + + MP_TAC (SPECL [`3:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + ARITH_TAC; + + REWRITE_TAC[aes256_xts_encrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0:num`; `1:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + REWRITE_TAC[aes256_xts_encrypt_tail] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[SUB_LIST_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[NUM_OF_BYTELIST_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[BYTES_TO_INT128_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV; + ALL_TAC] THEN + + MP_TAC (SPECL [`2:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + CONV_TAC NUM_REDUCE_CONV THEN + SIMP_TAC[] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_2BLOCKS_ENC] THEN + MP_TAC (SPECL [`2:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] +);; + +let READ_BYTES_EQ_READ_BYTE128_4BLOCKS_ENC = prove( + `!(ptr:int64) (ct:byte list) (iv:int128) (key1:int128 list) (key2:int128 list) s. + (read (memory :> bytes128 pt_ptr) s = + aes256_xts_encrypt_round (bytes_to_int128 (SUB_LIST (0x0,0x10) ct)) + (calculate_tweak 0x0 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x10))) s = + aes256_xts_encrypt_round (bytes_to_int128 (SUB_LIST (0x10,0x10) ct)) + (calculate_tweak 0x1 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x20))) s = + aes256_xts_encrypt_round (bytes_to_int128 (SUB_LIST (0x20,0x10) ct)) + (calculate_tweak 0x2 iv key2) + key1) ==> + (read (memory :> bytes128 (word_add pt_ptr (word 0x30))) s = + aes256_xts_encrypt_round (bytes_to_int128 (SUB_LIST (0x30,0x10) ct)) + (calculate_tweak 0x3 iv key2) + key1) ==> + read (memory :> bytes (pt_ptr,0x40)) s = + num_of_bytelist (SUB_LIST (0x0,0x40) (aes256_xts_encrypt ct 0x40 iv key1 key2))`, + REPEAT STRIP_TAC THEN + IMP_REWRITE_TAC[ARITH_RULE `0x40 = 0x30 + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `aes256_xts_encrypt ct 0x40 iv key1 key2` THEN + REPEAT CONJ_TAC THENL + [ + CONV_TAC NUM_REDUCE_CONV; + + MP_TAC (SPECL [`4:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + ARITH_TAC; + + REWRITE_TAC[aes256_xts_encrypt] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0:num`; `2:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + REWRITE_TAC[aes256_xts_encrypt_tail] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[SUB_LIST_OF_INT128_TO_BYTES] THEN + REWRITE_TAC[BYTES_TO_INT128_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV; + ALL_TAC] THEN + + MP_TAC (SPECL [`3:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + CONV_TAC NUM_REDUCE_CONV THEN + SIMP_TAC[] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_3BLOCKS_ENC] THEN + MP_TAC (SPECL [`3:num`; `ct:byte list`; `iv:int128`; `key1:int128 list`; `key2:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] +);; + + +(**********************************************************************) +(** Tactics **) + +let AESENC_TAC = + REWRITE_TAC [aes256_encrypt] THEN + REWRITE_TAC EL_15_128_CLAUSES THEN + REWRITE_TAC [aes256_encrypt_round; aese; aesmc] THEN + CONV_TAC (TOP_DEPTH_CONV let_CONV) THEN + BITBLAST_TAC;; + +let AESXTS_ENC_ONE_BLOCK_TAC = + REWRITE_TAC [aes256_xts_encrypt_1block] THEN + REWRITE_TAC [xts_init_tweak; aes256_xts_encrypt_round] THEN + CONV_TAC (TOP_DEPTH_CONV let_CONV) THEN + GEN_REWRITE_TAC LAND_CONV [WORD_XOR_SYM] THEN + REPEAT (AP_THM_TAC THEN AP_TERM_TAC) THEN + BITBLAST_TAC;; + +let TWEAK_UPDATE_CONV = + let thms = CONJUNCTS + ((REWRITE_RULE[ARITH; ADD_0] o + CONV_RULE EXPAND_CASES_CONV o ARITH_RULE) + `forall i. i < 9 ==> forall n. n + SUC i = SUC (n + i)`) in + NUM_REDUCE_CONV THENC + RATOR_CONV (LAND_CONV (num_CONV ORELSEC + FIRST_CONV + (map (fun th -> CHANGED_CONV (ONCE_REWRITE_CONV [th])) thms))) THENC + REWRITE_CONV [CONJUNCT2 calculate_tweak] THENC + GF_128_MULT_BY_PRIMITIVE_CONV;; + +(* differs from the Decrypt definition in using key2_lst instead of key2 + TODO: it seems that value of indm1 doesn't matter to the tactic, can it be removed? *) +let TWEAK_TAC reg ind indm1 = + let lower_term = subst [ind,`ind:num`] `(word_zx:int128->int64) (calculate_tweak ind iv key2_lst)` in + let upper_term = subst [ind,`ind:num`] `(word_subword:int128->num#num->int64) (calculate_tweak ind iv key2_lst) (64,64)` in + let full_term = subst [ind,`ind:num`] `calculate_tweak ind iv key2_lst` in + let full_lemma = subst [reg,`reg:(armstate,int128)component`] `read (reg:(armstate,int128)component) (s:armstate) = a ==> !a'. a = a' ==> read reg s = a'` in + let abbrev_term = subst [indm1,`indm1:num`] `tweak_pre:int128 = (calculate_tweak indm1 iv key2_lst)` in + FIRST_X_ASSUM(MP_TAC o SPEC lower_term + o MATCH_MP (MESON[] `read X9 s = a ==> !a'. a = a' ==> read X9 s = a'`)) THEN + ANTS_TAC THENL [CONV_TAC (RAND_CONV (RAND_CONV TWEAK_UPDATE_CONV)) THEN + ABBREV_TAC abbrev_term THEN + BITBLAST_TAC; DISCH_TAC] THEN + FIRST_X_ASSUM(MP_TAC o SPEC upper_term + o MATCH_MP (MESON[] `read X10 s = a ==> !a'. a = a' ==> read X10 s = a'`)) THEN + ANTS_TAC THENL [CONV_TAC (RAND_CONV (RATOR_CONV (RAND_CONV TWEAK_UPDATE_CONV))) THEN + ABBREV_TAC abbrev_term THEN + BITBLAST_TAC; DISCH_TAC] THEN + FIRST_X_ASSUM(MP_TAC o SPEC full_term + o MATCH_MP (MESON[] full_lemma)) THEN + ANTS_TAC THENL [CONV_TAC (RAND_CONV TWEAK_UPDATE_CONV) THEN + ABBREV_TAC abbrev_term THEN + BITBLAST_TAC; DISCH_TAC];; + +let XTSENC_TAC reg ind ind_tweak = + let tm = subst [ind, `ind:num`; ind_tweak, `ind_tweak:num`] + `aes256_xts_encrypt_round (bytes_to_int128 (SUB_LIST (ind,0x10) (pt_in:byte list))) + (calculate_tweak (ind_tweak) iv key2_lst) key1_lst` in + let lemma = subst [reg, `reg:(armstate,int128)component`] + `read (reg:(armstate,int128)component) (s:armstate) = a ==> !a'. a = a' ==> read reg s = a'` in + FIRST_X_ASSUM(MP_TAC o SPEC tm o MATCH_MP (MESON[] lemma)) THEN + ANTS_TAC THENL + [ EXPAND_TAC "key1_lst" THEN + CONV_TAC (RAND_CONV ( + REWRITE_CONV [aes256_xts_encrypt_round] THENC + DEPTH_CONV let_CONV)) THEN + GEN_REWRITE_TAC LAND_CONV [WORD_XOR_SYM] THEN + REPEAT (AP_THM_TAC THEN AP_TERM_TAC) THEN + GEN_REWRITE_TAC ONCE_DEPTH_CONV [WORD_XOR_SYM] THEN + AESENC_TAC; DISCH_TAC ];; + +let ENC_TAIL_SWAP_CASE_0_TAC = + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN REWRITE_TAC[th]) THEN + (* Simplify so that symbolic execution could match up, but couldn't use + CONV_TAC NUM_REDUCE_CONV because of non-overlapping *) + + RULE_ASSUM_TAC(REWRITE_RULE[ADD_0]) THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (1--5) THEN + + RULE_ASSUM_TAC(REWRITE_RULE[GSYM ADD_ASSOC]) THEN + RULE_ASSUM_TAC (CONV_RULE NUM_REDUCE_CONV) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + + REPEAT CONJ_TAC THENL + [ MATCH_MP_TAC (snd (EQ_IMP_RULE (SPECL [`(word_add ctxt_p (word l1_curr_len)):int64`; `s5:armstate`; + `(cipher_stealing_inv 0x0 l1_curr_len (val (tail_len:int64)) CC pt_in):int128`] + BREAK_ONE_BLOCK_INTO_BYTES))) THEN + CONV_TAC(ONCE_DEPTH_CONV NORMALIZE_RELATIVE_ADDRESS_CONV) THEN + ASM_REWRITE_TAC[] THEN + + MP_TAC (SPECL [`0x0`; `l1_curr_len:num`; `tail_len:int64`; `CC:int128`; `pt_in:byte list`] + CIPHER_STEALING_BYTE_EQUAL) THEN + CHANGED_TAC(CONV_TAC NUM_REDUCE_CONV) THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + + ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + STRIP_TAC THEN + + (* The case for 0 needed to be separated out and simplified from CIPHER_STEALING_INV_SIMP_TAC *) + CONJ_TAC THENL + [ ASM_REWRITE_TAC[] THEN + IMP_REWRITE_TAC[WORD_ZX_ZX; WORD_ZX_TRIVIAL] THEN + REWRITE_TAC[DIMINDEX_8; DIMINDEX_32; DIMINDEX_64] THEN + ASM_ARITH_TAC ; ALL_TAC] THEN + + MAP_EVERY (fun i -> CONJ_TAC THENL + [CIPHER_STEALING_INV_SIMP_TAC (mk_numeral (num i)); ALL_TAC]) (1--0xe) THEN + CIPHER_STEALING_INV_SIMP_TAC `0xf:num`; + + MP_TAC (SPECL [`ctxt_p:int64`; `0x0`; `val (tail_len:int64)`; + `l1_curr_len:num`; `(int128_to_bytes CC):byte list`; `s5:armstate`] + BYTE_LIST_AT_SPLIT_BACKWARDS_CARNONICAL) THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV THEN + CONV_TAC(ONCE_DEPTH_CONV NORMALIZE_RELATIVE_ADDRESS_CONV) THEN + ASM_SIMP_TAC[] THEN + ANTS_TAC THENL + [ IMP_REWRITE_TAC[WORD_ZX_ZX] THEN + REWRITE_TAC[DIMINDEX_8; DIMINDEX_32; DIMINDEX_64] THEN + MP_TAC (SPECL [`0x0`; `l1_curr_len:num`; `tail_len:int64`; `CC:int128`; `pt_in:byte list`] + CIPHER_STEALING_INV_SELECT) THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_SIMP_TAC[] ; ALL_TAC ] THEN + REWRITE_TAC[ADD_ASSOC; ARITH_RULE `((l1_curr_len + 0x10) + 0x0) = (l1_curr_len + 0x10)`]; (* will need replacement with v *) + + WORD_ARITH_TAC; + WORD_ARITH_TAC; +];; + +let ENC_TAIL_SWAP_CASE_TAC case = + let c_tm = `case:num` in + let v_tm = `v:num` in + let v = rand (concl (NUM_RED_CONV (subst [case,c_tm] `0x10 + case`))) in + let r1 = subst [case,c_tm; v,v_tm] `((l1_curr_len + 0x10) + case) = (l1_curr_len + v)` in + let t1 = subst [case,c_tm] `(cipher_stealing_inv case l1_curr_len (val (tail_len:int64)) CC pt_in):int128` in + + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN REWRITE_TAC[th]) THEN (* pop assum: i = case *) + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (1--5) THEN + RULE_ASSUM_TAC(REWRITE_RULE[GSYM ADD_ASSOC]) THEN + RULE_ASSUM_TAC (CONV_RULE NUM_REDUCE_CONV) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + (* For case = 0x1 + `read (memory :> bytes128 (word_add ctxt_p (word l1_curr_len))) s5 = + cipher_stealing_inv 0x1 l1_curr_len (val tail_len) CC pt_in /\ + (forall i'. + i' < val tail_len - 0x1 + ==> read (memory :> bytes8 (word_add (word_add ctxt_p (word (l1_curr_len + 0x10 + 0x1))) (word i'))) s5 = + EL i' (SUB_LIST (0x1,val tail_len - 0x1) (int128_to_bytes CC))) /\ + ~(ival (word 0x1) < &0x0) /\ ival (word (0x1 + 0x1)) - &0x1 = ival (word 0x1)` *) + REPEAT CONJ_TAC THENL (* 4 subgoals *) + [ MATCH_MP_TAC (snd (EQ_IMP_RULE (SPECL [`(word_add ctxt_p (word l1_curr_len)):int64`; + `s5:armstate`; t1] BREAK_ONE_BLOCK_INTO_BYTES))) THEN + CONV_TAC(ONCE_DEPTH_CONV NORMALIZE_RELATIVE_ADDRESS_CONV) THEN + ASM_REWRITE_TAC[] THEN + + MP_TAC (SPECL [case; `l1_curr_len:num`; `tail_len:int64`; `CC:int128`; `pt_in:byte list`] + CIPHER_STEALING_BYTE_EQUAL) THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + STRIP_TAC THEN + + MAP_EVERY (fun i -> CONJ_TAC THENL + [CIPHER_STEALING_INV_SIMP_TAC (mk_numeral (num i)); ALL_TAC]) + (0--0xe) THEN + CIPHER_STEALING_INV_SIMP_TAC `0xf:num`; + + MP_TAC (SPECL [`ctxt_p:int64`; case; `val (tail_len:int64)`; + `l1_curr_len:num`; `(int128_to_bytes CC):byte list`; `s5:armstate`] + BYTE_LIST_AT_SPLIT_BACKWARDS_CARNONICAL) THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV THEN + CONV_TAC(ONCE_DEPTH_CONV NORMALIZE_RELATIVE_ADDRESS_CONV) THEN + ASM_SIMP_TAC[] THEN + ANTS_TAC THENL + [ IMP_REWRITE_TAC[WORD_ZX_ZX] THEN + REWRITE_TAC[DIMINDEX_8; DIMINDEX_32; DIMINDEX_64] THEN + MP_TAC (SPECL [case; `l1_curr_len:num`; `tail_len:int64`; `CC:int128`; `pt_in:byte list`] + CIPHER_STEALING_INV_SELECT) THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_SIMP_TAC[] ; ALL_TAC ] THEN + REWRITE_TAC[ADD_ASSOC; ARITH_RULE r1]; + + WORD_ARITH_TAC; + WORD_ARITH_TAC +];; + +let ENC_TAIL_SWAP_ASM_CASES_TAC case = + let c_tm = `case:num` in + let asm_case = subst [case, c_tm] `(i:num) = case` in + ASM_CASES_TAC asm_case THENL [ ENC_TAIL_SWAP_CASE_TAC case; ALL_TAC] THEN + MP_TAC (SPECL [case; `i:num`] LE_LT) THEN + ASM_SIMP_TAC[] THEN + DISCH_TAC THEN + MP_TAC (SPECL [case; `i:num`] LE_SUC_LT) THEN + ASM_SIMP_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_SIMP_TAC[] THEN + DISCH_TAC;; + + +(**********************************************************************) +(** Proofs **) + + +(* Proof: Cipher stealing *) +let CIPHER_STEALING_ENC_CORRECT = time prove( + `!ptxt_p ctxt_p len key1_p + pt_in iv tail_len len_full_blocks num_5blocks + k1_0 k1_1 k1_2 k1_3 k1_4 k1_5 k1_6 k1_7 k1_8 k1_9 k1_10 k1_11 k1_12 k1_13 k1_14 + pc. + PAIRWISE nonoverlapping + [(word pc, LENGTH aes256_xts_encrypt_mc); + (ptxt_p, val len); + (ctxt_p, val len); + (key1_p, 244)] /\ + val len >= 16 /\ val len <= 2 EXP 24 /\ + LENGTH pt_in = val len /\ + word_and len (word 0xfffffffffffffff0) = len_full_blocks /\ + word_and len (word 0xf) = tail_len /\ + word (val len_full_blocks DIV 0x50) = num_5blocks /\ + word_add tail_len len_full_blocks = len /\ + [k1_0; k1_1; k1_2; k1_3; k1_4; k1_5; k1_6; k1_7; k1_8; k1_9; k1_10; + k1_11; k1_12; k1_13; k1_14] = key1_lst + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes256_xts_encrypt_mc /\ + read PC s = word (pc + 0x9e0) /\ + read X0 s = word_add ptxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + read X1 s = word_add ctxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + read X3 s = key1_p /\ + read X21 s = tail_len /\ + read Q6 s = calculate_tweak (acc_blocks num_5blocks len_full_blocks true) iv key2_lst /\ + read X19 s = word 0x87 /\ + read Q16 s = k1_0 /\ read Q17 s = k1_1 /\ read Q12 s = k1_2 /\ read Q13 s = k1_3 /\ + read Q14 s = k1_4 /\ read Q15 s = k1_5 /\ read Q4 s = k1_6 /\ read Q5 s = k1_7 /\ + read Q18 s = k1_8 /\ read Q19 s = k1_9 /\ read Q20 s = k1_10 /\ read Q21 s = k1_11 /\ + read Q22 s = k1_12 /\ read Q23 s = k1_13 /\ read Q7 s = k1_14 /\ + byte_list_at pt_in ptxt_p len s /\ + byte_list_at (aes256_xts_encrypt pt_in (acc_len num_5blocks len_full_blocks) iv key1_lst key2_lst) + ctxt_p (word (acc_len num_5blocks len_full_blocks)) s) + (\s. + read PC s = word (pc + 0xa8c) /\ //LENGTH aes256_xts_encrypt_mc - 8*4 = 0xaac - 0x8 * 0x4 + byte_list_at (aes256_xts_encrypt pt_in (val len) iv key1_lst key2_lst) ctxt_p len s ) + ( MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22] ,, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15] ,, + MAYCHANGE [memory :> bytes (ctxt_p,val len)]) + `, + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[byte_list_at; PAIRWISE; ALL; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + (* Prove the bounds on len_full_blocks, num_5blocks and len and their relationships *) + SUBGOAL_THEN `~(val (len_full_blocks:int64) < 0x10)` ASSUME_TAC THENL + [ SUBGOAL_THEN `~(val (len:int64) < 0x10)` MP_TAC THENL + [ASM_ARITH_TAC; ALL_TAC] THEN + UNDISCH_TAC `word_and len (word 0xfffffffffffffff0) = (len_full_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `len_full_blocks:int64`] NUM_BLOCKS_LO_BOUND_1BLOCK_THM) THEN + SIMP_TAC[]; ALL_TAC] THEN + + SUBGOAL_THEN `val (len_full_blocks:int64) <= 0x2 EXP 24` ASSUME_TAC THENL + [ UNDISCH_TAC `val (len:int64) <= 0x2 EXP 24` THEN + UNDISCH_TAC `word_and len (word 0xfffffffffffffff0) = (len_full_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `len_full_blocks:int64`] NUM_BLOCKS_HI_BOUND_THM) THEN + SIMP_TAC[]; ALL_TAC] THEN + + SUBGOAL_THEN `val (tail_len:int64) < 16` ASSUME_TAC THENL + [ EXPAND_TAC "tail_len" THEN + REWRITE_TAC[ARITH_RULE `0xf = 2 EXP 4 - 1`] THEN + REWRITE_TAC[VAL_WORD_AND_MASK_WORD] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SIMP_TAC[MOD_LT_EQ] THEN + CONV_TAC NUM_REDUCE_CONV + ; ALL_TAC] THEN + + (* relationship between variables *) + SUBGOAL_THEN `val (len_full_blocks:int64) <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "len_full_blocks" THEN SIMP_TAC[NUM_BLOCKS_LT_LEN_THM]; ALL_TAC] THEN + + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks" THEN + REWRITE_TAC [VAL_WORD; DIMINDEX_64] THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + + (* Prove more properties about len_full_blocks and num_5blocks *) + SUBGOAL_THEN `val (len_full_blocks:int64) DIV 0x50 = val (num_5blocks:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks" THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `0x10 divides val (len_full_blocks:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "len_full_blocks" THEN + REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT; DIVIDES_RMUL; DIVIDES_REFL] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + + (* If no tail, execute to the end *) + ASM_CASES_TAC `val (tail_len:int64) = 0` THENL + [ + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (1--2) THEN (* tst x21, #0xf; b.eq .Lxts_enc_abort *) + (* Discharge if condition *) + SUBGOAL_THEN `val (word_and (tail_len:int64) (word 0xf)) = 0x0` MP_TAC THENL + [ UNDISCH_TAC `val (tail_len:int64) = 0x0` THEN BITBLAST_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + + SUBGOAL_THEN `val (word (acc_len (num_5blocks:int64) (len_full_blocks:int64)):int64) = + acc_len num_5blocks len_full_blocks` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + MP_TAC (SPECL [`num_5blocks:int64`; `len_full_blocks:int64`; `2 EXP 64`] + BOUND_OF_ACC_LEN) THEN + ANTS_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[]; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + (* Prove that acc_len is equal to total len because there is no tail *) + SUBGOAL_THEN `val (len:int64) = + acc_len (num_5blocks:int64) (len_full_blocks:int64)` SUBST1_TAC THENL + [ SUBGOAL_THEN `len = (len_full_blocks:int64)` SUBST1_TAC THENL + [ EXPAND_TAC "len" THEN + SUBGOAL_THEN `tail_len:int64 = word 0` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM VAL_EQ_0] THEN ASM_REWRITE_TAC[]; ALL_TAC] THEN + REWRITE_TAC[ASSUME `tail_len:int64 = word 0`; WORD_ADD_0] + ; ALL_TAC] THEN + REWRITE_TAC[acc_len] THEN + REPEAT_N 4 (COND_CASES_TAC THENL[ASM_ARITH_TAC; ALL_TAC]) THEN + + CONV_TAC SYM_CONV THEN + REWRITE_TAC[ARITH_RULE `!a. 0x50 * a = a * 0x50`] THEN + MATCH_MP_TAC (SPECL [`val (len_full_blocks:int64)`; `val (num_5blocks:int64)`] DIVISION_BY_80_LEMMA) THEN + REPEAT CONJ_TAC THENL + [ + ASM_SIMP_TAC[]; + ASM_SIMP_TAC[]; + UNDISCH_TAC `~(val (num_5blocks:int64) * 0x50 + 0x10 = val (len_full_blocks:int64))` THEN ARITH_TAC; + UNDISCH_TAC `~(val (num_5blocks:int64) * 0x50 + 0x20 = val (len_full_blocks:int64))` THEN ARITH_TAC; + UNDISCH_TAC `~(val (num_5blocks:int64) * 0x50 + 0x30 = val (len_full_blocks:int64))` THEN ARITH_TAC; + UNDISCH_TAC `~(val (num_5blocks:int64) * 0x50 + 0x40 = val (len_full_blocks:int64))` THEN ARITH_TAC ] + ; ALL_TAC] THEN + ASM_SIMP_TAC[] + ; ALL_TAC + ] THEN + + (* The cipher stealing branch; tail != 0 *) + (* The byte-swap needs another invariant proof. *) + (* In the following "l1" means "less 1 block". This is to differentiate it from the decrypt case + where at the entry of cipher-stealing, we have one full block left to process and a tail, while + in encrypt that full block was already processed and that's why we need to go back "less 1" + to match the decrypt invariant. *) + ABBREV_TAC `l1_curr_len = ((acc_len (num_5blocks:int64) (len_full_blocks:int64)) - 0x10):num` THEN + ABBREV_TAC `l1_curr_blocks = ((acc_blocks (num_5blocks:int64) (len_full_blocks:int64) T) - 1):num` THEN + + SUBGOAL_THEN `l1_curr_len + 0x10 <= val (len:int64)` ASSUME_TAC THENL (* similar to decrypt *) + [ EXPAND_TAC "l1_curr_len" THEN + MP_TAC (SPECL [`num_5blocks:int64`; `len_full_blocks:int64`] VALUE_OF_ACC_LEN) THEN + REPEAT_N 3 (ANTS_TAC THENL [ASM_ARITH_TAC ORELSE ASM_SIMP_TAC[]; ALL_TAC]) THEN + ASM_ARITH_TAC; ALL_TAC ] THEN + + SUBGOAL_THEN `val ((word l1_curr_len):int64) = l1_curr_len` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `val ((word (l1_curr_len + 0x10)):int64) = l1_curr_len + 0x10` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + ASM_ARITH_TAC; ALL_TAC] THEN +(* + SUBGOAL_THEN `l1_curr_len >= 0` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM (ASSUME `(acc_len num_5blocks len_full_blocks) - 0x10 = l1_curr_len`)] THEN + MP_TAC (SPECL [`num_5blocks:int64`; `len_full_blocks:int64`] VALUE_OF_ACC_LEN) THEN + REPEAT_N 3 (ANTS_TAC THENL [ASM_ARITH_TAC ORELSE ASM_SIMP_TAC[]; ALL_TAC]) THEN + ASM_ARITH_TAC ; ALL_TAC ] THEN +*) + SUBGOAL_THEN `16 * l1_curr_blocks = l1_curr_len` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM (ASSUME `(acc_len num_5blocks len_full_blocks) - 0x10 = l1_curr_len`)] THEN (* put in tips doc*) + (* or UNDISCH_THEN `acc_len (num_5blocks:int64) (len_full_blocks:int64) = curr_len` + (fun th -> REWRITE_TAC[GSYM th]) THEN *) + EXPAND_TAC "l1_curr_blocks" THEN + REWRITE_TAC[acc_len; acc_blocks] THEN + REPEAT_N 4 (COND_CASES_TAC THENL [SIMP_TAC[] THEN ARITH_TAC; ALL_TAC] THEN SIMP_TAC[]) THEN + ARITH_TAC; ALL_TAC ] THEN + + ABBREV_TAC `CC = aes256_xts_encrypt_round + (bytes_to_int128 (SUB_LIST (l1_curr_len,0x10) (pt_in:byte list))) + (calculate_tweak (l1_curr_blocks) (iv:int128) (key2_lst:int128 list)) + (key1_lst:int128 list)` THEN + + (* For address matching when symbolic simulation *) + SUBGOAL_THEN `16 <= acc_len num_5blocks len_full_blocks` ASSUME_TAC THENL + [ MP_TAC (SPECL [`num_5blocks:int64`; `len_full_blocks:int64`] VALUE_OF_ACC_LEN) THEN + REPEAT_N 3 (ANTS_TAC THENL [ASM_ARITH_TAC ORELSE ASM_SIMP_TAC[]; ALL_TAC]) THEN + ASM_ARITH_TAC; ALL_TAC ] THEN + + SUBGOAL_THEN ` acc_len num_5blocks len_full_blocks = l1_curr_len + 0x10` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM (ASSUME `(acc_len num_5blocks len_full_blocks) - 0x10 = l1_curr_len`)] THEN + ASM_ARITH_TAC; ALL_TAC ] THEN + + SUBGOAL_THEN `1 <= acc_blocks (num_5blocks:int64) (len_full_blocks:int64) true` ASSUME_TAC THENL + [ REWRITE_TAC[acc_blocks] THEN + REPEAT_N 4 (COND_CASES_TAC THENL [SIMP_TAC[] THEN ARITH_TAC; ALL_TAC] THEN SIMP_TAC[]) THEN + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 = val (len_full_blocks:int64)` ASSUME_TAC THENL + [ MATCH_MP_TAC (SPECL [`val (len_full_blocks:int64)`; `val (num_5blocks:int64)`] DIVISION_BY_80_LEMMA) THEN + REPEAT CONJ_TAC THENL + [ + ASM_SIMP_TAC[]; + ASM_SIMP_TAC[]; + UNDISCH_TAC `~(val (num_5blocks:int64) * 0x50 + 0x10 = val (len_full_blocks:int64))` THEN ARITH_TAC; + UNDISCH_TAC `~(val (num_5blocks:int64) * 0x50 + 0x20 = val (len_full_blocks:int64))` THEN ARITH_TAC; + UNDISCH_TAC `~(val (num_5blocks:int64) * 0x50 + 0x30 = val (len_full_blocks:int64))` THEN ARITH_TAC; + UNDISCH_TAC `~(val (num_5blocks:int64) * 0x50 + 0x40 = val (len_full_blocks:int64))` THEN ARITH_TAC ] + ; ALL_TAC] THEN + SUBGOAL_THEN `0x10 <= val (num_5blocks:int64) * 0x50` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC ] THEN + ASM_ARITH_TAC; ALL_TAC ] THEN + + SUBGOAL_THEN `l1_curr_len + 0x10 + val (tail_len:int64) = val (len:int64)` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM (ASSUME `acc_len num_5blocks len_full_blocks - 0x10 = l1_curr_len`)] THEN + + MP_TAC (SPECL [`num_5blocks:int64`; `len_full_blocks:int64`] VALUE_OF_ACC_LEN) THEN + REPEAT_N 3 (ANTS_TAC THENL [ASM_ARITH_TAC ORELSE ASM_SIMP_TAC[]; ALL_TAC]) THEN + SIMP_TAC[] THEN DISCH_TAC THEN + + ASM_SIMP_TAC[ADD_ASSOC; ARITH_RULE `~(val len_full_blocks < 0x10) ==> val len_full_blocks - 0x10 + 0x10 + = val len_full_blocks`] THEN (* add to tips doc, see My questions doc *) + REWRITE_TAC[GSYM (ASSUME `word_add (tail_len:int64) len_full_blocks = len`)] THEN + ASM_SIMP_TAC[VAL_WORD_ADD_CASES; DIMINDEX_64; + ARITH_RULE `val len_full_blocks <= 0x1000000 /\ val tail_len < 0x10 ==> + val tail_len + val len_full_blocks < 0x2 EXP 0x40`] THEN + ASM_ARITH_TAC; ALL_TAC ] THEN + + SUBGOAL_THEN `word_add (ptxt_p:int64) (word (acc_len num_5blocks len_full_blocks)) = + word_add ptxt_p (word (l1_curr_len + 0x10))` ASSUME_TAC THENL + [ REPEAT AP_TERM_TAC THEN + ASM_ARITH_TAC ; ALL_TAC ] THEN + + SUBGOAL_THEN `word_sub (word_add ctxt_p (word (acc_len num_5blocks len_full_blocks))) (word 0x10):int64 = + word_add ctxt_p (word l1_curr_len)` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM (ASSUME `(acc_len num_5blocks len_full_blocks) - 0x10 = l1_curr_len`)] THEN + ASM_SIMP_TAC[WORD_SUB] THEN + CONV_TAC WORD_RULE; ALL_TAC] THEN + + SUBGOAL_THEN `word_sub (word_add ctxt_p (word (l1_curr_len + 0x10))) (word 0x10):int64 = + word_add ctxt_p (word l1_curr_len)` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM (ASSUME `acc_len num_5blocks len_full_blocks = l1_curr_len + 0x10`)] THEN + ASM_SIMP_TAC[] ; ALL_TAC] THEN + + (* Invariant proof for .composite_enc_loop *) + (* Invariant: + X0 points to tail of pt_in; Pm in specs + X1 points to starting of last full block of ct_out; CC + X13 points to tail of ct_out; will become Cm at the end of the loop + X20 = X0, points to tail of pt_in; Pm + X21 holds decreasing tail_len + Q6 holds last tweak + Q16 ... Q7 holds the key schedule for encryption + + Memory: ptxt_p points to the input + Memory: Up to the last block, the output pointed to by ctxt_p matches the specification + Memory: X13 points to tail location in the output, to which Cm is copyied byte by byte from where X1 points + Memory: X1 (= X13 - 0x10) points to CC = [Cm | CP] will become PP = [Pm | CP] by copying Pm one byte at a time to override Cm + Loop: bytes are copied in decreasing addresses, i.e. X21 is an offset to both X1 and X13 + decreasing from "tail" down to 0. The iterator i is the value of X21. + Memory: For the last block, CC, pointed to by X1, for each byte + [0,i) -- previous decryption result, Cm + [i,tail_len) -- equal corresponding pt_in tail bytes, Pm + [tail_len,16] -- previous decryption result, CP + Memory: For the tail, Cm, pointed to by X13, for each byte + [i,tail_len) -- copied over from Pm block + + +----------------+ +----------------+ + | P_m-1 | | P_m | CP | + +----------------+ +----------------+ + | ^ | + | <-- | | + l1_curr_len | Enc curr_len x21 | Enc + | | | | | + v v v +---------+ v + +----------------+ | +----------------+ + | C_m | CP | | | C_m-1 | + +----------------+ | +--------+-------+ + ^ ^ | | + | <-- | | | + x1 x21 (decreasing offset) | | + || | | + +------------------------+ | + | (2) | + +------------------------------+ | + (1) | | + +----------------+ +---v--+ | + | C_m-1 | | C_m | | + +----------------+ +------+ | + ^ ^ ^ | + | | | | + x1 | (3) x13 | + +----------------------------------+ + + 1, 2 and 3 are order of moving bytes because they're written to the same place. + - 1 and 2 are in a loop iterating over the bytes at offset x21 + - 3 is after the loop and last block encryption (decryption) writing the block at the output at x1 + + *) + + ENSURES_WHILE_PADOWN_TAC + `val (tail_len:int64)` (* counter begin number *) + `0` (* counter end number *) + `pc + 0x9f4` (* loop body start PC *) + `pc + 0xa08` (* loop backedge branch PC *) + `\i s. + // loop invariant at the end of the loop iteration + ( read X0 s = word_add ptxt_p (word (l1_curr_len + 0x10)) /\ + read X1 s = word_add ctxt_p (word l1_curr_len) /\ + read X13 s = word_add ctxt_p (word (l1_curr_len + 0x10)) /\ + read X20 s = word_add ptxt_p (word (l1_curr_len + 0x10)) /\ + read X21 s = (word i):int64 /\ + read Q6 s = calculate_tweak (acc_blocks num_5blocks len_full_blocks true) iv key2_lst /\ + read Q16 s = k1_0 /\ read Q17 s = k1_1 /\ read Q12 s = k1_2 /\ read Q13 s = k1_3 /\ + read Q14 s = k1_4 /\ read Q15 s = k1_5 /\ read Q4 s = k1_6 /\ read Q5 s = k1_7 /\ + read Q18 s = k1_8 /\ read Q19 s = k1_9 /\ read Q20 s = k1_10 /\ read Q21 s = k1_11 /\ + read Q22 s = k1_12 /\ read Q23 s = k1_13 /\ read Q7 s = k1_14 /\ + byte_list_at pt_in ptxt_p len s /\ + // Encryption is correct up until l1_curr_len + byte_list_at (aes256_xts_encrypt pt_in l1_curr_len iv key1_lst key2_lst) + ctxt_p (word l1_curr_len) s /\ + // Contents of CC at each i + read (memory :> bytes128 (word_add ctxt_p (word l1_curr_len))) s = + cipher_stealing_inv i l1_curr_len (val (tail_len:int64)) CC pt_in /\ + + // bytes of Cm at offset i to (tail_len-i) in CC + // are stored at their final location in ciphertext in the tail part + // they're copied from CC before they're overwritten by bytes from Pm + byte_list_at (SUB_LIST (i, val tail_len - i) (int128_to_bytes CC)) + (word_add ctxt_p (word (l1_curr_len + 0x10 + i))) + (word ((val tail_len) - i)) s) /\ + // loop backedge condition + (read ZF s <=> i = 0) /\ + (read NF s <=> ival ((word i):int64) < &0) /\ + (read VF s <=> ~(ival ((word (i + 1)):int64) - &1 = ival ((word i):int64)))` THEN + ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL + [ + (* Subgoal1: 0 < val tail_len *) + ASM_ARITH_TAC; (* 5 goals *) + + (* Subgoal2: invariant holds before entering loop *) + REWRITE_TAC[byte_list_at] THEN + UNDISCH_THEN `val ((word l1_curr_len):int64) = l1_curr_len` + (fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN REWRITE_TAC[th] + THEN ASSUME_TAC th) THEN (* put in tips doc: keep the assumption *) + UNDISCH_THEN `val ((word (l1_curr_len + 0x10)):int64) = l1_curr_len + 0x10` + (fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN REWRITE_TAC[th] + THEN ASSUME_TAC th) THEN + + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (1--2) THEN + (* Discharge if condition *) + SUBGOAL_THEN `~(val (word_and (tail_len:int64) (word 0xf)) = 0x0)` MP_TAC THENL + [ UNDISCH_TAC `~(val (tail_len:int64) = 0x0)` THEN + UNDISCH_TAC `val (tail_len:int64) < 16` THEN + MP_TAC (SPEC `tail_len:int64` WORD_AND_MASK16_EQ_0) THEN + SIMP_TAC[]; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (3--5) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + (* + `tail_len = word (val tail_len) /\ + (forall i. + i < l1_curr_len + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s5 = + EL i (aes256_xts_encrypt pt_in l1_curr_len iv key1_lst key2_lst)) /\ + read (memory :> bytes128 (word_add ctxt_p (word l1_curr_len))) s5 = + cipher_stealing_inv (val tail_len) l1_curr_len (val tail_len) CC pt_in /\ + (forall i. + i < val (word 0x0) + ==> read (memory :> bytes8 (word_add (word_add ctxt_p (word (l1_curr_len + 0x10 + val tail_len))) + (word i))) s5 = + EL i (SUB_LIST (val tail_len,0x0) (int128_to_bytes CC)))`. *) + REPEAT CONJ_TAC THENL (* 4 subgoals (7 total) *) + [ + (* `tail_len = word (val tail_len)` *) + REWRITE_TAC[WORD_VAL]; + + (*`forall i. + i < l1_curr_len + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s5 = + EL i (aes256_xts_encrypt pt_in l1_curr_len iv key1_lst key2_lst)`. *) + UNDISCH_TAC + `forall i. + i < l1_curr_len + 0x10 + ==> read (memory :> bytes8 (word_add (ctxt_p:int64) (word i))) s5 = + EL i (aes256_xts_encrypt pt_in (l1_curr_len + 0x10) iv key1_lst key2_lst)` THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`)] THEN + REWRITE_TAC[ARITH_RULE `0x10 * l1_curr_blocks + 0x10 = 0x10 * (l1_curr_blocks + 0x1)`] THEN + MP_TAC (SPECL [`0x10 * (l1_curr_blocks + 0x1):num`; `ctxt_p:int64`; + `(aes256_xts_encrypt pt_in (0x10 * (l1_curr_blocks + 0x1)) iv key1_lst key2_lst):byte list`; + `s5:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL [ + REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + MP_TAC (SPECL [`0x10 * l1_curr_blocks:num`; `ctxt_p:int64`; + `(aes256_xts_encrypt pt_in (0x10 * l1_curr_blocks) iv key1_lst key2_lst):byte list`; + `s5:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL [ + REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + MP_TAC(SPECL [`l1_curr_blocks:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + MP_TAC(SPECL [`l1_curr_blocks + 0x1:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + IMP_REWRITE_TAC[ARITH_RULE `0x10 * (l1_curr_blocks + 0x1) = 0x10 * l1_curr_blocks + 0x10`] THEN + DISCH_TAC THEN DISCH_TAC THEN + (* `read (memory :> bytes (ctxt_p,0x10 * (l1_curr_blocks + 0x1))) s5 = + num_of_bytelist (aes256_xts_encrypt pt_in (0x10 * (l1_curr_blocks + 0x1)) iv key1_lst key2_lst) + ==> read (memory :> bytes (ctxt_p,l1_curr_len)) s5 = + num_of_bytelist (aes256_xts_encrypt pt_in l1_curr_len iv key1_lst key2_lst)` *) + + DISCH_TAC THEN + IMP_REWRITE_TAC[SPECL [`ctxt_p:int64`; `l1_curr_len:num`; + `(aes256_xts_encrypt pt_in (l1_curr_len + 0x10) iv key1_lst key2_lst):byte list`; + `s5:armstate`] READ_BYTES_AND_BYTE128_MERGE] THEN + EXISTS_TAC `iv:int128` THEN EXISTS_TAC `key1_lst:int128 list` THEN + EXISTS_TAC `key2_lst:int128 list` THEN EXISTS_TAC `pt_in:byte list` THEN + (* `num_of_bytelist (SUB_LIST (0x0,l1_curr_len) + (aes256_xts_encrypt pt_in (l1_curr_len + 0x10) iv key1_lst key2_lst)) = + num_of_bytelist (aes256_xts_encrypt pt_in l1_curr_len iv key1_lst key2_lst) /\ + l1_curr_len + 0x10 <= + LENGTH (aes256_xts_encrypt pt_in (l1_curr_len + 0x10) iv key1_lst key2_lst) /\ + num_of_bytelist (aes256_xts_encrypt pt_in (l1_curr_len + 0x10) iv key1_lst key2_lst) = + num_of_bytelist (SUB_LIST (0x0,l1_curr_len + 0x10) + (aes256_xts_encrypt pt_in (l1_curr_len + 0x10) iv key1_lst key2_lst))` *) + REPEAT CONJ_TAC THENL [ (* 3 subgoals (8 total) *) + AP_TERM_TAC THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`)] THEN + IMP_REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS]; + + ASM_ARITH_TAC; + + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] + ]; + + (* `read (memory :> bytes128 (word_sub (word_add ctxt_p (word l1_curr_len)) (word 0x10))) s5 + = cipher_stealing_inv (val tail_len) l1_curr_len (val tail_len) CC pt_in` *) + REWRITE_TAC[cipher_stealing_inv; SUB_REFL] THEN + SUBGOAL_THEN `SUB_LIST (val (tail_len:int64),0x0) (SUB_LIST (l1_curr_len + 0x10,val tail_len) (pt_in:byte list)) = []` SUBST1_TAC THENL + [ REWRITE_TAC[SUB_LIST_CLAUSES]; ALL_TAC] THEN + REWRITE_TAC[CONJUNCT1 APPEND] THEN + SUBGOAL_THEN `APPEND (SUB_LIST (0x0,val (tail_len:int64)) (int128_to_bytes CC)) + (SUB_LIST (val tail_len,0x10 - val tail_len) (int128_to_bytes CC)) = + (int128_to_bytes CC)` SUBST1_TAC THENL + [ MP_TAC (ISPECL [`int128_to_bytes CC`; `val (tail_len:int64)`; `16 - val (tail_len:int64)`; `0`] (GSYM SUB_LIST_SPLIT)) THEN + IMP_REWRITE_TAC[ADD_CLAUSES; ARITH_RULE `!x. x < 16 ==> x + 16 - x = 16`] THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES; LENGTH_OF_INT128_TO_BYTES] ; ALL_TAC] THEN + REWRITE_TAC[BYTES_TO_INT128_OF_INT128_TO_BYTES] THEN + + (* `read (memory :> bytes128 (word_sub (word_add ctxt_p (word curr_len)) (word 0x10))) s5 = CC` *) + (* Apply READ_LAST_LEMMA with proper arguments *) + MP_TAC (SPECL [`ctxt_p:int64`; `l1_curr_len:num`; `word (l1_curr_len+0x10):int64`; + `aes256_xts_encrypt pt_in (l1_curr_len+0x10) iv key1_lst key2_lst:byte list`; `s5:armstate`] READ_LAST_LEMMA) THEN + UNDISCH_THEN `val ((word (l1_curr_len + 0x10)):int64) = l1_curr_len + 0x10` + (fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN REWRITE_TAC[th] THEN ASSUME_TAC th) THEN + ASM_SIMP_TAC[] THEN + (* `(l1_curr_len + 0x10 <= l1_curr_len + 0x10 /\ + LENGTH (aes256_xts_encrypt pt_in (l1_curr_len + 0x10) iv key1_lst key2_lst) = + l1_curr_len + 0x10 + ==> read (memory :> bytes128 (word_add ctxt_p (word l1_curr_len))) s5 = + bytes_to_int128 (SUB_LIST (l1_curr_len,0x10) + (aes256_xts_encrypt pt_in (l1_curr_len + 0x10) iv key1_lst key2_lst))) + ==> read (memory :> bytes128 (word_add ctxt_p (word l1_curr_len))) s5 = CC` *) + ANTS_TAC THENL + [ CONJ_TAC THENL + [ ARITH_TAC; + + (* `LENGTH (aes256_xts_encrypt pt_in l1_curr_len iv key1_lst key2_lst) = l1_curr_len`*) + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`); + ARITH_RULE `0x10 * l1_curr_blocks + 0x10 = 0x10 * (l1_curr_blocks + 0x1)`; + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] ] + ; ALL_TAC ] THEN + + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + (* `bytes_to_int128 (SUB_LIST (l1_curr_len,0x10) + (aes256_xts_encrypt pt_in (l1_curr_len + 0x10) iv key1_lst key2_lst)) = CC` *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(l1_curr_len + 0x10 < 0x10)`] THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`)] THEN + SIMP_TAC[ARITH_RULE `0x10 * l1_curr_blocks + 0x10 = 0x10 * (l1_curr_blocks + 0x1)`; + MOD_MULT] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + IMP_REWRITE_TAC[SUB_0; DIV_MULT] THEN + + COND_CASES_TAC THENL + [ (* `l1_curr_blocks + 0x1 < 0x2` *) + MP_TAC (SPECL [`0x0:num`; `0x0:num`; `pt_in:byte list`; `iv:int128`; + `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + + EXPAND_TAC "CC" THEN + SUBGOAL_THEN `l1_curr_len = 0` SUBST1_TAC THENL + [ UNDISCH_TAC `l1_curr_blocks + 0x1 < 2` THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`)] THEN + ARITH_TAC ; ALL_TAC] THEN + IMP_REWRITE_TAC[(ISPECL [`(aes256_xts_encrypt_tail 0x0 0x0 pt_in iv key1_lst key2_lst):byte list`; + `0x10:num`] SUB_LIST_LENGTH_IMPLIES)] THEN + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + SUBGOAL_THEN `l1_curr_blocks = 0` SUBST1_TAC THENL + [ UNDISCH_TAC `l1_curr_blocks + 0x1 < 2` THEN ARITH_TAC ; ALL_TAC] THEN + CONV_TAC NUM_REDUCE_CONV; + + (* ~(l1_curr_len DIV 0x10 < 0x2) *) + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `l1_curr_blocks >= 1` ASSUME_TAC THENL + [ ASM_ARITH_TAC ; ALL_TAC ] THEN + IMP_REWRITE_TAC[ARITH_RULE `l1_curr_blocks >= 0x1 ==> (l1_curr_blocks + 0x1) - 0x2 = l1_curr_blocks - 0x1`; + ARITH_RULE `l1_curr_blocks >= 0x1 ==> (l1_curr_blocks + 0x1) - 0x1 = l1_curr_blocks`] THEN + + MP_TAC (SPECL [`0`;`(l1_curr_blocks - 1):num`; `pt_in:byte list`; `iv:int128`; + `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + ASM_SIMP_TAC[ARITH_RULE `l1_curr_blocks >= 0x1 ==> ~(l1_curr_blocks - 0x1 < 0x0)`] THEN + IMP_REWRITE_TAC[SUB_0; ARITH_RULE `l1_curr_blocks >= 0x1 ==> l1_curr_blocks - 1 + 1 = l1_curr_blocks`] THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`)] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN + DISCH_TAC THEN + (* `bytes_to_int128 (SUB_LIST (0x0,0x10) (aes256_xts_encrypt_tail l1_curr_blocks 0x0 pt_in iv key1_lst key2_lst)) + = CC /\ l1_curr_blocks * 0x10 = l1_curr_len`*) + MP_TAC (SPECL [`l1_curr_blocks:num`; `0x0:num`; `pt_in:byte list`; `iv:int128`; + `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + ASM_SIMP_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + EXPAND_TAC "CC" THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`); CONJUNCT1 MULT_AC] + ]; + (* `forall i. + i < val (word 0x0) + ==> read (memory :> bytes8 (word_add (word_add ctxt_p (word (l1_curr_len + val tail_len))) + (word i))) s5 + = EL i (SUB_LIST (val tail_len,0x0) (int128_to_bytes CC))`*) + REWRITE_TAC[VAL_WORD_0] THEN ARITH_TAC + ]; + + (* Subgoal 3: inductive step *) + REPEAT STRIP_TAC THEN + + (* For non-overlapping and MAYCHANGE address reasoning *) + SUBGOAL_THEN `(l1_curr_len + 0x10) + i < val (len:int64)` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM (ASSUME `acc_len num_5blocks len_full_blocks - 0x10 = l1_curr_len`)] THEN + MP_TAC (SPECL [`num_5blocks:int64`; `len_full_blocks:int64`] VALUE_OF_ACC_LEN) THEN + REPEAT_N 3 (ANTS_TAC THENL [ASM_ARITH_TAC ORELSE ASM_SIMP_TAC[]; ALL_TAC]) THEN + SIMP_TAC[] THEN DISCH_TAC THEN + + UNDISCH_TAC `word_add (tail_len:int64) (len_full_blocks:int64) = len` THEN + UNDISCH_TAC `i < val (tail_len:int64)` THEN + + ONCE_REWRITE_TAC[GSYM VAL_EQ] THEN + REWRITE_TAC[VAL_WORD_ADD;DIMINDEX_64] THEN + IMP_REWRITE_TAC[MOD_LT] THEN + ASM_ARITH_TAC + ; ALL_TAC ] THEN + + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes8 (word_add ctxt_p (word (l1_curr_len + 0x10 + i)))],, + MAYCHANGE [memory :> bytes8 (word_add ctxt_p (word (l1_curr_len + i)))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + UNDISCH_THEN `val ((word l1_curr_len):int64) = l1_curr_len` + (fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN REWRITE_TAC[th]) THEN + ENSURES_INIT_TAC "s0" THEN + + SUBGOAL_THEN `val ((word (val (tail_len:int64) - i)):int64) = val tail_len - i` SUBST_ALL_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val ((word (val (tail_len:int64) - (i + 0x1))):int64) = val tail_len - (i + 1)` SUBST_ALL_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `word_sub ((word (i + 0x1)):int64) (word 0x1) = word i` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM VAL_EQ; VAL_WORD_SUB; DIMINDEX_64] THEN + MP_TAC (SPECL [`val ((word (i + 0x1)):int64)`; `0x2 EXP 0x40`; `val ((word 0x1):int64)`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN ASM_ARITH_TAC + ; ALL_TAC] THEN + ANTS_TAC THENL [ WORD_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; `val ((word (i + 0x1)):int64) - val ((word 0x1):int64)`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + SIMP_TAC[ARITH_RULE `!x. 1 * x = x`] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[MOD_LT] THEN + CONJ_TAC THENL + [ SUBGOAL_THEN `i + 1 < 2 EXP 64` MP_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + ARITH_TAC; + UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + WORD_ARITH_TAC] + ; ALL_TAC ] THEN + + (* The symbolic simulation does not capture the LDR/STR at a byte level with i as the iterator, because it doesn't + know which i. So the following steps are to break the cases for values of i *) + (* Read a byte from Cm (at location l1_curr_len + i into w15 *) + MP_TAC (SPECL [`(word_add ctxt_p (word l1_curr_len)):int64`; `word i:int64`; `s0:armstate`; + `(cipher_stealing_inv (i + 0x1) l1_curr_len (val (tail_len:int64)) CC pt_in):int128`] + SELECT_ONE_BYTE_FROM_BLOCK) THEN + + SUBGOAL_THEN `val ((word i):int64) < 0x10` ASSUME_TAC THENL + [ UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + WORD_ARITH_TAC; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + REPEAT STRIP_TAC THEN + (* Added assumption + 69 [`read (memory :> bytes8 (word_add (word_add ctxt_p (word l1_curr_len)) (word i))) s0 = + EL (val (word i)) (int128_to_bytes (cipher_stealing_inv (i + 0x1) l1_curr_len (val tail_len) CC pt_in))` *) + + (* Read a byte from Pm at location l1_curr_len + 16 + i into w14 *) + MP_TAC (SPECL [`ptxt_p:int64`; `len:int64`; `(word_add (word (l1_curr_len + 0x10)) (word i)):int64`; + `pt_in:byte list`; `s0:armstate`] SELECT_ONE_BYTE_FROM_FORALL) THEN + + SUBGOAL_THEN `val (word_add ((word (l1_curr_len+0x10)):int64) (word i)) < val (len:int64)` ASSUME_TAC THENL + [ REWRITE_TAC[WORD_RULE `!a b. word_add ((word a):int64) (word b) = word (a + b)`] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + STRIP_TAC THEN + (* Added assumption + 71 [`read (memory :> bytes8 (word_add ptxt_p (word_add (word (l1_curr_len + 0x10)) (word i)))) s0 = + EL (val (word_add (word (l1_curr_len + 0x10)) (word i))) pt_in`] *) + + (* Break the assumption `read (memory :> bytes128 (word_add ctxt_p (word l1_curr_len))) s0`` + into bytes using BREAK_ONE_BLOCK_INTO_BYTES *) + MP_TAC (SPECL [`(word_add ctxt_p (word l1_curr_len)):int64`; `s0:armstate`; + `(cipher_stealing_inv (i + 0x1) l1_curr_len (val (tail_len:int64)) CC pt_in):int128`] + BREAK_ONE_BLOCK_INTO_BYTES) THEN + ASM_SIMP_TAC[] THEN REPEAT STRIP_TAC THEN + + (* For address matching when symbolic simulation *) + + (* From John, changed all addresses to canonical form where the pointer is the first operand of word_add *) + CHANGED_TAC(RULE_ASSUM_TAC(CONV_RULE(ONCE_DEPTH_CONV NORMALIZE_RELATIVE_ADDRESS_CONV))) THEN + + SUBGOAL_THEN `word_add (ptxt_p:int64) (word_add (word (l1_curr_len+0x10)) (word i)) = + word_add ptxt_p (word ((l1_curr_len + 16) + i))` ASSUME_TAC THENL + [ REWRITE_TAC[WORD_RULE `!a b. word_add ((word a):int64) (word b) = word (a + b)`; ADD_ASSOC] + ; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN ASSUME_TAC th) THEN + + SUBGOAL_THEN `val ((word i):int64) = i` MP_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + ASM_ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN(RULE_ASSUM_TAC o REWRITE_RULE o CONJUNCTS) THEN + + (* case analysis based on i = 0 ... 14, because symbolic execution + needs to know which byte is being overwritten in pt_ptr to properly update the state. *) + (* Case 0 needed its own tactic *) + ASM_CASES_TAC `i:num = 0` THENL + [ ENC_TAIL_SWAP_CASE_0_TAC; ALL_TAC ] THEN + + MP_TAC (SPECL [`0`; `i:num`] LE_LT) THEN + ASM_SIMP_TAC[] THEN + DISCH_TAC THEN + MP_TAC (SPECL [`0`; `i:num`] LE_SUC_LT) THEN + ASM_SIMP_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_SIMP_TAC[] THEN + DISCH_TAC THEN + + MAP_EVERY (fun i -> ENC_TAIL_SWAP_ASM_CASES_TAC (mk_numeral (num i))) (1--14) THEN + UNDISCH_TAC `15 <= i` THEN + UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 16` THEN + ARITH_TAC; + + (* Subgoal 4: Prove backedge is taken when i > 0 *) + REPEAT STRIP_TAC THEN + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (1--1) THEN + SUBGOAL_THEN `ival ((word i):int64) < &0x0 <=> + ~(ival ((word (i + 0x1)):int64) - &0x1 = ival ((word i):int64))` ASSUME_TAC THENL + [ SUBGOAL_THEN `ival ((word i):int64) = &i` ASSUME_TAC THENL + [ MATCH_MP_TAC IVAL_WORD_LT THEN + UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `ival ((word (i + 0x1)):int64) = &(i + 1)` ASSUME_TAC THENL + [ MATCH_MP_TAC IVAL_WORD_LT THEN + UNDISCH_TAC `i < val (tail_len:int64)` THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_SIMP_TAC[]; + + (* Subgoal 5: *) + REPEAT STRIP_TAC THEN + REWRITE_TAC[byte_list_at] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[cipher_stealing_inv; CONJUNCT1 SUB_LIST; CONJUNCT1 APPEND] THEN + REWRITE_TAC[SUB_0] THEN + ASM_REWRITE_TAC[] THEN + SUBGOAL_THEN `val ((word (val (tail_len:int64))):int64) = val tail_len` SUBST1_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `(SUB_LIST (0x0,val (tail_len:int64)) (SUB_LIST (l1_curr_len + 16,val tail_len) (pt_in:byte list))) = + (SUB_LIST (l1_curr_len + 16,val tail_len) pt_in)` SUBST1_TAC THENL + [ IMP_REWRITE_TAC[SUB_LIST_REFL] THEN + ASM_REWRITE_TAC[LENGTH_SUB_LIST; MIN] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes128 (word_add ctxt_p (word l1_curr_len))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + ABBREV_TAC `curr_blocks = (acc_blocks (num_5blocks:int64) (len_full_blocks:int64) T):num` THEN + + SUBGOAL_THEN `curr_blocks = l1_curr_blocks + 0x1` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM (ASSUME `curr_blocks - 0x1 = l1_curr_blocks`)] THEN + EXPAND_TAC "curr_blocks" THEN + ASM_ARITH_TAC; ALL_TAC ] THEN + + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (1--32) THEN + + ABBREV_TAC `combinedCC = bytes_to_int128 + (APPEND (SUB_LIST (l1_curr_len + 0x10,val (tail_len:int64)) (pt_in:byte list)) + (SUB_LIST (val tail_len,0x10 - val tail_len) + (int128_to_bytes (CC:int128))))` THEN + FIRST_X_ASSUM(MP_TAC o SPEC `aes256_xts_encrypt_round combinedCC + (calculate_tweak curr_blocks iv key2_lst) key1_lst` o MATCH_MP (MESON[] + `read (Q26:(armstate,int128)component) (s:armstate) = a ==> !a'. a = a' ==> read Q26 s = a'`)) THEN + REWRITE_TAC[ASSUME `curr_blocks = l1_curr_blocks + 0x1`] THEN + ANTS_TAC THENL + [ EXPAND_TAC "key1_lst" THEN + CONV_TAC (RAND_CONV ( + REWRITE_CONV [aes256_xts_encrypt_round] THENC + DEPTH_CONV let_CONV)) THEN + GEN_REWRITE_TAC LAND_CONV [WORD_XOR_SYM] THEN + AP_THM_TAC THEN + REWRITE_TAC [aes256_encrypt] THEN + REWRITE_TAC EL_15_128_CLAUSES THEN + REWRITE_TAC [aes256_encrypt_round; aese; aesmc] THEN + CONV_TAC (TOP_DEPTH_CONV let_CONV) THEN + AP_TERM_TAC THEN + GEN_REWRITE_TAC LAND_CONV [WORD_XOR_SYM] THEN + REPEAT (AP_THM_TAC ORELSE AP_TERM_TAC) THEN + GEN_REWRITE_TAC LAND_CONV [WORD_XOR_SYM] THEN + REFL_TAC; DISCH_TAC ] THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (33--33) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_SIMP_TAC[] THEN + + UNDISCH_THEN `l1_curr_len + 16 + val (tail_len:int64) = val (len:int64)` + (fun th -> SUBST1_TAC (GSYM th)) THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`)] THEN + + (* `forall i. + i < 0x10 * l1_curr_blocks + 0x10 + val tail_len + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s33 = + EL i (aes256_xts_encrypt pt_in (0x10 * l1_curr_blocks + 0x10 + val tail_len) iv key1_lst key2_lst)` *) + MATCH_MP_TAC (SPECL [`0x10 * l1_curr_blocks:num`; `tail_len:int64`; `ctxt_p:int64`; `s33:armstate`] + BREAK_DATA_INTO_PARTS_ENCRYPT) THEN + REPEAT CONJ_TAC THENL (* 4 subgoals *) + [ (* 1. + `0x10 * l1_curr_blocks + 0x10 + val tail_len <= + LENGTH (aes256_xts_encrypt pt_in (0x10 * l1_curr_blocks + 0x10 + val tail_len) iv key1_lst key2_lst)`*) + IMP_REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT] THEN ARITH_TAC; + + (* 2. + `forall i. + i < 0x10 * l1_curr_blocks + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s33 = + EL i (aes256_xts_encrypt pt_in (0x10 * l1_curr_blocks + 0x10 + val tail_len) iv key1_lst key2_lst)` *) + UNDISCH_TAC `forall i. + i < l1_curr_len + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s33 = + EL i (aes256_xts_encrypt pt_in l1_curr_len iv key1_lst key2_lst)` THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`)] THEN + MP_TAC (SPECL [`0x10 * l1_curr_blocks:num`; `ctxt_p:int64`; + `(aes256_xts_encrypt pt_in (0x10 * l1_curr_blocks + 0x10 + val (tail_len:int64)) iv key1_lst key2_lst):byte list`; + `s33:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL [ + IMP_REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT] THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + MP_TAC (SPECL [`0x10 * l1_curr_blocks:num`; `ctxt_p:int64`; + `(aes256_xts_encrypt pt_in (0x10 * l1_curr_blocks) iv key1_lst key2_lst):byte list`; + `s33:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL [ + IMP_REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + AP_TERM_TAC THEN + MP_TAC(SPECL [`l1_curr_blocks:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT] THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`)] THEN + ASM_SIMP_TAC[SUB_LIST_LENGTH_IMPLIES]; + + (* 3. + `forall i. + i < 0x10 + ==> read (memory :> bytes8 (word_add (word_add ctxt_p (word (0x10 * l1_curr_blocks))) (word i))) + s33 = EL i (SUB_LIST (0x10 * l1_curr_blocks,0x10) + (aes256_xts_encrypt pt_in (0x10 * l1_curr_blocks + 0x10 + val tail_len) iv key1_lst key2_lst))` *) + MP_TAC (SPECL [`0x10:num`; `(word_add ctxt_p (word (0x10 * l1_curr_blocks))):int64`; + ` (SUB_LIST (0x10 * l1_curr_blocks,0x10) + (aes256_xts_encrypt pt_in (0x10 * l1_curr_blocks + 0x10 + val (tail_len:int64)) + iv key1_lst key2_lst)):byte list`; + `s33:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL [ + REWRITE_TAC[LENGTH_SUB_LIST] THEN + IMP_REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT] THEN + ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[SUB_LIST_MIN_RIGHT; MIN] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + REWRITE_TAC[READ_MEMORY_BYTES_BYTES128] THEN + ASM_REWRITE_TAC[] THEN + SIMP_TAC[ARITH_RULE `0x10 <= 0x10`] THEN + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `!x y. ~(x + 16 + y < 16)`] THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`); + ARITH_RULE `0x10 * l1_curr_blocks + 0x10 + val tail_len = + 0x10 * (l1_curr_blocks + 1) + val tail_len`] THEN + REWRITE_TAC[MOD_MULT_ADD] THEN + ASM_SIMP_TAC[MOD_LT] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[ARITH_RULE + `((0x10 * (l1_curr_blocks + 0x1) + val tail_len) - val tail_len) DIV 0x10 = + (0x10 * (l1_curr_blocks + 0x1)) DIV 0x10`] THEN + IMP_REWRITE_TAC[DIV_MULT; ARITH_RULE `~(16 = 0)`] THEN + COND_CASES_TAC THENL + [ (* `l1_curr_blocks + 0x1 < 0x2` *) + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`)] THEN + SUBGOAL_THEN `l1_curr_blocks = 0` ASSUME_TAC THENL + [ UNDISCH_TAC `l1_curr_blocks + 0x1 < 2` THEN ARITH_TAC ; ALL_TAC] THEN + REWRITE_TAC[ASSUME `l1_curr_blocks = 0x0`] THEN + EXPAND_TAC "combinedCC" THEN + REWRITE_TAC[aes256_xts_encrypt_tail] THEN + ASM_SIMP_TAC[LET_DEF; LET_END_DEF] THEN + ASM_REWRITE_TAC[GSYM (ASSUME `0 = l1_curr_len`)] THEN + CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [`(SUB_LIST (0,0x10) pt_in):byte list`; + `(SUB_LIST (0x10,val (tail_len:int64)) pt_in):byte list`; + `val (tail_len:int64)`; `iv:int128`; `0:num`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_FST_OF_ENC_CIPHER_STEALING) THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_LEFT; ARITH_RULE `16 <= 16`] THEN + + REWRITE_TAC[cipher_stealing_encrypt; LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[SUB_LIST_OF_INT128_TO_BYTES; + NUM_OF_BYTELIST_OF_INT128_TO_BYTES; CALCULATE_TWEAK_EXPAND] THEN + EXPAND_TAC "combinedCC" THEN + EXPAND_TAC "CC" THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`); ASSUME `l1_curr_blocks = 0x0`] THEN + CONV_TAC NUM_REDUCE_CONV; + ALL_TAC + ] THEN + + SUBGOAL_THEN `l1_curr_blocks >= 1` ASSUME_TAC THENL + [ UNDISCH_TAC `~(l1_curr_blocks + 0x1 < 0x2)` THEN ARITH_TAC; ALL_TAC] THEN + + IMP_REWRITE_TAC[ADD_SUB; ARITH_RULE `((l1_curr_blocks + 0x1) - 0x2) = l1_curr_blocks - 1`] THEN + + MP_TAC (SPECL [`0:num`; `(l1_curr_blocks - 1):num`; `pt_in:byte list`; `iv:int128`; + `key1_lst:int128 list`; `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + ASM_SIMP_TAC[ARITH_RULE `l1_curr_blocks >= 1 ==> ~(l1_curr_blocks - 1 < 0)`] THEN + IMP_REWRITE_TAC[SUB_0; ARITH_RULE `l1_curr_blocks >= 1 ==> l1_curr_blocks - 1 + 1 = l1_curr_blocks`] THEN + ONCE_REWRITE_TAC[ARITH_RULE `l1_curr_blocks * 16 = 16 * l1_curr_blocks`] THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN + + REWRITE_TAC[aes256_xts_encrypt_tail] THEN + ASM_SIMP_TAC[LET_DEF; LET_END_DEF] THEN + + MP_TAC (SPECL [`(SUB_LIST (l1_curr_blocks * 0x10,0x10) pt_in):byte list`; + `(SUB_LIST ((l1_curr_blocks + 0x1) * 0x10,val (tail_len:int64)) pt_in):byte list`; + `val (tail_len:int64)`; `iv:int128`; `l1_curr_blocks:num`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_FST_OF_ENC_CIPHER_STEALING) THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_LEFT; ARITH_RULE `16 <= 16`] THEN + + REWRITE_TAC[cipher_stealing_encrypt; LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[SUB_LIST_OF_INT128_TO_BYTES; + NUM_OF_BYTELIST_OF_INT128_TO_BYTES; CALCULATE_TWEAK_EXPAND; + ARITH_RULE `l1_curr_blocks * 16 = 16 * l1_curr_blocks`; + ARITH_RULE `0x10 * (l1_curr_blocks + 0x1) = 16 * l1_curr_blocks + 16`] THEN + EXPAND_TAC "combinedCC" THEN + EXPAND_TAC "CC" THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`)]; + + (* 4. Proving tail is correct + `forall i. + i < val tail_len + ==> read (memory :> bytes8 (word_add (word_add ctxt_p (word (0x10 * l1_curr_blocks + 0x10))) + (word i))) s33 = + EL i (SUB_LIST (0x10 * l1_curr_blocks + 0x10,val tail_len) + (aes256_xts_encrypt pt_in (0x10 * l1_curr_blocks + 0x10 + val tail_len) iv key1_lst key2_lst))` *) + UNDISCH_TAC + `forall i. i < val (tail_len:int64) + ==> read (memory :> bytes8 (word_add (word_add ctxt_p (word (l1_curr_len + 0x10))) + (word i))) s33 = + EL i (SUB_LIST (0x0,val tail_len) (int128_to_bytes CC))` THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`)] THEN + + MP_TAC (SPECL [`val (tail_len:int64):num`; `(word_add ctxt_p (word (0x10 * l1_curr_blocks + 0x10))):int64`; + `(SUB_LIST (0x0,val (tail_len:int64)) (int128_to_bytes CC)):byte list`; + `s33:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV THEN + UNDISCH_TAC `val (tail_len:int64) < 0x10` THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + MP_TAC (SPECL [`val (tail_len:int64):num`; `(word_add ctxt_p (word (0x10 * l1_curr_blocks + 0x10))):int64`; + `(SUB_LIST (0x10 * l1_curr_blocks + 0x10,val (tail_len:int64)) + (aes256_xts_encrypt pt_in (0x10 * l1_curr_blocks + 0x10 + val tail_len) iv key1_lst key2_lst)):byte list`; + `s33:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[LENGTH_SUB_LIST] THEN + IMP_REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT] THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + AP_TERM_TAC THEN + REWRITE_TAC[SUB_LIST_IDEMPOTENT] THEN + REWRITE_TAC[SUB_LIST_MIN_RIGHT; MIN; LE_REFL] THEN + + REWRITE_TAC[aes256_xts_encrypt; + ARITH_RULE `~(0x10 * l1_curr_blocks + 0x10 + val (tail_len:int64) < 0x10)`] THEN + REWRITE_TAC[ARITH_RULE `0x10 * l1_curr_blocks + 0x10 + val tail_len = + 0x10 * (l1_curr_blocks + 1) + val tail_len`] THEN + REWRITE_TAC[MOD_MULT_ADD] THEN + ASM_SIMP_TAC[MOD_LT] THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + REWRITE_TAC[ARITH_RULE + `((0x10 * (l1_curr_blocks + 0x1) + val tail_len) - val tail_len) DIV 0x10 = + (0x10 * (l1_curr_blocks + 0x1)) DIV 0x10`] THEN + IMP_REWRITE_TAC[DIV_MULT; ARITH_RULE `~(16 = 0)`] THEN + COND_CASES_TAC THENL + [ (* `l1_curr_blocks + 0x1 < 0x2` *) + SUBGOAL_THEN `l1_curr_blocks = 0` SUBST_ALL_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[aes256_xts_encrypt_tail] THEN + ASM_SIMP_TAC[LET_DEF; LET_END_DEF] THEN + CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [`(SUB_LIST (0,0x10) pt_in):byte list`; + `(SUB_LIST (0x10,val (tail_len:int64)) pt_in):byte list`; + `val (tail_len:int64)`; `iv:int128`; `0:num`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_FST_OF_ENC_CIPHER_STEALING) THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * 0x0 = l1_curr_len`)] THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA; ARITH_RULE `16 <= 16`] THEN + + REWRITE_TAC[cipher_stealing_encrypt; LET_DEF; LET_END_DEF; SUB_LIST_IDEMPOTENT] THEN + EXPAND_TAC "CC" THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * 0x0 = l1_curr_len`)] THEN + CONV_TAC NUM_REDUCE_CONV; + ALL_TAC + ] THEN + + SUBGOAL_THEN `l1_curr_blocks >= 1` ASSUME_TAC THENL + [ UNDISCH_TAC `~(l1_curr_blocks + 0x1 < 0x2)` THEN ARITH_TAC; ALL_TAC] THEN + + IMP_REWRITE_TAC[ADD_SUB; ARITH_RULE `((l1_curr_blocks + 0x1) - 0x2) = l1_curr_blocks - 1`] THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`)] THEN + + MP_TAC (ISPECL [`(aes256_xts_encrypt_rec 0x0 (l1_curr_blocks - 0x1) pt_in iv key1_lst key2_lst):byte list`; + `(aes256_xts_encrypt_tail l1_curr_blocks (val (tail_len:int64)) pt_in iv key1_lst key2_lst):byte list`; + `0x10 * l1_curr_blocks + 0x10:num`; `val (tail_len:int64)`; `0x10 * l1_curr_blocks:num` + ] SUB_LIST_APPEND_RIGHT_GENERAL) THEN + ANTS_TAC THENL + [ REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_REC] THEN + UNDISCH_TAC `l1_curr_blocks >= 1` THEN + ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL [ ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + REWRITE_TAC[ARITH_RULE `(0x10 * l1_curr_blocks + 0x10) - 0x10 * l1_curr_blocks = 0x10`] THEN + REWRITE_TAC[aes256_xts_encrypt_tail] THEN + ASM_SIMP_TAC[LET_DEF; LET_END_DEF] THEN + + MP_TAC (SPECL [`(SUB_LIST (l1_curr_blocks * 0x10,0x10) pt_in):byte list`; + `(SUB_LIST ((l1_curr_blocks + 0x1) * 0x10,val (tail_len:int64)) pt_in):byte list`; + `val (tail_len:int64)`; `iv:int128`; `l1_curr_blocks:num`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_FST_OF_ENC_CIPHER_STEALING) THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA; ARITH_RULE `16 <= 16`] THEN + + REWRITE_TAC[cipher_stealing_encrypt; LET_DEF; LET_END_DEF; SUB_LIST_IDEMPOTENT] THEN + EXPAND_TAC "CC" THEN + REWRITE_TAC[GSYM (ASSUME `0x10 * l1_curr_blocks = l1_curr_len`)] THEN + REWRITE_TAC[ARITH_RULE `l1_curr_blocks * 0x10 = 0x10 * l1_curr_blocks`] + ] + ] (* end of loop invariant proof. *) +);; + + +let CIPHER_STEALING_ENC_SAFE = time prove( + `exists f_events. + forall ptxt_p ctxt_p key1_p len pc + tail_len len_full_blocks num_5blocks. + PAIRWISE nonoverlapping + [(word pc, LENGTH aes256_xts_encrypt_mc); + (ptxt_p, val len); + (ctxt_p, val len); + (key1_p, 244)] + /\ val len >= 16 /\ val len <= 2 EXP 24 + /\ word_add tail_len len_full_blocks = len + /\ word_and len (word 0xfffffffffffffff0) = len_full_blocks + /\ word_and len (word 0xf) = tail_len + /\ word (val len_full_blocks DIV 0x50) = num_5blocks + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes256_xts_encrypt_mc /\ + read PC s = word (pc + 0x9e0) /\ + read X0 s = word_add ptxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + read X1 s = word_add ctxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + read X3 s = key1_p /\ + read X21 s = tail_len /\ + read X19 s = word 0x87 /\ + read events s = e) + (\s. read PC s = word (pc + 0xa8c) /\ + exists e2. + read events s = APPEND e2 e /\ + e2 = f_events ptxt_p ctxt_p key1_p tail_len len_full_blocks + num_5blocks pc /\ + memaccess_inbounds e2 + [(ptxt_p, val len); (ctxt_p, val len); (key1_p, 244)] + [(ctxt_p, val len)]) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes(ctxt_p, val len)])`, + + CONCRETIZE_F_EVENTS_TAC + `\(ptxt_p:int64) (ctxt_p:int64) (key1_p:int64) (tail_len:int64) + (len_full_blocks:int64) (num_5blocks:int64) (pc:num). + if val (tail_len) = 0 then + f_ev_short ptxt_p ctxt_p key1_p tail_len len_full_blocks + num_5blocks pc + else + APPEND + (APPEND + (f_ev_epil ptxt_p ctxt_p key1_p tail_len len_full_blocks + num_5blocks pc) + (APPEND + (ENUMERATEL (val tail_len) + (f_ev_loop ptxt_p ctxt_p key1_p tail_len len_full_blocks + num_5blocks pc)) + (f_ev_prol ptxt_p ctxt_p key1_p tail_len len_full_blocks + num_5blocks pc)) + ) + (f_ev_pre ptxt_p ctxt_p key1_p tail_len len_full_blocks + num_5blocks pc) + :(uarch_event)list` THEN + REPEAT META_EXISTS_TAC THEN + + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[byte_list_at; PAIRWISE; ALL; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + (* Prove the bounds on len_full_blocks, num_5blocks and len *) + SUBGOAL_THEN `~(val (len_full_blocks:int64) < 16)` ASSUME_TAC THENL + [ SUBGOAL_THEN `~(val (len:int64) < 16)` MP_TAC THENL + [ASM_ARITH_TAC; ALL_TAC] THEN + UNDISCH_TAC `word_and len (word 0xfffffffffffffff0) = (len_full_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `len_full_blocks:int64`] NUM_BLOCKS_LO_BOUND_1BLOCK_THM) THEN + SIMP_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `val (len_full_blocks:int64) <= 2 EXP 24` ASSUME_TAC THENL + [ UNDISCH_TAC `val (len:int64) <= 2 EXP 24` THEN + UNDISCH_TAC `word_and len (word 0xfffffffffffffff0) = (len_full_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `len_full_blocks:int64`] NUM_BLOCKS_HI_BOUND_THM) THEN + SIMP_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `val (tail_len:int64) < 16` ASSUME_TAC THENL + [ EXPAND_TAC "tail_len" THEN + REWRITE_TAC[ARITH_RULE `0xf = 2 EXP 4 - 1`] THEN + REWRITE_TAC[VAL_WORD_AND_MASK_WORD] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SIMP_TAC[MOD_LT_EQ] THEN + CONV_TAC NUM_REDUCE_CONV + ; ALL_TAC] THEN + (* relationship between variables *) + SUBGOAL_THEN `val (len_full_blocks:int64) <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "len_full_blocks" THEN SIMP_TAC[NUM_BLOCKS_LT_LEN_THM]; ALL_TAC] THEN + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks" THEN + REWRITE_TAC [VAL_WORD; DIMINDEX_64] THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks" THEN + REWRITE_TAC [VAL_WORD; DIMINDEX_64] THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 0x2 EXP 0x18` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= val (len:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + + (* Prove more properties about len_full_blocks and num_5blocks *) + SUBGOAL_THEN `val (len_full_blocks:int64) DIV 0x50 = val (num_5blocks:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks" THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `0x10 divides val (len_full_blocks:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "len_full_blocks" THEN + REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT; DIVIDES_RMUL; DIVIDES_REFL] THEN + MP_TAC (SPEC `len:int64` VAL_BOUND_64) THEN + ARITH_TAC; ALL_TAC] THEN + + (* If no tail, execute to the end *) + ASM_CASES_TAC `val (tail_len:int64) = 0` THENL + [ + ENSURES_INIT_TAC "s0" THEN + ARM_STEPS_TAC AES256_XTS_ENCRYPT_EXEC (1--2) THEN + (* Discharge if condition *) + SUBGOAL_THEN `val (word_and (tail_len:int64) (word 0xf)) = 0x0` MP_TAC THENL + [ UNDISCH_TAC `val (tail_len:int64) = 0x0` THEN BITBLAST_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + DISCHARGE_SAFETY_PROPERTY_TAC; + + ALL_TAC] THEN + + (* The cipher stealing branch *) + ASM_REWRITE_TAC[] THEN + ABBREV_TAC `curr_len = (acc_len (num_5blocks:int64) (len_full_blocks:int64)):num` THEN + + SUBGOAL_THEN `curr_len <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "curr_len" THEN + MP_TAC (SPECL [`num_5blocks:int64`; `len_full_blocks:int64`] VALUE_OF_ACC_LEN) THEN + REPEAT_N 3 (ANTS_TAC THENL [ASM_ARITH_TAC ORELSE ASM_SIMP_TAC[]; ALL_TAC]) THEN + SIMP_TAC[] THEN DISCH_TAC THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val ((word curr_len):int64) = curr_len` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + EXPAND_TAC "curr_len" THEN + MP_TAC (SPECL [`num_5blocks:int64`; `len_full_blocks:int64`; `2 EXP 64`] + BOUND_OF_ACC_LEN) THEN + ANTS_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `16 <= curr_len` ASSUME_TAC THENL + [ EXPAND_TAC "curr_len" THEN + MP_TAC (SPECL [`num_5blocks:int64`; `len_full_blocks:int64`] VALUE_OF_ACC_LEN) THEN + REPEAT_N 3 (ANTS_TAC THENL [ASM_ARITH_TAC ORELSE ASM_SIMP_TAC[]; ALL_TAC]) THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `curr_len + val (tail_len:int64) = val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "curr_len" THEN + MP_TAC (SPECL [`num_5blocks:int64`; `len_full_blocks:int64`] VALUE_OF_ACC_LEN) THEN + REPEAT_N 3 (ANTS_TAC THENL [ASM_ARITH_TAC ORELSE ASM_SIMP_TAC[]; ALL_TAC]) THEN + SIMP_TAC[] THEN DISCH_TAC THEN + REWRITE_TAC[GSYM (ASSUME `word_add (tail_len:int64) len_full_blocks = len`)] THEN + ASM_SIMP_TAC[VAL_WORD_ADD_CASES; DIMINDEX_64; + ARITH_RULE `val len_full_blocks <= 0x1000000 /\ val tail_len < 0x10 ==> + val tail_len + val len_full_blocks < 0x2 EXP 0x40`] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + + (* Pre-loop: branch check + register setup, 5 steps to reach loop start *) + ENSURES_EVENTS_SEQUENCE_TAC `pc + 0x9f4` + `\s. + read X0 s = word_add ptxt_p (word curr_len) /\ + read X1 s = word_add ctxt_p (word (curr_len - 0x10)) /\ + read X13 s = word_add ctxt_p (word curr_len) /\ + read X20 s = word_add ptxt_p (word curr_len) /\ + read X21 s = tail_len` THEN + CONJ_TAC THENL + [ + REWRITE_TAC[byte_list_at] THEN + UNDISCH_THEN `val ((word curr_len):int64) = curr_len` + (fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th]) THEN REWRITE_TAC[th]) THEN + + ENSURES_INIT_TAC "s0" THEN + ARM_STEPS_TAC AES256_XTS_ENCRYPT_EXEC (1--2) THEN + + (* Discharge if condition *) + SUBGOAL_THEN `~(val (word_and (tail_len:int64) (word 0xf)) = 0x0)` MP_TAC THENL + [ UNDISCH_TAC `~(val (tail_len:int64) = 0x0)` THEN + UNDISCH_TAC `val (tail_len:int64) < 16` THEN + MP_TAC (SPEC `tail_len:int64` WORD_AND_MASK16_EQ_0) THEN + SIMP_TAC[]; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ARM_STEPS_TAC AES256_XTS_ENCRYPT_EXEC (3--5) THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + CONJ_TAC THENL [ + ASM_SIMP_TAC[WORD_SUB] THEN + CONV_TAC WORD_RULE; ALL_TAC] THEN + ABBREV_TAC `vlen = val (len:int64)` THEN + DISCHARGE_SAFETY_PROPERTY_TAC; + + ALL_TAC + ] THEN + + (* Abbreviate for the loop: l1_curr_len = curr_len - 16 *) + ABBREV_TAC `l1_curr_len = (curr_len - 0x10):num` THEN + SUBGOAL_THEN `curr_len = l1_curr_len + 0x10` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `l1_curr_len + 0x10 + val (tail_len:int64) = val (len:int64)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + + (* Invariant proof for .composite_enc_loop *) + ENSURES_EVENTS_WHILE_UP2_TAC + `val (tail_len:int64)` + `pc + 0x9f4` + `pc + 0xa0c` + `\i s. + ( read X0 s = word_add ptxt_p (word curr_len) /\ + read X1 s = word_add ctxt_p (word l1_curr_len) /\ + read X13 s = word_add ctxt_p (word curr_len) /\ + read X20 s = word_add ptxt_p (word curr_len) /\ + read X21 s = (word (val (tail_len:int64) - i)):int64)` THEN + ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL + [ + (* Subgoal 1: invariant holds before entering loop *) + REWRITE_TAC[byte_list_at] THEN + + ENSURES_INIT_TAC "s0" THEN STRIP_EXISTS_ASSUM_TAC THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + REWRITE_TAC[WORD_VAL; SUB_0] THEN NO_TAC; + + DISCHARGE_SAFETY_PROPERTY_TAC + ]; + + (* Subgoal 2: inductive step *) + REWRITE_TAC[] THEN + REPEAT STRIP_TAC THEN + ABBREV_TAC `n = val (tail_len:int64)` THEN + + (* For non-overlapping and MAYCHANGE address reasoning *) + SUBGOAL_THEN `l1_curr_len + 16 + (n - i - 1) < val (len:int64)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes8 (word_add ctxt_p (word (l1_curr_len + 0x10 + + (n - i - 1))))],, + MAYCHANGE [memory :> bytes8 (word_add ctxt_p (word (l1_curr_len + + (n - i - 1))))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + STRIP_EXISTS_ASSUM_TAC THEN + + SUBGOAL_THEN `val ((word (n - i)):int64) = n - i` SUBST_ALL_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `i < n` THEN + UNDISCH_TAC `n < 0x10` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val ((word (n - (i + 0x1))):int64) = n - (i + 1)` SUBST_ALL_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `i < n` THEN + UNDISCH_TAC `n < 0x10` THEN + ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `word_sub ((word (i + 0x1)):int64) (word 0x1) = word i` ASSUME_TAC THENL + [ REWRITE_TAC[GSYM VAL_EQ; VAL_WORD_SUB; DIMINDEX_64] THEN + MP_TAC (SPECL [`val ((word (i + 0x1)):int64)`; `0x2 EXP 0x40`; `val ((word 0x1):int64)`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN ASM_ARITH_TAC + ; ALL_TAC] THEN + ANTS_TAC THENL [ WORD_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; `val ((word (i + 0x1)):int64) - val ((word 0x1):int64)`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + SIMP_TAC[ARITH_RULE `!x. 1 * x = x`] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[MOD_LT] THEN + CONJ_TAC THENL + [ SUBGOAL_THEN `i + 1 < 2 EXP 64` MP_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + ARITH_TAC; + UNDISCH_TAC `i < n` THEN + UNDISCH_TAC `n < 0x10` THEN + WORD_ARITH_TAC] + ; ALL_TAC] THEN + + SUBGOAL_THEN `val ((word i):int64) < 0x10` ASSUME_TAC THENL + [ UNDISCH_TAC `i < n` THEN + UNDISCH_TAC `n < 0x10` THEN + WORD_ARITH_TAC; ALL_TAC ] THEN + + ARM_STEPS_TAC AES256_XTS_ENCRYPT_EXEC (1--6) THEN + (* Help MAYCHANGE predicate be syntactically similar to the MAYCHANGE conclusion *) + SUBGOAL_THEN `word_sub (word (n - i)) (word 1) = word (n - i - 1):int64` SUBST_ALL_TAC THENL [ + IMP_REWRITE_TAC[WORD_SUB2] THEN SIMPLE_ARITH_TAC; + ALL_TAC; + ] THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + + CONJ_TAC THENL [ + SUBGOAL_THEN `1 <= n - i /\ n - i <= 15` STRIP_ASSUME_TAC THENL + [SIMPLE_ARITH_TAC; ALL_TAC] THEN + VAL_INT64_TAC `n - i` THEN + VAL_INT64_TAC `n - i - 1` THEN + SUBGOAL_THEN `ival (word (n - i):int64) = &(n - i)` ASSUME_TAC THENL + [REWRITE_TAC[ival] THEN ASM_REWRITE_TAC[] THEN + REWRITE_TAC[DIMINDEX_64] THEN CONV_TAC NUM_REDUCE_CONV THEN + SIMPLE_ARITH_TAC; + ALL_TAC] THEN + SUBGOAL_THEN `ival (word (n - i - 1):int64) = &(n - i - 1)` + ASSUME_TAC THENL + [REWRITE_TAC[ival] THEN ASM_REWRITE_TAC[] THEN + REWRITE_TAC[DIMINDEX_64] THEN CONV_TAC NUM_REDUCE_CONV THEN + SIMPLE_ARITH_TAC; + ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + SUBGOAL_THEN `~(&(n - i - 1):int < &0)` (fun th -> REWRITE_TAC[th]) THENL + [REWRITE_TAC[INT_NOT_LT; INT_POS]; ALL_TAC] THEN + + SUBGOAL_THEN `&(n - i) - &1:int = &(n - i - 1)` SUBST1_TAC THENL + [ ASM_SIMP_TAC[GSYM INT_OF_NUM_SUB]; ALL_TAC] THEN + SIMPLE_ARITH_TAC; + + ALL_TAC + ] THEN + CONJ_TAC THENL [ + AP_TERM_TAC THEN SIMPLE_ARITH_TAC; + ALL_TAC + ] THEN + + UNDISCH_THEN `curr_len - 0x10 = l1_curr_len` (SUBST_ALL_TAC o GSYM) THEN + + SUBGOAL_THEN `curr_len - 0x10 + 0x10 = curr_len` SUBST_ALL_TAC THENL + [ UNDISCH_TAC `0x10 <= curr_len` THEN ARITH_TAC; ALL_TAC] THEN + + ABBREV_TAC `m = val (len:int64)` THEN + DISCHARGE_SAFETY_PROPERTY_TAC + ~abbrevs_unfold_before_f_events_tac:[ + `acc_len num_5blocks len_full_blocks = curr_len`; + `val (tail_len:int64) = n`; + ]; + + (* Subgoal 3: post-loop epilogue *) + REWRITE_TAC[] THEN + ENSURES_INIT_TAC "s0" THEN STRIP_EXISTS_ASSUM_TAC THEN + ARM_STEPS_TAC AES256_XTS_ENCRYPT_EXEC (1--32) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + CONJ_TAC THENL [ + UNDISCH_THEN `curr_len - 0x10 = l1_curr_len` (SUBST_ALL_TAC o GSYM) THEN + + SUBGOAL_THEN `curr_len - 0x10 + 0x10 = curr_len` SUBST_ALL_TAC THENL + [ UNDISCH_TAC `0x10 <= curr_len` THEN ARITH_TAC; ALL_TAC] THEN + + REWRITE_TAC[GSYM (ASSUME `acc_len num_5blocks len_full_blocks = curr_len`)] THEN + ABBREV_TAC `vlen = val (len:int64)` THEN + DISCHARGE_SAFETY_PROPERTY_TAC; + + (* Maychange *) + ABBREV_TAC `vallen = val (len:int64)` THEN + MONOTONE_MAYCHANGE_TAC + ] + ] +);; + + +(* Proof: Less than 2 blocks *) +let AES_XTS_ENCRYPT_LT_2BLOCK_CORRECT = time prove( + `!ptxt_p ctxt_p len key1_p key2_p iv_p + pt_in iv + k1_0 k1_1 k1_2 k1_3 k1_4 k1_5 k1_6 k1_7 k1_8 k1_9 k1_10 k1_11 k1_12 k1_13 k1_14 + k2_0 k2_1 k2_2 k2_3 k2_4 k2_5 k2_6 k2_7 k2_8 k2_9 k2_10 k2_11 k2_12 k2_13 k2_14 + pc. + PAIRWISE nonoverlapping + [(word pc, LENGTH aes256_xts_encrypt_mc); + (ptxt_p, val len); + (ctxt_p, val len); + (key1_p, 244); + (key2_p, 244)] /\ + val len >= 16 /\ val len < 0x20 /\ LENGTH pt_in = val len /\ + [k1_0; k1_1; k1_2; k1_3; k1_4; k1_5; k1_6; k1_7; k1_8; k1_9; k1_10; + k1_11; k1_12; k1_13; k1_14] = key1_lst /\ + [k2_0; k2_1; k2_2; k2_3; k2_4; k2_5; k2_6; k2_7; k2_8; k2_9; k2_10; + k2_11; k2_12; k2_13; k2_14] = key2_lst + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes256_xts_encrypt_mc /\ + read PC s = word (pc + 0x1c) /\ + C_ARGUMENTS [ptxt_p; ctxt_p; len; key1_p; key2_p; iv_p] s /\ + byte_list_at pt_in ptxt_p len s /\ + read(memory :> bytes128 iv_p) s = iv /\ + set_key_schedule s key1_p k1_0 k1_1 k1_2 k1_3 k1_4 k1_5 k1_6 k1_7 k1_8 k1_9 k1_10 k1_11 k1_12 k1_13 k1_14 /\ + set_key_schedule s key2_p k2_0 k2_1 k2_2 k2_3 k2_4 k2_5 k2_6 k2_7 k2_8 k2_9 k2_10 k2_11 k2_12 k2_13 k2_14) + (\s. read PC s = word (pc + 0xa8c) /\ //LENGTH aes256_xts_encrypt_mc - 8*4 = 0xaac - 0x8 * 0x4 + byte_list_at (aes256_xts_encrypt pt_in (val len) iv key1_lst key2_lst) ctxt_p len s + ) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes(ctxt_p, val len)]) + `, + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; byte_list_at; C_ARGUMENTS; SOME_FLAGS; PAIRWISE; ALL; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + SUBGOAL_THEN `word_add (word_and len (word 0xf)) + (word_and len (word 0xfffffffffffffff0)) = len:int64` ASSUME_TAC THENL + [REWRITE_TAC[word_split_lemma]; ALL_TAC] THEN + ABBREV_TAC `len_full_blocks:int64 = word_and len (word 0xfffffffffffffff0)` THEN + ABBREV_TAC `tail_len:int64 = word_and len (word 0xf)` THEN + ABBREV_TAC `num_5blocks = (word (val (len_full_blocks:int64) DIV 0x50)):int64` THEN + + SUBGOAL_THEN `val (len_full_blocks:int64) = 16` ASSUME_TAC THENL + [ EXPAND_TAC "len_full_blocks" THEN + REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `val (len:int64) DIV 16 = 1` SUBST1_TAC THENL + [ MATCH_MP_TAC(MESON[LE_ANTISYM] `m <= n /\ n <= m ==> m = n`) THEN + CONJ_TAC THENL [ ASM_ARITH_TAC; ASM_ARITH_TAC]; + ALL_TAC] THEN + ARITH_TAC; ALL_TAC] THEN + + (* Prove property until start of cipher stealing. *) + ENSURES_SEQUENCE_TAC `pc + 0x9e0` + `\s. + read X0 s = word_add ptxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + read X1 s = word_add ctxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + read X3 s = key1_p /\ + read X21 s = tail_len /\ + read Q6 s = calculate_tweak (acc_blocks num_5blocks len_full_blocks T) iv key2_lst /\ + read X19 s = word 0x87 /\ + read Q16 s = k1_0 /\ read Q17 s = k1_1 /\ read Q12 s = k1_2 /\ read Q13 s = k1_3 /\ + read Q14 s = k1_4 /\ read Q15 s = k1_5 /\ read Q4 s = k1_6 /\ read Q5 s = k1_7 /\ + read Q18 s = k1_8 /\ read Q19 s = k1_9 /\ read Q20 s = k1_10 /\ read Q21 s = k1_11 /\ + read Q22 s = k1_12 /\ read Q23 s = k1_13 /\ read Q7 s = k1_14 /\ + byte_list_at pt_in ptxt_p len s /\ + byte_list_at (aes256_xts_encrypt pt_in (acc_len num_5blocks len_full_blocks) iv key1_lst key2_lst) + ctxt_p (word (acc_len num_5blocks len_full_blocks)) s` THEN + CONJ_TAC THENL + [ + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes128 ctxt_p]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (1--2) THEN + + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (len:int64) (word 0x10)) < &0x0 + <=> ~(ival (len:int64) - &0x10 = ival (word_sub (len:int64) (word 0x10)))` MP_TAC THENL + [ MP_TAC (BITBLAST_RULE (* put in tips doc. Q: When to use it vs. ARITH_RULE? *) + `val (len:int64) >= 0x10 ==> val len < 0x20 ==> + ival (word_sub len (word 0x10)) >= &0x0`) THEN + ASM_REWRITE_TAC[] THEN + MP_TAC (BITBLAST_RULE + `val (len:int64) >= 0x10 ==> val len < 0x20 ==> + ival (len:int64) - &0x10 = ival (word_sub len (word 0x10))`) THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; + ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + MP_TAC (SPECL [`ptxt_p:int64`; `len:int64`; `pt_in:byte list`; `s2:armstate`] READ_LT_2BLOCK) THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (3--65) THEN + (* Prove Q6 stores initial tweak *) + FIRST_X_ASSUM(MP_TAC o SPEC `(calculate_tweak 0 iv key2_lst)` + o MATCH_MP (MESON[] `read Q6 s = a ==> !a'. a = a' ==> read Q6 s = a'`)) THEN + ANTS_TAC THENL + [ REWRITE_TAC[CONJUNCT1 calculate_tweak; xts_init_tweak] THEN + EXPAND_TAC "key2_lst" THEN AESENC_TAC; DISCH_TAC] THEN + + (* Simulating until branching into tail1x *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (66--77) THEN + (* Simulate AES-XTS encryption of block in Q0 *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (78--108) THEN + XTSENC_TAC `Q0:(armstate,int128)component` `0` `0` THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (109--118) THEN (* until b .Lxts_enc_done = arm_B (word 0x8) *) + TWEAK_TAC `Q6:(armstate,int128)component` `1:num` `0:num` THEN + + SUBGOAL_THEN `val (num_5blocks:int64) = 0` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks" THEN + UNDISCH_TAC `val (len_full_blocks:int64) = 0x10` THEN + SIMP_TAC[] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[VAL_WORD_0]; ALL_TAC ] THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + (* `word_add ptxt_p (word 0x10) = word_add ptxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + word_add ctxt_p (word 0x10) = word_add ctxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + calculate_tweak 0x1 iv key2_lst = calculate_tweak (acc_blocks num_5blocks len_full_blocks true) iv key2_lst /\ + (forall i. + i < val (word (acc_len num_5blocks len_full_blocks)) + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s118 = + EL i (aes256_xts_encrypt pt_in (acc_len num_5blocks len_full_blocks) iv key1_lst key2_lst))` *) + REPEAT CONJ_TAC THENL + [ + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_blocks] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0x10`; `ctxt_p:int64`; `(aes256_xts_encrypt pt_in 0x10 iv key1_lst key2_lst):byte list`; + `s118:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL [ + MP_TAC (SPECL [`1`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_1BLOCK_ENC] + ] + ; ALL_TAC] THEN + + (* Reuse the cipher stealing proof *) + MP_TAC CIPHER_STEALING_ENC_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[byte_list_at; PAIRWISE; ALL; MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + ASM_SIMP_TAC[] THEN + ASM_ARITH_TAC +);; + +(* Proof: Less than 3 blocks *) +let AES_XTS_ENCRYPT_LT_3BLOCK_CORRECT = time prove( + `!ptxt_p ctxt_p len key1_p key2_p iv_p + pt_in iv + k1_0 k1_1 k1_2 k1_3 k1_4 k1_5 k1_6 k1_7 k1_8 k1_9 k1_10 k1_11 k1_12 k1_13 k1_14 + k2_0 k2_1 k2_2 k2_3 k2_4 k2_5 k2_6 k2_7 k2_8 k2_9 k2_10 k2_11 k2_12 k2_13 k2_14 + pc. + PAIRWISE nonoverlapping + [(word pc, LENGTH aes256_xts_encrypt_mc); + (ptxt_p, val len); + (ctxt_p, val len); + (key1_p, 244); + (key2_p, 244)] /\ + ~(val len < 0x20) /\ val len < 0x30 /\ LENGTH pt_in = val len /\ + [k1_0; k1_1; k1_2; k1_3; k1_4; k1_5; k1_6; k1_7; k1_8; k1_9; k1_10; + k1_11; k1_12; k1_13; k1_14] = key1_lst /\ + [k2_0; k2_1; k2_2; k2_3; k2_4; k2_5; k2_6; k2_7; k2_8; k2_9; k2_10; + k2_11; k2_12; k2_13; k2_14] = key2_lst + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes256_xts_encrypt_mc /\ + read PC s = word (pc + 0x1c) /\ + C_ARGUMENTS [ptxt_p; ctxt_p; len; key1_p; key2_p; iv_p] s /\ + byte_list_at pt_in ptxt_p len s /\ + read(memory :> bytes128 iv_p) s = iv /\ + set_key_schedule s key1_p k1_0 k1_1 k1_2 k1_3 k1_4 k1_5 k1_6 k1_7 k1_8 k1_9 k1_10 k1_11 k1_12 k1_13 k1_14 /\ + set_key_schedule s key2_p k2_0 k2_1 k2_2 k2_3 k2_4 k2_5 k2_6 k2_7 k2_8 k2_9 k2_10 k2_11 k2_12 k2_13 k2_14) + (\s. read PC s = word (pc + 0xa8c) /\ //LENGTH aes256_xts_encrypt_mc - 8*4 = 0xaac - 0x8 * 0x4 + byte_list_at (aes256_xts_encrypt pt_in (val len) iv key1_lst key2_lst) ctxt_p len s + ) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes(ctxt_p, val len)]) + `, + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; byte_list_at; C_ARGUMENTS; SOME_FLAGS; PAIRWISE; ALL; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + SUBGOAL_THEN `word_add (word_and len (word 0xf)) + (word_and len (word 0xfffffffffffffff0)) = len:int64` ASSUME_TAC THENL + [REWRITE_TAC[word_split_lemma]; ALL_TAC] THEN + ABBREV_TAC `len_full_blocks:int64 = word_and len (word 0xfffffffffffffff0)` THEN + ABBREV_TAC `tail_len:int64 = word_and len (word 0xf)` THEN + ABBREV_TAC `num_5blocks = (word (val (len_full_blocks:int64) DIV 0x50)):int64` THEN + + SUBGOAL_THEN `val (len_full_blocks:int64) = 0x20` ASSUME_TAC THENL + [ EXPAND_TAC "len_full_blocks" THEN + REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `val (len:int64) DIV 16 = 2` SUBST1_TAC THENL + [ MATCH_MP_TAC(MESON[LE_ANTISYM] `m <= n /\ n <= m ==> m = n`) THEN + CONJ_TAC THENL [ ASM_ARITH_TAC; ASM_ARITH_TAC]; + ALL_TAC] THEN + ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `val (num_5blocks:int64) = 0` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks" THEN + UNDISCH_TAC `val (len_full_blocks:int64) = 0x20` THEN + SIMP_TAC[] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[VAL_WORD_0]; ALL_TAC ] THEN + + (* Prove property until start of cipher stealing. *) + ENSURES_SEQUENCE_TAC `pc + 0x9e0` + `\s. + read X0 s = word_add ptxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + read X1 s = word_add ctxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + read X3 s = key1_p /\ + read X21 s = tail_len /\ + read Q6 s = calculate_tweak (acc_blocks num_5blocks len_full_blocks T) iv key2_lst /\ + read X19 s = word 0x87 /\ + read Q16 s = k1_0 /\ read Q17 s = k1_1 /\ read Q12 s = k1_2 /\ read Q13 s = k1_3 /\ + read Q14 s = k1_4 /\ read Q15 s = k1_5 /\ read Q4 s = k1_6 /\ read Q5 s = k1_7 /\ + read Q18 s = k1_8 /\ read Q19 s = k1_9 /\ read Q20 s = k1_10 /\ read Q21 s = k1_11 /\ + read Q22 s = k1_12 /\ read Q23 s = k1_13 /\ read Q7 s = k1_14 /\ + byte_list_at pt_in ptxt_p len s /\ + byte_list_at (aes256_xts_encrypt pt_in (acc_len num_5blocks len_full_blocks) iv key1_lst key2_lst) + ctxt_p (word (acc_len num_5blocks len_full_blocks)) s` THEN + CONJ_TAC THENL + [ + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes128 ctxt_p; + memory :> bytes128 (word_add ctxt_p (word 0x10))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (1--2) THEN + + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (len:int64) (word 0x10)) < &0x0 + <=> ~(ival (len:int64) - &0x10 = ival (word_sub (len:int64) (word 0x10)))` MP_TAC THENL + [ MP_TAC (BITBLAST_RULE (* put in tips doc. Q: When to use it vs. ARITH_RULE? *) + `~(val (len:int64) < 0x20) ==> val len < 0x30 ==> + ival (word_sub len (word 0x10)) >= &0x0`) THEN + ASM_REWRITE_TAC[] THEN + MP_TAC (BITBLAST_RULE + `~(val (len:int64) < 0x20) ==> val len < 0x30 ==> + ival (len:int64) - &0x10 = ival (word_sub len (word 0x10))`) THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; + ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + MP_TAC (SPECL [`ptxt_p:int64`; `len:int64`; `pt_in:byte list`; `s2:armstate`] READ_LT_3BLOCK) THEN + ASM_SIMP_TAC[] THEN REPEAT STRIP_TAC THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (3--65) THEN + (* Prove Q6 stores initial tweak *) + FIRST_X_ASSUM(MP_TAC o SPEC `(calculate_tweak 0 iv key2_lst)` + o MATCH_MP (MESON[] `read Q6 s = a ==> !a'. a = a' ==> read Q6 s = a'`)) THEN + ANTS_TAC THENL + [ REWRITE_TAC[CONJUNCT1 calculate_tweak; xts_init_tweak] THEN + EXPAND_TAC "key2_lst" THEN AESENC_TAC; DISCH_TAC] THEN + + (* Simulating until branching into tail2x *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (66--87) THEN + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + (* Simulate AES-XTS encryption of blocks in Q0, Q1 *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (88--148) THEN + XTSENC_TAC `Q0:(armstate,int128)component` `0` `0` THEN + XTSENC_TAC `Q1:(armstate,int128)component` `0x10` `1` THEN + (* until b .Lxts_enc_done = arm_B (word xxx) *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (149--158) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `2:num` `1:num` THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + + REPEAT CONJ_TAC THENL + [ + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_blocks] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0x20`; `ctxt_p:int64`; `(aes256_xts_encrypt pt_in 0x20 iv key1_lst key2_lst):byte list`; + `s158:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL [ + MP_TAC (SPECL [`2`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_2BLOCKS_ENC] + ] + ; ALL_TAC] THEN + + (* Reuse the cipher stealing proof *) + MP_TAC CIPHER_STEALING_ENC_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[byte_list_at; PAIRWISE; ALL; MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + ASM_SIMP_TAC[] THEN + ASM_ARITH_TAC +);; + +(* Proof: Less than 4 blocks *) +let AES_XTS_ENCRYPT_LT_4BLOCK_CORRECT = time prove( + `!ptxt_p ctxt_p len key1_p key2_p iv_p + pt_in iv + k1_0 k1_1 k1_2 k1_3 k1_4 k1_5 k1_6 k1_7 k1_8 k1_9 k1_10 k1_11 k1_12 k1_13 k1_14 + k2_0 k2_1 k2_2 k2_3 k2_4 k2_5 k2_6 k2_7 k2_8 k2_9 k2_10 k2_11 k2_12 k2_13 k2_14 + pc. + PAIRWISE nonoverlapping + [(word pc, LENGTH aes256_xts_encrypt_mc); + (ptxt_p, val len); + (ctxt_p, val len); + (key1_p, 244); + (key2_p, 244)] /\ + ~(val len < 0x30) /\ val len < 0x40 /\ LENGTH pt_in = val len /\ + [k1_0; k1_1; k1_2; k1_3; k1_4; k1_5; k1_6; k1_7; k1_8; k1_9; k1_10; + k1_11; k1_12; k1_13; k1_14] = key1_lst /\ + [k2_0; k2_1; k2_2; k2_3; k2_4; k2_5; k2_6; k2_7; k2_8; k2_9; k2_10; + k2_11; k2_12; k2_13; k2_14] = key2_lst + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes256_xts_encrypt_mc /\ + read PC s = word (pc + 0x1c) /\ + C_ARGUMENTS [ptxt_p; ctxt_p; len; key1_p; key2_p; iv_p] s /\ + byte_list_at pt_in ptxt_p len s /\ + read(memory :> bytes128 iv_p) s = iv /\ + set_key_schedule s key1_p k1_0 k1_1 k1_2 k1_3 k1_4 k1_5 k1_6 k1_7 k1_8 k1_9 k1_10 k1_11 k1_12 k1_13 k1_14 /\ + set_key_schedule s key2_p k2_0 k2_1 k2_2 k2_3 k2_4 k2_5 k2_6 k2_7 k2_8 k2_9 k2_10 k2_11 k2_12 k2_13 k2_14) + (\s. read PC s = word (pc + 0xa8c) /\ //LENGTH aes256_xts_encrypt_mc - 8*4 = 0xaac - 0x8 * 0x4 + byte_list_at (aes256_xts_encrypt pt_in (val len) iv key1_lst key2_lst) ctxt_p len s + ) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes(ctxt_p, val len)]) + `, + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; byte_list_at; C_ARGUMENTS; SOME_FLAGS; PAIRWISE; ALL; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + SUBGOAL_THEN `word_add (word_and len (word 0xf)) + (word_and len (word 0xfffffffffffffff0)) = len:int64` ASSUME_TAC THENL + [REWRITE_TAC[word_split_lemma]; ALL_TAC] THEN + ABBREV_TAC `len_full_blocks:int64 = word_and len (word 0xfffffffffffffff0)` THEN + ABBREV_TAC `tail_len:int64 = word_and len (word 0xf)` THEN + ABBREV_TAC `num_5blocks = (word (val (len_full_blocks:int64) DIV 0x50)):int64` THEN + + SUBGOAL_THEN `val (len_full_blocks:int64) = 0x30` ASSUME_TAC THENL + [ EXPAND_TAC "len_full_blocks" THEN + REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `val (len:int64) DIV 16 = 3` SUBST1_TAC THENL + [ MATCH_MP_TAC(MESON[LE_ANTISYM] `m <= n /\ n <= m ==> m = n`) THEN + CONJ_TAC THENL [ ASM_ARITH_TAC; ASM_ARITH_TAC]; + ALL_TAC] THEN + ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `val (num_5blocks:int64) = 0` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks" THEN + UNDISCH_TAC `val (len_full_blocks:int64) = 0x30` THEN + SIMP_TAC[] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[VAL_WORD_0]; ALL_TAC ] THEN + + (* Prove property until start of cipher stealing. *) + ENSURES_SEQUENCE_TAC `pc + 0x9e0` + `\s. + read X0 s = word_add ptxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + read X1 s = word_add ctxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + read X3 s = key1_p /\ + read X21 s = tail_len /\ + read Q6 s = calculate_tweak (acc_blocks num_5blocks len_full_blocks T) iv key2_lst /\ + read X19 s = word 0x87 /\ + read Q16 s = k1_0 /\ read Q17 s = k1_1 /\ read Q12 s = k1_2 /\ read Q13 s = k1_3 /\ + read Q14 s = k1_4 /\ read Q15 s = k1_5 /\ read Q4 s = k1_6 /\ read Q5 s = k1_7 /\ + read Q18 s = k1_8 /\ read Q19 s = k1_9 /\ read Q20 s = k1_10 /\ read Q21 s = k1_11 /\ + read Q22 s = k1_12 /\ read Q23 s = k1_13 /\ read Q7 s = k1_14 /\ + byte_list_at pt_in ptxt_p len s /\ + byte_list_at (aes256_xts_encrypt pt_in (acc_len num_5blocks len_full_blocks) iv key1_lst key2_lst) + ctxt_p (word (acc_len num_5blocks len_full_blocks)) s` THEN + CONJ_TAC THENL + [ + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes128 ctxt_p; + memory :> bytes128 (word_add ctxt_p (word 0x10)); + memory :> bytes128 (word_add ctxt_p (word 0x20))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (1--2) THEN + + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (len:int64) (word 0x10)) < &0x0 + <=> ~(ival (len:int64) - &0x10 = ival (word_sub (len:int64) (word 0x10)))` MP_TAC THENL + [ MP_TAC (BITBLAST_RULE (* put in tips doc. Q: When to use it vs. ARITH_RULE? *) + `~(val (len:int64) < 0x30) ==> val len < 0x40 ==> + ival (word_sub len (word 0x10)) >= &0x0`) THEN + ASM_REWRITE_TAC[] THEN + MP_TAC (BITBLAST_RULE + `~(val (len:int64) < 0x30) ==> val len < 0x40 ==> + ival (len:int64) - &0x10 = ival (word_sub len (word 0x10))`) THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; + ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + MP_TAC (SPECL [`ptxt_p:int64`; `len:int64`; `pt_in:byte list`; `s2:armstate`] READ_LT_4BLOCK) THEN + ASM_SIMP_TAC[] THEN REPEAT STRIP_TAC THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (3--65) THEN + (* Prove Q6 stores initial tweak *) + FIRST_X_ASSUM(MP_TAC o SPEC `(calculate_tweak 0 iv key2_lst)` + o MATCH_MP (MESON[] `read Q6 s = a ==> !a'. a = a' ==> read Q6 s = a'`)) THEN + ANTS_TAC THENL + [ REWRITE_TAC[CONJUNCT1 calculate_tweak; xts_init_tweak] THEN + EXPAND_TAC "key2_lst" THEN AESENC_TAC; DISCH_TAC] THEN + + (* Simulating until branching into tail3x *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (66--87) THEN + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (88--95) THEN + TWEAK_TAC `Q9:(armstate,int128)component` `2:num` `1:num` THEN + (* Simulate AES-XTS encryption of block in Q0, Q1, Q24 *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (96--187) THEN + XTSENC_TAC `Q0:(armstate,int128)component` `0` `0` THEN + XTSENC_TAC `Q1:(armstate,int128)component` `0x10` `1` THEN + XTSENC_TAC `Q24:(armstate,int128)component` `0x20` `2` THEN + (* until b .Lxts_enc_done = arm_B (word xxx) *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (188--198) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `3:num` `2:num` THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + + REPEAT CONJ_TAC THENL + [ + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_blocks] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0x30`; `ctxt_p:int64`; `(aes256_xts_encrypt pt_in 0x30 iv key1_lst key2_lst):byte list`; + `s198:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL [ + MP_TAC (SPECL [`3`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_3BLOCKS_ENC] + ] + ; ALL_TAC] THEN + + (* Reuse the cipher stealing proof *) + MP_TAC CIPHER_STEALING_ENC_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[byte_list_at; PAIRWISE; ALL; MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + ASM_SIMP_TAC[] THEN + ASM_ARITH_TAC +);; + +(* Proof: Less than 5 blocks *) +let AES_XTS_ENCRYPT_LT_5BLOCK_CORRECT = time prove( + `!ptxt_p ctxt_p len key1_p key2_p iv_p + pt_in iv + k1_0 k1_1 k1_2 k1_3 k1_4 k1_5 k1_6 k1_7 k1_8 k1_9 k1_10 k1_11 k1_12 k1_13 k1_14 + k2_0 k2_1 k2_2 k2_3 k2_4 k2_5 k2_6 k2_7 k2_8 k2_9 k2_10 k2_11 k2_12 k2_13 k2_14 + pc. + PAIRWISE nonoverlapping + [(word pc, LENGTH aes256_xts_encrypt_mc); + (ptxt_p, val len); + (ctxt_p, val len); + (key1_p, 244); + (key2_p, 244)] /\ + ~(val len < 0x40) /\ val len < 0x50 /\ LENGTH pt_in = val len /\ + [k1_0; k1_1; k1_2; k1_3; k1_4; k1_5; k1_6; k1_7; k1_8; k1_9; k1_10; + k1_11; k1_12; k1_13; k1_14] = key1_lst /\ + [k2_0; k2_1; k2_2; k2_3; k2_4; k2_5; k2_6; k2_7; k2_8; k2_9; k2_10; + k2_11; k2_12; k2_13; k2_14] = key2_lst + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes256_xts_encrypt_mc /\ + read PC s = word (pc + 0x1c) /\ + C_ARGUMENTS [ptxt_p; ctxt_p; len; key1_p; key2_p; iv_p] s /\ + byte_list_at pt_in ptxt_p len s /\ + read(memory :> bytes128 iv_p) s = iv /\ + set_key_schedule s key1_p k1_0 k1_1 k1_2 k1_3 k1_4 k1_5 k1_6 k1_7 k1_8 k1_9 k1_10 k1_11 k1_12 k1_13 k1_14 /\ + set_key_schedule s key2_p k2_0 k2_1 k2_2 k2_3 k2_4 k2_5 k2_6 k2_7 k2_8 k2_9 k2_10 k2_11 k2_12 k2_13 k2_14) + (\s. read PC s = word (pc + 0xa8c) /\ //LENGTH aes256_xts_encrypt_mc - 8*4 = 0xaac - 0x8 * 0x4 + byte_list_at (aes256_xts_encrypt pt_in (val len) iv key1_lst key2_lst) ctxt_p len s + ) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes(ctxt_p, val len)]) + `, + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; byte_list_at; C_ARGUMENTS; SOME_FLAGS; PAIRWISE; ALL; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + SUBGOAL_THEN `word_add (word_and len (word 0xf)) + (word_and len (word 0xfffffffffffffff0)) = len:int64` ASSUME_TAC THENL + [REWRITE_TAC[word_split_lemma]; ALL_TAC] THEN + ABBREV_TAC `len_full_blocks:int64 = word_and len (word 0xfffffffffffffff0)` THEN + ABBREV_TAC `tail_len:int64 = word_and len (word 0xf)` THEN + ABBREV_TAC `num_5blocks = (word (val (len_full_blocks:int64) DIV 0x50)):int64` THEN + + SUBGOAL_THEN `val (len_full_blocks:int64) = 0x40` ASSUME_TAC THENL + [ EXPAND_TAC "len_full_blocks" THEN + REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `val (len:int64) DIV 16 = 4` SUBST1_TAC THENL + [ MATCH_MP_TAC(MESON[LE_ANTISYM] `m <= n /\ n <= m ==> m = n`) THEN + CONJ_TAC THENL [ ASM_ARITH_TAC; ASM_ARITH_TAC]; + ALL_TAC] THEN + ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `val (num_5blocks:int64) = 0` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks" THEN + UNDISCH_TAC `val (len_full_blocks:int64) = 0x40` THEN + SIMP_TAC[] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[VAL_WORD_0]; ALL_TAC ] THEN + + (* Prove property until start of cipher stealing. *) + ENSURES_SEQUENCE_TAC `pc + 0x9e0` + `\s. + read X0 s = word_add ptxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + read X1 s = word_add ctxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + read X3 s = key1_p /\ + read X21 s = tail_len /\ + read Q6 s = calculate_tweak (acc_blocks num_5blocks len_full_blocks T) iv key2_lst /\ + read X19 s = word 0x87 /\ + read Q16 s = k1_0 /\ read Q17 s = k1_1 /\ read Q12 s = k1_2 /\ read Q13 s = k1_3 /\ + read Q14 s = k1_4 /\ read Q15 s = k1_5 /\ read Q4 s = k1_6 /\ read Q5 s = k1_7 /\ + read Q18 s = k1_8 /\ read Q19 s = k1_9 /\ read Q20 s = k1_10 /\ read Q21 s = k1_11 /\ + read Q22 s = k1_12 /\ read Q23 s = k1_13 /\ read Q7 s = k1_14 /\ + byte_list_at pt_in ptxt_p len s /\ + byte_list_at (aes256_xts_encrypt pt_in (acc_len num_5blocks len_full_blocks) iv key1_lst key2_lst) + ctxt_p (word (acc_len num_5blocks len_full_blocks)) s` THEN + CONJ_TAC THENL + [ + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes128 ctxt_p; + memory :> bytes128 (word_add ctxt_p (word 0x10)); + memory :> bytes128 (word_add ctxt_p (word 0x20)); + memory :> bytes128 (word_add ctxt_p (word 0x30))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC] THEN + + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (1--2) THEN + + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (len:int64) (word 0x10)) < &0x0 + <=> ~(ival (len:int64) - &0x10 = ival (word_sub (len:int64) (word 0x10)))` MP_TAC THENL + [ MP_TAC (BITBLAST_RULE (* put in tips doc. Q: When to use it vs. ARITH_RULE? *) + `~(val (len:int64) < 0x40) ==> val len < 0x50 ==> + ival (word_sub len (word 0x10)) >= &0x0`) THEN + ASM_REWRITE_TAC[] THEN + MP_TAC (BITBLAST_RULE + `~(val (len:int64) < 0x40) ==> val len < 0x50 ==> + ival (len:int64) - &0x10 = ival (word_sub len (word 0x10))`) THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; + ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN DISCH_TAC THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + MP_TAC (SPECL [`ptxt_p:int64`; `len:int64`; `pt_in:byte list`; `s2:armstate`] READ_LT_5BLOCK) THEN + ASM_SIMP_TAC[] THEN REPEAT STRIP_TAC THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (3--65) THEN + (* Prove Q6 stores initial tweak *) + FIRST_X_ASSUM(MP_TAC o SPEC `(calculate_tweak 0 iv key2_lst)` + o MATCH_MP (MESON[] `read Q6 s = a ==> !a'. a = a' ==> read Q6 s = a'`)) THEN + ANTS_TAC THENL + [ REWRITE_TAC[CONJUNCT1 calculate_tweak; xts_init_tweak] THEN + EXPAND_TAC "key2_lst" THEN AESENC_TAC; DISCH_TAC] THEN + + (* Simulating until branching into tail4x *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (66--87) THEN + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (88--95) THEN + TWEAK_TAC `Q9:(armstate,int128)component` `2:num` `1:num` THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (96--103) THEN + TWEAK_TAC `Q10:(armstate,int128)component` `3:num` `2:num` THEN + (* Simulate AES-XTS encryption of block in Q0, Q1, Q24, Q25 *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (104--227) THEN + XTSENC_TAC `Q0:(armstate,int128)component` `0` `0` THEN + XTSENC_TAC `Q1:(armstate,int128)component` `0x10` `1` THEN + XTSENC_TAC `Q24:(armstate,int128)component` `0x20` `2` THEN + XTSENC_TAC `Q25:(armstate,int128)component` `0x30` `3` THEN + (* until b .Lxts_enc_done = arm_B (word xxx) *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (228--238) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `4:num` `3:num` THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + + REPEAT CONJ_TAC THENL + [ + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_len] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[acc_blocks] THEN CONV_TAC NUM_REDUCE_CONV; + + ASM_REWRITE_TAC[acc_len] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + MP_TAC (SPECL [`0x40`; `ctxt_p:int64`; `(aes256_xts_encrypt pt_in 0x40 iv key1_lst key2_lst):byte list`; + `s238:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL [ + MP_TAC (SPECL [`4`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + IMP_REWRITE_TAC[READ_BYTES_EQ_READ_BYTE128_4BLOCKS_ENC] + ] + ; ALL_TAC] THEN + + (* Reuse the cipher stealing proof *) + MP_TAC CIPHER_STEALING_ENC_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[byte_list_at; PAIRWISE; ALL; MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + ASM_SIMP_TAC[] THEN + ASM_ARITH_TAC +);; + + +(* +void aes_xts_encrypt(const uint8_t *in, uint8_t *out, size_t length, + const s2n_bignum_AES_KEY *key1, const s2n_bignum_AES_KEY *key2, + const uint8_t iv[16]) +*) +let AES256_XTS_ENCRYPT_CORRECT = prove( + `!ptxt_p ctxt_p len key1_p key2_p iv_p + pt_in iv + k1_0 k1_1 k1_2 k1_3 k1_4 k1_5 k1_6 k1_7 k1_8 k1_9 k1_10 k1_11 k1_12 k1_13 k1_14 + k2_0 k2_1 k2_2 k2_3 k2_4 k2_5 k2_6 k2_7 k2_8 k2_9 k2_10 k2_11 k2_12 k2_13 k2_14 + pc. + PAIRWISE nonoverlapping + [(word pc, LENGTH aes256_xts_encrypt_mc); + (ptxt_p, val len); + (ctxt_p, val len); + (key1_p, 244); + (key2_p, 244)] /\ + val len >= 16 /\ val len <= 2 EXP 24 /\ LENGTH pt_in = val len + ==> ensures arm + // precondition + (\s. aligned_bytes_loaded s (word pc) aes256_xts_encrypt_mc /\ + read PC s = word (pc + 28) /\ + C_ARGUMENTS [ptxt_p; ctxt_p; len; key1_p; key2_p; iv_p] s /\ + byte_list_at pt_in ptxt_p len s /\ + read(memory :> bytes128 iv_p) s = iv /\ + set_key_schedule s key1_p k1_0 k1_1 k1_2 k1_3 k1_4 k1_5 k1_6 k1_7 k1_8 k1_9 k1_10 k1_11 k1_12 k1_13 k1_14 /\ + set_key_schedule s key2_p k2_0 k2_1 k2_2 k2_3 k2_4 k2_5 k2_6 k2_7 k2_8 k2_9 k2_10 k2_11 k2_12 k2_13 k2_14 + ) + // postcondition + (\s. read PC s = word (pc + 0xa8c) /\ //LENGTH aes256_xts_encrypt_mc - 8*4 = 0xaac - 0x8 * 0x4 + byte_list_at (aes256_xts_encrypt pt_in (val len) iv + [k1_0; k1_1; k1_2; k1_3; k1_4; k1_5; k1_6; k1_7; k1_8; k1_9; k1_10; k1_11; k1_12; k1_13; k1_14] + [k2_0; k2_1; k2_2; k2_3; k2_4; k2_5; k2_6; k2_7; k2_8; k2_9; k2_10; k2_11; k2_12; k2_13; k2_14]) + ctxt_p len s + ) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes(ctxt_p, val len)])`, + + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; byte_list_at; C_ARGUMENTS; SOME_FLAGS; PAIRWISE; ALL; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + REPEAT STRIP_TAC THEN + + (* Break len into full blocks and tail *) + SUBGOAL_THEN `word_add (word_and len (word 0xf)) + (word_and len (word 0xfffffffffffffff0)) = len:int64` ASSUME_TAC THENL + [REWRITE_TAC[word_split_lemma]; ALL_TAC] THEN + ABBREV_TAC `len_full_blocks:int64 = word_and len (word 0xfffffffffffffff0)` THEN + ABBREV_TAC `num_5blocks = (word (val (len_full_blocks:int64) DIV 0x50)):int64` THEN + ABBREV_TAC `tail_len:int64 = word_and len (word 0xf)` THEN + + ABBREV_TAC `key1_lst:int128 list = [k1_0; k1_1; k1_2; k1_3; k1_4; k1_5; k1_6; k1_7; k1_8; k1_9; k1_10; k1_11; k1_12; k1_13; k1_14]` THEN + ABBREV_TAC `key2_lst:int128 list = [k2_0; k2_1; k2_2; k2_3; k2_4; k2_5; k2_6; k2_7; k2_8; k2_9; k2_10; k2_11; k2_12; k2_13; k2_14]` THEN + + (* Case splits on length: + len < 16 -- error case + len < 32 -- one block, or one block and a tail + len < 48 -- two blocks, or two blocks and a tail + len < 64 -- three blocks, or three blocks and a tail + len < 80 -- four blocks, or four blocks and a tail + len >= 80 -- five blocks and up => at least one big loop iteration + + Note: for encrypt, in cipherstealing, the tail is directly processed since the last + tweak is available from prior calculations. The order of the tweaks is not flipped, + as in the case of decrypt, between the last block and the tail. + *) + ASM_CASES_TAC `val (len:int64) < 0x50` THENL [ + ASM_CASES_TAC `val (len:int64) < 0x20` THENL + [ + MP_TAC AES_XTS_ENCRYPT_LT_2BLOCK_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; byte_list_at; C_ARGUMENTS; SOME_FLAGS; PAIRWISE; ALL; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + ASM_SIMP_TAC[] ; ALL_TAC ] THEN + + ASM_CASES_TAC `val (len:int64) < 0x30` THENL + [ + MP_TAC AES_XTS_ENCRYPT_LT_3BLOCK_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; byte_list_at; C_ARGUMENTS; SOME_FLAGS; PAIRWISE; ALL; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + ASM_SIMP_TAC[] ; ALL_TAC ] THEN + + ASM_CASES_TAC `val (len:int64) < 0x40` THENL + [ + MP_TAC AES_XTS_ENCRYPT_LT_4BLOCK_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; byte_list_at; C_ARGUMENTS; SOME_FLAGS; PAIRWISE; ALL; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + ASM_SIMP_TAC[] ; ALL_TAC ] THEN + + ASM_CASES_TAC `val (len:int64) < 0x50` THENL + [ + MP_TAC AES_XTS_ENCRYPT_LT_5BLOCK_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[set_key_schedule; byte_list_at; C_ARGUMENTS; SOME_FLAGS; PAIRWISE; ALL; + MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + ASM_SIMP_TAC[] ; ALL_TAC ] THEN + + ASM_ARITH_TAC + ; ALL_TAC] THEN + + (* Prove the bounds on len_full_blocks, num_5blocks and len and their relationships *) + SUBGOAL_THEN `~(val (len_full_blocks:int64) < 0x50)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(val (len:int64) < 0x50)` THEN + UNDISCH_TAC `word_and len (word 0xfffffffffffffff0) = (len_full_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `len_full_blocks:int64`] LEN_FULL_BLOCKS_LO_BOUND_THM) THEN + SIMP_TAC[]; ALL_TAC] THEN + + SUBGOAL_THEN `val (len_full_blocks:int64) <= 0x2 EXP 24` ASSUME_TAC THENL + [ UNDISCH_TAC `val (len:int64) <= 0x2 EXP 24` THEN + UNDISCH_TAC `word_and len (word 0xfffffffffffffff0) = (len_full_blocks:int64)` THEN + MP_TAC (SPECL [`len:int64`; `len_full_blocks:int64`] NUM_BLOCKS_HI_BOUND_THM) THEN + SIMP_TAC[]; ALL_TAC] THEN + + SUBGOAL_THEN `0 < val (num_5blocks:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `word (val (len_full_blocks:int64) DIV 0x50) = (num_5blocks:int64)` THEN + UNDISCH_TAC `~(val (len_full_blocks:int64) < 0x50)` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 0x2 EXP 24` THEN + MP_TAC (SPECL [`len_full_blocks:int64`; `num_5blocks:int64`] + NUM_5BLOCKS_LO_BOUND_THM) THEN SIMP_TAC[] + ; ALL_TAC] THEN + + SUBGOAL_THEN `val (len_full_blocks:int64) <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "len_full_blocks" THEN SIMP_TAC[NUM_BLOCKS_LT_LEN_THM]; ALL_TAC] THEN + + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks" THEN + REWRITE_TAC [VAL_WORD; DIMINDEX_64] THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + + (* Verify properties of the program until the beginning of the loop. + This saves work in the second subgoal of the loop invariant and brings it here. + Up to the loop: + - First 5 tweaks are calculated from the iv + - X2 contains len_full_blocks + - X8 contains num_5blocks + - key1 schedule is loaded in Q registers + - X9 and X10 are not needed to be spelled out for the proof itself, but to be + kept in the assumption list after the proof *) + ENSURES_SEQUENCE_TAC + `pc + 0x140` + `\s. + read X0 s = ptxt_p /\ + read X1 s = ctxt_p /\ + read X2 s = len_full_blocks /\ + read X3 s = key1_p /\ + read X21 s = tail_len /\ + read X8 s = num_5blocks /\ + read X9 s = word_zx (calculate_tweak 4 iv key2_lst) /\ + read X10 s = word_subword (calculate_tweak 4 iv key2_lst) (64,64) /\ + read Q6 s = calculate_tweak 0 iv key2_lst /\ + read Q8 s = calculate_tweak 1 iv key2_lst /\ + read Q9 s = calculate_tweak 2 iv key2_lst /\ + read Q10 s = calculate_tweak 3 iv key2_lst /\ + read Q11 s = calculate_tweak 4 iv key2_lst /\ + read X19 s = word 0x87 /\ + read Q16 s = k1_0 /\ read Q17 s = k1_1 /\ read Q12 s = k1_2 /\ read Q13 s = k1_3 /\ + read Q14 s = k1_4 /\ read Q15 s = k1_5 /\ read Q4 s = k1_6 /\ read Q5 s = k1_7 /\ + read Q18 s = k1_8 /\ read Q19 s = k1_9 /\ read Q20 s = k1_10 /\ read Q21 s = k1_11 /\ + read Q22 s = k1_12 /\ read Q23 s = k1_13 /\ read Q7 s = k1_14 /\ + byte_list_at pt_in ptxt_p len s /\ + byte_list_at (aes256_xts_encrypt pt_in 0 iv key1_lst key2_lst) + ctxt_p (word 0) s + ` THEN + CONJ_TAC THENL + [ + (* ===> Symbolic Simulation: Start symbolic simulation*) + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (1--2) THEN + + (* Discharge if condition *) + SUBGOAL_THEN + `ival (word_sub (len:int64) (word 0x10)) < &0x0 + <=> ~(ival (len:int64) - &0x10 = ival (word_sub (len:int64) (word 0x10)))` MP_TAC THENL + [ MP_TAC (BITBLAST_RULE + `val (len:int64) >= 0x10 ==> val len <= 2 EXP 0x18 ==> + ival (word_sub len (word 0x10)) >= &0x0`) THEN + ASM_REWRITE_TAC[] THEN + MP_TAC (BITBLAST_RULE + `val (len:int64) >= 0x10 ==> val len <= 2 EXP 0x18 ==> + ival (len:int64) - &0x10 = ival (word_sub len (word 0x10))`) THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC;(* works on the goal; that's why we bring the assumptions we want as antecedants of the goal *) + ALL_TAC + ] THEN + ASM_REWRITE_TAC[] THEN + DISCH_TAC THEN POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + (* Try DISCH_THEN(RULE_ASSUM_TAC o REWRITE_RULE o CONJUNCTS) *) + + (* ===> Symbolic Simulation: Symbolic execution for initialization of tweak *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (3--65) THEN + (* Prove Q6 stores initial tweak *) + FIRST_X_ASSUM(MP_TAC o SPEC `(calculate_tweak 0 iv key2_lst)` + o MATCH_MP (MESON[] `read Q6 s = a ==> !a'. a = a' ==> read Q6 s = a'`)) THEN + ANTS_TAC THENL + [REWRITE_TAC[CONJUNCT1 calculate_tweak; xts_init_tweak] THEN + EXPAND_TAC "key2_lst" THEN AESENC_TAC; DISCH_TAC] THEN + + (* ===> Symbolic Simulation: Symbolic simulating untill next branch: + - iv for second block + - load key schedule *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (66--77) THEN + (* Branching on x2 *) + (* Eliminate 1 block case *) + SUBGOAL_THEN `~(val (len_full_blocks:int64) < 0x20)` MP_TAC THENL + [ UNDISCH_TAC `~(val (len_full_blocks:int64) < 0x50)` THEN ARITH_TAC; + DISCH_THEN(RULE_ASSUM_TAC o REWRITE_RULE o CONJUNCTS)] THEN + + (* Prove x9, x10 store lower and upper halves of tweak 1 and Q8 stores the full tweak 1 *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (78--87) THEN + TWEAK_TAC `Q8:(armstate,int128)component` `1:num` `0:num` THEN + + (* Eliminate 2 blocks case *) + SUBGOAL_THEN `~(val (len_full_blocks:int64) < 0x30)` MP_TAC THENL + [ UNDISCH_TAC `~(val (len_full_blocks:int64) < 0x50)` THEN ARITH_TAC; + DISCH_THEN(RULE_ASSUM_TAC o REWRITE_RULE o CONJUNCTS)] THEN + (* prove Q9 stores tweak of 3rd block (index 2) *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (88--95) THEN (* TODO: How is the last parameter in TWEAK_TAC `0` in the upcoming ones? *) + TWEAK_TAC `Q9:(armstate,int128)component` `2:num` `0:num` THEN + (* Eliminate 3 blocks case *) + SUBGOAL_THEN `~(val (len_full_blocks:int64) < 0x40)` MP_TAC THENL + [ UNDISCH_TAC `~(val (len_full_blocks:int64) < 0x50)` THEN ARITH_TAC; + DISCH_THEN(RULE_ASSUM_TAC o REWRITE_RULE o CONJUNCTS)] THEN + (* prove Q10 stores tweak of 4th block (index 3) *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (96--103) THEN + TWEAK_TAC `Q10:(armstate,int128)component` `3:num` `0:num` THEN + (* Eliminate 4 blocks case, proven by the assumption ~(len_full_blocks < 0x50)*) + (* prove Q11 stores tweak of 5th block (index 4) *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (105--110) THEN + TWEAK_TAC `Q11:(armstate,int128)component` `4:num` `0:num` THEN + + (* Prove the optimized udiv is basically udiv *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (111--114) THEN + SUBGOAL_THEN `word_ushr + ((word ((val (len_full_blocks:int64) * 0xcccccccccccccccd) DIV 0x2 EXP 0x40)):int64) + 0x6 = + word ((val len_full_blocks) DIV 0x50)` ASSUME_TAC THENL + [ MP_TAC (BITBLAST_RULE `val (len_full_blocks:int64) < 2 EXP 64`) THEN + REWRITE_TAC[word_ushr] THEN + MP_TAC (SPECL [`val (len_full_blocks:int64)`] UDIV_OPT_THM) THEN SIMP_TAC[] + ; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ ASM_REWRITE_TAC[byte_list_at]; + REWRITE_TAC[aes256_xts_encrypt] THEN + CONV_TAC (DEPTH_CONV NUM_RED_CONV) THEN + ASM_REWRITE_TAC[byte_list_at] THEN + REWRITE_TAC[VAL_WORD_0] THEN ARITH_TAC ] + ; ALL_TAC + ] THEN + + (* Prove property until right before cipher stealing *) + ENSURES_SEQUENCE_TAC `pc + 0x9e0` + `\s. + read X0 s = word_add ptxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + read X1 s = word_add ctxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + read X3 s = key1_p /\ + read X21 s = tail_len /\ + read Q6 s = calculate_tweak (acc_blocks num_5blocks len_full_blocks T) iv key2_lst /\ + read X19 s = word 0x87 /\ + read Q16 s = k1_0 /\ read Q17 s = k1_1 /\ read Q12 s = k1_2 /\ read Q13 s = k1_3 /\ + read Q14 s = k1_4 /\ read Q15 s = k1_5 /\ read Q4 s = k1_6 /\ read Q5 s = k1_7 /\ + read Q18 s = k1_8 /\ read Q19 s = k1_9 /\ read Q20 s = k1_10 /\ read Q21 s = k1_11 /\ + read Q22 s = k1_12 /\ read Q23 s = k1_13 /\ read Q7 s = k1_14 /\ + byte_list_at pt_in ptxt_p len s /\ + byte_list_at (aes256_xts_encrypt pt_in (acc_len num_5blocks len_full_blocks) iv key1_lst key2_lst) + ctxt_p (word (acc_len num_5blocks len_full_blocks)) s` THEN + CONJ_TAC THENL + [ + (* Loop invariant of main loop *) + ENSURES_WHILE_PAUP_TAC + `0` (* counter begin number *) + `val (num_5blocks:int64)` (* counter end number *) + `pc + 0x140` (* loop body start PC *) + `pc + 0x430` (* loop backedge branch PC *) + `\i s. + // loop invariant at the end of the loop iteration + (read X0 s = word_add ptxt_p (word_mul (word 0x50) (word i)) /\ + read X1 s = word_add ctxt_p (word_mul (word 0x50) (word i)) /\ + read X21 s = tail_len /\ + read X3 s = key1_p /\ + read X2 s = word_sub len_full_blocks (word_mul (word 0x50) (word i)) /\ + read X8 s = word_sub num_5blocks (word i) /\ + read X19 s = word 0x87 /\ + read X9 s = word_zx (calculate_tweak (i * 5 + 4) iv key2_lst) /\ + read X10 s = word_subword (calculate_tweak (i * 5 + 4) iv key2_lst) (64,64) /\ + read Q6 s = calculate_tweak (i * 5) iv key2_lst /\ + read Q8 s = calculate_tweak (i * 5 + 1) iv key2_lst /\ + read Q9 s = calculate_tweak (i * 5 + 2) iv key2_lst /\ + read Q10 s = calculate_tweak (i * 5 + 3) iv key2_lst /\ + read Q11 s = calculate_tweak (i * 5 + 4) iv key2_lst /\ + read Q16 s = k1_0 /\ read Q17 s = k1_1 /\ read Q12 s = k1_2 /\ read Q13 s = k1_3 /\ + read Q14 s = k1_4 /\ read Q15 s = k1_5 /\ read Q4 s = k1_6 /\ read Q5 s = k1_7 /\ + read Q18 s = k1_8 /\ read Q19 s = k1_9 /\ read Q20 s = k1_10 /\ read Q21 s = k1_11 /\ + read Q22 s = k1_12 /\ read Q23 s = k1_13 /\ read Q7 s = k1_14 /\ + byte_list_at pt_in ptxt_p len s /\ + byte_list_at (aes256_xts_encrypt pt_in (i * 0x50) iv key1_lst key2_lst) + ctxt_p (word (i * 0x50)) s) /\ + // loop backedge condition + (read ZF s <=> i = val (num_5blocks:int64))` THEN + ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL + [ + (* Subgoal 1. + 0 < `val (num_5blocks:int64)` + automatically discharged by asm *) + + (* Subgoal 2. Invariant holds before entering the loop *) + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ WORD_ARITH_TAC; WORD_ARITH_TAC; WORD_ARITH_TAC; WORD_ARITH_TAC; + CONV_TAC NUM_REDUCE_CONV; + CONV_TAC NUM_REDUCE_CONV; + CONV_TAC NUM_REDUCE_CONV; + CONV_TAC NUM_REDUCE_CONV; + CONV_TAC NUM_REDUCE_CONV; + CONV_TAC NUM_REDUCE_CONV; + CONV_TAC NUM_REDUCE_CONV; + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[VAL_WORD_0] THEN ARITH_TAC ]; + + (* Subgoal 3: inductive step in the loop body *) + REPEAT STRIP_TAC THEN + + SUBGOAL_THEN `i * 0x50 + 0x50 <= val (len:int64)` ASSUME_TAC THENL + [ + SUBGOAL_THEN `i + 1 <= val (num_5blocks:int64)` MP_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC ] THEN + SUBGOAL_THEN `val (len_full_blocks:int64) <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "len_full_blocks" THEN SIMP_TAC[NUM_BLOCKS_LT_LEN_THM]; ALL_TAC ] THEN + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 <= val (len:int64)` ASSUME_TAC THENL + [ EXPAND_TAC "num_5blocks" THEN + REWRITE_TAC [VAL_WORD; DIMINDEX_64] THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= val (len:int64)` THEN + ARITH_TAC; ALL_TAC ] THEN + SUBGOAL_THEN `(i + 1) * 0x50 <= val (len:int64)` MP_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC ] THEN + ARITH_TAC; ALL_TAC + ] THEN + + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + MAYCHANGE [memory :> bytes128 (word_add ctxt_p (word (0x50 * i))); + memory :> bytes128 (word_add ctxt_p (word (0x50 * i + 0x10))); + memory :> bytes128 (word_add ctxt_p (word (0x50 * i + 0x20))); + memory :> bytes128 (word_add ctxt_p (word (0x50 * i + 0x30))); + memory :> bytes128 (word_add ctxt_p (word (0x50 * i + 0x40)))]` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL[ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + (* see https://hol-light.zulipchat.com/#narrow/channel/474190-s2n-bignum/topic/.E2.9C.94.20SUBSUMED_MAYCHANGE.20proof/near/541307474 *) + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; ALL_TAC + ] THEN + + (* ===> Symbolic Simulation: Start symbolic simulation*) + ASM_REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + + (* List values for ptxt_p + [0 .. 0x40] *) + MP_TAC (SPECL [`ptxt_p:int64`; `i:num`; `len:int64`; `pt_in:byte list`; `s0:armstate`] READ_BL_LEMMA) THEN + ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN + (* Prove Q0, Q1, Q24, Q25, Q26 stores correct plaintext *) + (* and prove Q6, Q8, Q9, Q10, Q11 stores correct tweak: *) + (* Run simulation until after every ciphertext block and new tweak are calculated + and prove they're correct in their registers *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (1--151) THEN + XTSENC_TAC `Q0:(armstate,int128)component` `i * 0x50` `i * 0x5` THEN + TWEAK_TAC `Q6:(armstate,int128)component` `i * 5 + 5` `i * 5 + 4` THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (152--159) THEN + XTSENC_TAC `Q1:(armstate,int128)component` `i * 0x50 + 0x10` `i * 0x5 + 0x1` THEN + TWEAK_TAC `Q8:(armstate,int128)component` `i * 5 + 6` `i * 5 + 5` THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (160--167) THEN + XTSENC_TAC `Q24:(armstate,int128)component` `i * 0x50 + 0x20` `i * 0x5 + 0x2` THEN + TWEAK_TAC `Q9:(armstate,int128)component` `i * 5 + 7` `i * 5 + 6` THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (168--175) THEN + XTSENC_TAC `Q25:(armstate,int128)component` `i * 0x50 + 0x30` `i * 0x5 + 0x3` THEN + TWEAK_TAC `Q10:(armstate,int128)component` `i * 5 + 8` `i * 5 + 7` THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (176--183) THEN + XTSENC_TAC `Q26:(armstate,int128)component` `i * 0x50 + 0x40` `i * 0x5 + 0x4` THEN + TWEAK_TAC `Q11:(armstate,int128)component` `i * 5 + 9` `i * 5 + 8` THEN + + (* The following lemmas are for NONSELFMODIFYING_STATE_UPDATE_TAC when store back to ctxt_p, + and for the MAYCHANGE clauses *) + RULE_ASSUM_TAC(REWRITE_RULE + [WORD_RULE `word_mul (word 0x50) (word i):int64 = word(0x50 * i)`]) THEN + + (* + 38 [`forall i'. + i' < val (word (i * 0x50)). ====> becomes 0x50 * i + ==> read (memory :> bytes8 (word_add ctxt_p (word i'))) s183 = + EL i' + (aes256_xts_encrypt pt_in (i * 0x50) iv key1_lst key2_lst)`] + 39 [`forall i'. + i' < val len + ==> read (memory :> bytes8 (word_add ptxt_p (word i'))) s183 = + EL i' pt_in`] + *) + (* Rewrite to help reasoning about nonoverlapping + so that the universally quantified assumption stays. + See: https://hol-light.zulipchat.com/#narrow/channel/474190-s2n-bignum/topic/.E2.9C.94.20Symbolic.20simulation.20removed.20assumption/with/541554894 *) + SUBGOAL_THEN `val ((word (i * 0x50)):int64) = 0x50 * i` MP_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN ASM_ARITH_TAC; ALL_TAC] THEN + DISCH_THEN(RULE_ASSUM_TAC o REWRITE_RULE o CONJUNCTS) THEN + + (* Simulate until end of loop *) + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (184--188) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + (* + val it : goalstack = 13 subgoals (16 total) + +`word_add (word_add ptxt_p (word (0x50 * i))) (word 0x50) = + word_add ptxt_p (word_mul (word 0x50) (word (i + 0x1))) /\ + word_add (word_add ctxt_p (word (0x50 * i))) (word 0x50) = + word_add ctxt_p (word_mul (word 0x50) (word (i + 0x1))) /\ + word_sub (word_sub len_full_blocks (word (0x50 * i))) (word 0x50) = + word_sub len_full_blocks (word_mul (word 0x50) (word (i + 0x1))) /\ + word_sub (word_sub num_5blocks (word i)) (word 0x1) = + word_sub num_5blocks (word (i + 0x1)) /\ + word_zx (calculate_tweak (i * 0x5 + 0x9) iv key2_lst) = + word_zx (calculate_tweak ((i + 0x1) * 0x5 + 0x4) iv key2_lst) /\ + word_subword (calculate_tweak (i * 0x5 + 0x9) iv key2_lst) (0x40,0x40) = + word_subword (calculate_tweak ((i + 0x1) * 0x5 + 0x4) iv key2_lst) + (0x40,0x40) /\ + calculate_tweak (i * 0x5 + 0x5) iv key2_lst = + calculate_tweak ((i + 0x1) * 0x5) iv key2_lst /\ + calculate_tweak (i * 0x5 + 0x6) iv key2_lst = + calculate_tweak ((i + 0x1) * 0x5 + 0x1) iv key2_lst /\ + calculate_tweak (i * 0x5 + 0x7) iv key2_lst = + calculate_tweak ((i + 0x1) * 0x5 + 0x2) iv key2_lst /\ + calculate_tweak (i * 0x5 + 0x8) iv key2_lst = + calculate_tweak ((i + 0x1) * 0x5 + 0x3) iv key2_lst /\ + calculate_tweak (i * 0x5 + 0x9) iv key2_lst = + calculate_tweak ((i + 0x1) * 0x5 + 0x4) iv key2_lst /\ + (forall i'. + i' < val (word ((i + 0x1) * 0x50)) + ==> read (memory :> bytes8 (word_add ctxt_p (word i'))) s188 = + EL i' + (aes256_xts_encrypt pt_in ((i + 0x1) * 0x50) iv key1_lst key2_lst)) /\ + (val (word_sub (word_sub num_5blocks (word i)) (word 0x1)) = 0x0 <=> + i + 0x1 = val num_5blocks)` + *) + [ REWRITE_TAC[WORD_RULE `word_mul (word 0x50) (word (i + 1)):int64 = word_add (word(0x50 * i)) (word 0x50)`] THEN + REWRITE_TAC[WORD_ADD_ASSOC]; + REWRITE_TAC[WORD_RULE `word_mul (word 0x50) (word (i + 1)):int64 = word_add (word(0x50 * i)) (word 0x50)`] THEN + REWRITE_TAC[WORD_ADD_ASSOC]; + REWRITE_TAC[WORD_RULE `word_mul (word 0x50) (word (i + 1)):int64 = word_add (word(0x50 * i)) (word 0x50)`] THEN + CONV_TAC WORD_RULE; + CONV_TAC WORD_RULE; + REWRITE_TAC[WORD_RULE `(i + 0x1) * 0x5 + 0x4 = i * 0x5 + 0x9`]; + REWRITE_TAC[WORD_RULE `(i + 0x1) * 0x5 + 0x4 = i * 0x5 + 0x9`]; + REWRITE_TAC[WORD_RULE `(i + 0x1) * 0x5 = i * 0x5 + 0x5`]; + REWRITE_TAC[WORD_RULE `(i + 0x1) * 0x5 + 0x1 = i * 0x5 + 0x6`]; + REWRITE_TAC[WORD_RULE `(i + 0x1) * 0x5 + 0x2 = i * 0x5 + 0x7`]; + REWRITE_TAC[WORD_RULE `(i + 0x1) * 0x5 + 0x3 = i * 0x5 + 0x8`]; + REWRITE_TAC[WORD_RULE `(i + 0x1) * 0x5 + 0x4 = i * 0x5 + 0x9`]; + + (* The following is the main proof for inductive step *) + REWRITE_TAC[ARITH_RULE `(i + 0x1) * 0x50 = 0x50 * i + 0x50`] THEN + SUBGOAL_THEN `val ((word (0x50 * i + 0x50)):int64) = 0x50 * i + 0x50` ASSUME_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `i * 0x50 + 0x50 <= val (len:int64)` THEN + UNDISCH_TAC `val (len:int64) <= 2 EXP 24` THEN + ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + + (* Remove quantifier over reading one byte at a time, i'*) + UNDISCH_TAC + `forall i'. + i' < 0x50 * i + ==> read (memory :> bytes8 (word_add ctxt_p (word i'))) s188 = + EL i' (aes256_xts_encrypt pt_in (i * 0x50) iv key1_lst key2_lst)` THEN + MP_TAC (SPECL [`0x50 * i + 0x50:num`; `ctxt_p:int64`; + `(aes256_xts_encrypt pt_in (0x50 * i + 0x50) iv key1_lst key2_lst):byte list`; + `s188:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x50 = 0x10 * (5 * i + 5)`; + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + MP_TAC (SPECL [`0x50 * i:num`; `ctxt_p:int64`; + `(aes256_xts_encrypt pt_in (i * 0x50) iv key1_lst key2_lst):byte list`; + `s188:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `i * 0x50 = 0x10 * 5 * i`; + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + DISCH_TAC THEN + + (* Prove one block equivalence and reduce proving the following: + `read (memory :> bytes (ctxt_p,0x50 * i + 0x50)) s188 = + num_of_bytelist + (aes256_xts_encrypt pt_in (0x50 * i + 0x50) iv key1_lst key2_lst)` + to: + `read (memory :> bytes (ctxt_p, 0x50 * i + 0x40)) s188 = + num_of_bytelist + (aes256_xts_encrypt pt_in (0x50 * i + 0x40) iv key1_lst key2_lst)` *) + IMP_REWRITE_TAC[ARITH_RULE `0x50 * i + 0x50 = (0x50 * i + 0x40) + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `(aes256_xts_encrypt pt_in (0x50 * i + 0x50) iv key1_lst key2_lst)` THEN + REPEAT CONJ_TAC THENL [ + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x40) + 0x10 = 0x50 * i + 0x50`]; + + MP_TAC (SPECL [`0x5 * i + 0x5:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN (* DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] *) + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x50 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * i + 0x50) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 80 = 16 * (5 * i + 5)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x50) DIV 0x10 = 0x5 * i + 0x5`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x5 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x5) - 0x2 = 0x5 * i + 0x3`; + ARITH_RULE `(0x5 * i + 0x5) - 0x1 = 0x5 * i + 0x4`] THEN + + MP_TAC (SPECL [`0`;`5 * i + 3:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i + 3 < 0)`; + ARITH_RULE `((0x5 * i + 0x3) - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x40`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * i + 4:num`; `0x0:num`; `pt_in:byte list`; `iv:int128`; + `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 + 0x40 = (i * 0x5 + 0x4) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x40 = 0x10 * (5 * i + 4)`; + ARITH_RULE `0x50 * i + 0x50 = 0x10 * (5 * i + 4) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + (** Reduce the goal to contain 0x50 * i + 0x30 **) + IMP_REWRITE_TAC[ARITH_RULE `0x50 * i + 0x40 = (0x50 * i + 0x30) + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `(aes256_xts_encrypt pt_in (0x50 * i + 0x40) iv key1_lst key2_lst)` THEN + REPEAT CONJ_TAC THENL [ + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x30) + 0x10 = 0x50 * i + 0x40`] THEN + MP_TAC (SPECL [`0x5 * i + 0x4:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES]; + + MP_TAC (SPECL [`0x5 * i + 0x4:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x40 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * i + 0x40) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 64 = 16 * (5 * i + 4)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x40) DIV 0x10 = 0x5 * i + 0x4`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x4 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x4) - 0x2 = 0x5 * i + 0x2`; + ARITH_RULE `(0x5 * i + 0x4) - 0x1 = 0x5 * i + 0x3`] THEN + + MP_TAC (SPECL [`0`;`5 * i + 2:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i + 2 < 0)`; + ARITH_RULE `((0x5 * i + 0x2) - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x30`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * i + 3:num`; `0x0:num`; `pt_in:byte list`; `iv:int128`; + `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 + 0x30 = (i * 0x5 + 0x3) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x30 = 0x10 * (5 * i + 3)`; + ARITH_RULE `0x50 * i + 0x40 = 0x10 * (5 * i + 3) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + (** Reduce the goal to contain 0x50 * i + 0x20 **) + IMP_REWRITE_TAC[ARITH_RULE `0x50 * i + 0x30 = (0x50 * i + 0x20) + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `(aes256_xts_encrypt pt_in (0x50 * i + 0x30) iv key1_lst key2_lst)` THEN + REPEAT CONJ_TAC THENL [ + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x20) + 0x10 = 0x50 * i + 0x30`] THEN + MP_TAC (SPECL [`0x5 * i + 0x3:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES]; + + MP_TAC (SPECL [`0x5 * i + 0x3:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + DISCH_TAC THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x30 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * i + 0x30) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 48 = 16 * (5 * i + 3)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x30) DIV 0x10 = 0x5 * i + 0x3`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x3 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x3) - 0x2 = 0x5 * i + 0x1`; + ARITH_RULE `(0x5 * i + 0x3) - 0x1 = 0x5 * i + 0x2`] THEN + + MP_TAC (SPECL [`0`;`5 * i + 1:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i + 1 < 0)`; + ARITH_RULE `((0x5 * i + 0x1) - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x20`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * i + 2:num`; `0x0:num`; `pt_in:byte list`; `iv:int128`; + `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 + 0x20 = (i * 0x5 + 0x2) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 2)`; + ARITH_RULE `0x50 * i + 0x30 = 0x10 * (5 * i + 2) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + (** Reduce the goal to contain 0x50 * i + 0x10 **) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = (0x50 * i + 0x10) + 0x10`] THEN + (* Use SPECL to force IMP_REWRITE_TAC to apply once *) + IMP_REWRITE_TAC[(SPECL [`ctxt_p:int64`; `(0x50 * i + 0x10):num`; + `x:byte list`; `s188:armstate`] READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `(aes256_xts_encrypt pt_in (0x50 * i + 0x20) iv key1_lst key2_lst)` THEN + REPEAT CONJ_TAC THENL [ + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x10) + 0x10 = 0x50 * i + 0x20`] THEN + MP_TAC (SPECL [`0x5 * i + 0x2:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES]; + + MP_TAC (SPECL [`0x5 * i + 0x2:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + DISCH_TAC THEN + ASM_REWRITE_TAC[] THEN + ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x20 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * i + 0x20) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 32 = 16 * (5 * i + 2)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x20) DIV 0x10 = 0x5 * i + 0x2`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x2 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x2) - 0x2 = 0x5 * i`; + ARITH_RULE `(0x5 * i + 0x2) - 0x1 = 0x5 * i + 0x1`] THEN + + MP_TAC (SPECL [`0`;`5 * i:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i < 0)`; + ARITH_RULE `((0x5 * i) - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x10`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * i + 1:num`; `0x0:num`; `pt_in:byte list`; `iv:int128`; + `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 + 0x10 = (i * 0x5 + 0x1) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x10 = 0x10 * (5 * i + 1)`; + ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 1) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + (** Reduce the goal to 0x50 * i **) + (* + `read (memory :> bytes (ctxt_p,0x50 * i + 0x10)) s188 = + num_of_bytelist + (aes256_xts_encrypt pt_in (0x50 * i + 0x10) iv key1_lst key2_lst)` + *) + (* Using SPECL with `x` does not yield a correct goal; it contains as one of the conjuctions: + `num_of_bytelist + (SUB_LIST (0x0,0x50 * i + 0x10) + (aes256_xts_encrypt pt_in (i * 0x50) iv key1_lst key2_lst)) = + num_of_bytelist + (aes256_xts_encrypt pt_in (0x50 * i + 0x10) iv key1_lst key2_lst) + *) + IMP_REWRITE_TAC[(SPECL [`ctxt_p:int64`; `(0x50 * i):num`; + `(aes256_xts_encrypt pt_in (0x50 * i + 0x10) iv key1_lst key2_lst):byte list`; `s188:armstate`] + READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `iv:int128` THEN EXISTS_TAC `key1_lst:int128 list` THEN + EXISTS_TAC `key2_lst:int128 list` THEN EXISTS_TAC `pt_in:byte list` THEN + + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * i + 0x1:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES]; + + MP_TAC (SPECL [`0x5 * i + 0x1:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + DISCH_TAC THEN ASM_REWRITE_TAC[] THEN ARITH_TAC; + + (* Establish that one xts decrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x10 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * i + 0x10) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 16 = 16 * (5 * i + 1)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x10) DIV 0x10 = 0x5 * i + 0x1`] THEN + + (* Two cases: i = 0 then execute tail branch, else execute recursion branch *) + COND_CASES_TAC THENL + [ SUBGOAL_THEN `i = 0` SUBST1_TAC THENL + [ UNDISCH_TAC `5 * i + 1 < 2` THEN + UNDISCH_TAC `0 <= i` THEN + ARITH_TAC + ; ALL_TAC] THEN CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [`0:num`; `0x0:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[(ISPECL [`(aes256_xts_encrypt_tail 0x0 0x0 pt_in iv key1_lst key2_lst):byte list`; + `0x10:num`] SUB_LIST_LENGTH_IMPLIES)] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + CONV_TAC NUM_REDUCE_CONV; + + (* i != 0 *) + SIMP_TAC[ARITH_RULE `(0x5 * i + 0x1) - 0x2 = 0x5 * i - 0x1`; + ARITH_RULE `(0x5 * i + 0x1) - 0x1 = 0x5 * i`] THEN + MP_TAC (SPECL [`0`;`5 * i - 1:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SUBGOAL_THEN `~(0x5 * i - 0x1 < 0x0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(0x5 * i + 0x1 < 0x2)` THEN ARITH_TAC; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + IMP_REWRITE_TAC[ARITH_RULE `~(0x5 * i + 0x1 < 0x2) ==> (0x5 * i - 1 - 0x0 + 0x1) * 0x10 = 0x50 * i`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * i:num`; `0x0:num`; `pt_in:byte list`; `iv:int128`; + `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 = (i * 0x5) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`] + ]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `i * 0x50 = 0x50 * i`; + ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + ARITH_RULE `0x50 * i + 0x10 = 0x10 * 5 * i + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] + ]; + + (* 4 goals total from here *) + SUBGOAL_THEN `i + 1 < 2 EXP 64` ASSUME_TAC THENL + [ + UNDISCH_TAC `i < val (num_5blocks:int64)` THEN + EXPAND_TAC "num_5blocks" THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 0x2 EXP 0x18` THEN + REWRITE_TAC [VAL_WORD; DIMINDEX_64] THEN ARITH_TAC; ALL_TAC + ] THEN + EQ_TAC THENL + [ REWRITE_TAC[WORD_RULE `!x:int64 a b. (word_sub (word_sub x a) b) = word_sub x (word_add a b)`] THEN + ASM_SIMP_TAC[WORD_RULE `!a b. a + b < 2 EXP 64 ==> (word_add (word a) (word b)) = word (a + b)`] THEN + REWRITE_TAC[VAL_EQ_0; WORD_SUB_EQ_0] THEN + DISCH_TAC THEN ASM_REWRITE_TAC[] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT]; + REWRITE_TAC[WORD_RULE `!x:int64 a b. (word_sub (word_sub x a) b) = word_sub x (word_add a b)`] THEN + ASM_SIMP_TAC[WORD_RULE `!a b. a + b < 2 EXP 64 ==> (word_add (word a) (word b)) = word (a + b)`] THEN + REWRITE_TAC[VAL_EQ_0; WORD_SUB_EQ_0; WORD_VAL] + ] + ]; (* 3 goals total from here *) + + (** Subgoal 4 of main loop invariant: + prove backedge is taken if i != val num_5blocks **) + REPEAT STRIP_TAC THEN + REWRITE_TAC[byte_list_at] THEN + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (1--1) THEN + SUBGOAL_THEN `~(val (word_sub (num_5blocks:int64) (word i)) = 0x0)` ASSUME_TAC THENL + [ UNDISCH_TAC `i < val (num_5blocks:int64)` THEN WORD_ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_SIMP_TAC[]; (* 2 goals total from here *) + + (** Subgoal 5: Prove the invariant implies post-condition + Backedge instruction is executed here **) + REPEAT STRIP_TAC THEN + REWRITE_TAC[byte_list_at] THEN + SUBST_ALL_TAC (WORD_RULE `(word (val (num_5blocks:int64))):int64 = num_5blocks`) THEN + + MATCH_MP_TAC ENSURES_FRAME_SUBSUMED THEN + EXISTS_TAC `MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI ,, + MAYCHANGE [X19; X20; X21; X22],, + MAYCHANGE [Q8; Q9; Q10; Q11; Q12; Q13; Q14; Q15],, + if val (num_5blocks:int64) * 0x50 + 0x40 = val (len_full_blocks:int64) + then + MAYCHANGE [memory :> bytes128 (word_add ctxt_p (word (0x50 * val (num_5blocks:int64)))); + memory :> bytes128 (word_add ctxt_p (word (0x50 * val num_5blocks + 0x10))); + memory :> bytes128 (word_add ctxt_p (word (0x50 * val num_5blocks + 0x20))); + memory :> bytes128 (word_add ctxt_p (word (0x50 * val num_5blocks + 0x30)))] + else + (if val (num_5blocks:int64) * 0x50 + 0x30 = val (len_full_blocks:int64) + then + MAYCHANGE [memory :> bytes128 (word_add ctxt_p (word (0x50 * val (num_5blocks:int64)))); + memory :> bytes128 (word_add ctxt_p (word (0x50 * val num_5blocks + 0x10))); + memory :> bytes128 (word_add ctxt_p (word (0x50 * val num_5blocks + 0x20)))] + else + (if val (num_5blocks:int64) * 0x50 + 0x20 = val (len_full_blocks:int64) + then + MAYCHANGE [memory :> bytes128 (word_add ctxt_p (word (0x50 * val (num_5blocks:int64)))); + memory :> bytes128 (word_add ctxt_p (word (0x50 * val num_5blocks + 0x10)))] + else + (if val (num_5blocks:int64) * 0x50 + 0x10 = val (len_full_blocks:int64) + then + MAYCHANGE [memory :> bytes128 (word_add ctxt_p (word (0x50 * val (num_5blocks:int64))))] + else + MAYCHANGE []))) + ` THEN + REWRITE_TAC[MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + CONJ_TAC THENL [ + REPEAT (GEN_REWRITE_TAC ONCE_DEPTH_CONV [GSYM SEQ_ASSOC] THEN + MATCH_MP_TAC SUBSUMED_SEQ THEN REWRITE_TAC[SUBSUMED_REFL]) THEN + REPEAT COND_CASES_TAC THENL + [ SUBGOAL_THEN `0x50 * val (num_5blocks:int64) + 0x40 <= val (len:int64)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ABBREV_TAC `val5blocks = val (num_5blocks:int64)` THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; + SUBGOAL_THEN `0x50 * val (num_5blocks:int64) + 0x30 <= val (len:int64)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ABBREV_TAC `val5blocks = val (num_5blocks:int64)` THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; + SUBGOAL_THEN `0x50 * val (num_5blocks:int64) + 0x20 <= val (len:int64)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ABBREV_TAC `val5blocks = val (num_5blocks:int64)` THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; + SUBGOAL_THEN `0x50 * val (num_5blocks:int64) + 0x10 <= val (len:int64)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ABBREV_TAC `val5blocks = val (num_5blocks:int64)` THEN + ABBREV_TAC `vallen = val (len:int64)` THEN + SUBSUMED_MAYCHANGE_TAC; + SUBSUMED_MAYCHANGE_TAC] + ; ALL_TAC + ] THEN + + ENSURES_INIT_TAC "s0" THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (1--3) THEN + FIRST_X_ASSUM MP_TAC THEN + + (* Assumptions that help with reasoning about nonoverlapping + so that the universally quantified assumption stays. + See: https://hol-light.zulipchat.com/#narrow/channel/474190-s2n-bignum/topic/.E2.9C.94.20Symbolic.20simulation.20removed.20assumption/with/541554894 *) + SUBGOAL_THEN `(val (num_5blocks:int64)) * 0x50 < 0x2 EXP 0x40` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val ((word (val (num_5blocks:int64) * 0x50)):int64) = 0x50 * val num_5blocks` ASSUME_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN ASM_ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[th])) THEN + + COND_CASES_TAC THENL + [ (* Case: len % 0x50 = 0x40 *) + DISCH_TAC THEN + + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 + 0x40 = val (len_full_blocks:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (word_sub + (word_sub (len_full_blocks:int64) + (word_mul (word 0x50) (num_5blocks:int64))) + (word 0x40)) = + 0x0` THEN + REWRITE_TAC [VAL_EQ_0; WORD_SUB_EQ_0] THEN + REWRITE_TAC [WORD_RULE `!x:int64. word_mul (word 0x50) x = word(val x * 0x50)`] THEN + REWRITE_TAC[GSYM VAL_EQ] THEN + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 < 2 EXP 64` MP_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 2 EXP 24` THEN + ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[VAL_WORD_SUB_CASES] THEN + SIMP_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + NUM_REDUCE_TAC THEN ARITH_TAC + ; ALL_TAC] THEN + + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 + 0x40 <= val (len:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 + 0x40 = val (len_full_blocks:int64)` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= val (len:int64)` THEN + ARITH_TAC + ; ALL_TAC] THEN + MP_TAC (SPECL [`ptxt_p:int64`; `num_5blocks:int64`; `len:int64`; `pt_in:byte list`; `s3:armstate`] READ_TAIL4_LEMMA) THEN + ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (4--127) THEN + XTSENC_TAC `Q0:(armstate,int128)component` + `val (num_5blocks:int64) * 0x50` `val (num_5blocks:int64) * 0x5` THEN + XTSENC_TAC `Q1:(armstate,int128)component` + `val (num_5blocks:int64) * 0x50 + 0x10` `val (num_5blocks:int64) * 0x5 + 0x1` THEN + XTSENC_TAC `Q24:(armstate,int128)component` + `val (num_5blocks:int64) * 0x50 + 0x20` `val (num_5blocks:int64) * 0x5 + 0x2` THEN + XTSENC_TAC `Q25:(armstate,int128)component` + `val (num_5blocks:int64) * 0x50 + 0x30` `val (num_5blocks:int64) * 0x5 + 0x3` THEN + + (* The following lemmas are for NONSELFMODIFYING_STATE_UPDATE_TAC when store back to ctxt_p + Otherwise symbolic simulation fails with + Failure "could not prove that updates will not modify the program code" *) + CHANGED_TAC (RULE_ASSUM_TAC(REWRITE_RULE + [WORD_RULE `word_mul (word 0x50) num_5blocks:int64 = word(0x50 * val num_5blocks)`])) THEN + CHANGED_TAC (RULE_ASSUM_TAC(REWRITE_RULE + [WORD_RULE `!base m n. word_add (word_add base (word m)) (word n) = word_add base (word(m + n))`])) THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (128--128) THEN (* Store 2 blocks in ctxt_p *) + (* Need to simplify the expression for X1 after the first store instruction *) + CHANGED_TAC (RULE_ASSUM_TAC(REWRITE_RULE + [WORD_RULE `!base m n. word_add (word_add base (word m)) (word n) = word_add base (word(m + n))`])) THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (129--137) THEN (* Store 2 blocks and calculate tweak *) + TWEAK_TAC `Q6:(armstate,int128)component` `val (num_5blocks:int64) * 0x5 + 0x4` `val (num_5blocks:int64) * 0x5 + 0x3` THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (138--138) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + (*` word_add ptxt_p (word (0x50 * val num_5blocks + 0x40)) = + word_add ptxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + word_add (word_add ctxt_p (word (0x50 * val num_5blocks))) (word 0x40) = + word_add ctxt_p (word (acc_len num_5blocks len_full_blocks)) /\ + calculate_tweak (val num_5blocks * 0x5 + 0x4) iv key2_lst = + calculate_tweak (acc_blocks num_5blocks len_full_blocks true) iv key2_lst /\ + (forall i. + i < val (word (acc_len num_5blocks len_full_blocks)) + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s138 = + EL i (aes256_xts_encrypt pt_in (acc_len num_5blocks len_full_blocks) iv key1_lst key2_lst))` *) + REPEAT CONJ_TAC THENL (* 4 subgoals (6 total) *) + [ + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_blocks] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[LE_REFL] THEN + SUBGOAL_THEN `val ((word (0x50 * val (num_5blocks:int64) + 0x40)):int64) = + 0x50 * val num_5blocks + 0x40` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; MOD_LT; DIMINDEX_64] THEN + UNDISCH_TAC `val (num_5blocks:int64) * 0x50 + 0x40 <= val (len:int64)` THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + CHANGED_TAC (POP_ASSUM(fun th -> REWRITE_TAC[th])) THEN + (* `forall i. + i < 0x50 * val num_5blocks + 0x40 + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s138 = + EL i (aes256_xts_encrypt pt_in (0x50 * val num_5blocks + 0x40) iv key1_lst key2_lst)` *) + + (* Remove quantifier in conclusion then in antecedent of the goal: + ==> (forall i. + i < 0x50 * val num_5blocks + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s138 = + EL i (aes256_xts_encrypt pt_in (val num_5blocks * 0x50) iv key1_lst key2_lst)) + ==> (forall i. + i < 0x50 * val num_5blocks + 0x40 + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s138 = + EL i (aes256_xts_encrypt pt_in (0x50 * val num_5blocks + 0x40) iv key1_lst key2_lst))` *) + UNDISCH_TAC + `forall i. + i < 0x50 * val (num_5blocks:int64) + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s138 = + EL i (aes256_xts_encrypt pt_in (val num_5blocks * 0x50) iv key1_lst key2_lst)` THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks:int64) + 0x40:num`; `ctxt_p:int64`; + `(aes256_xts_encrypt pt_in (0x50 * val (num_5blocks:int64) + 0x40) iv key1_lst key2_lst):byte list`; + `s138:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x40 = 0x10 * (5 * i + 4)`; + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + MP_TAC (SPECL [`0x50 * val (num_5blocks:int64):num`; `ctxt_p:int64`; + `(aes256_xts_encrypt pt_in (val (num_5blocks:int64) * 0x50) iv key1_lst key2_lst):byte list`; + `s138:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `i * 0x50 = 0x10 * 5 * i`; + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN +(* `read (memory :> bytes (ctxt_p,0x50 * val num_5blocks)) s138 = + num_of_bytelist + (SUB_LIST (0x0,0x50 * val num_5blocks) + (aes256_xts_encrypt pt_in (val num_5blocks * 0x50) iv key1_lst key2_lst)) + ==> read (memory :> bytes (ctxt_p,0x50 * val num_5blocks + 0x40)) s138 = + num_of_bytelist + (SUB_LIST (0x0,0x50 * val num_5blocks + 0x40) + (aes256_xts_encrypt pt_in (0x50 * val num_5blocks + 0x40) iv key1_lst + key2_lst))` *) + DISCH_TAC THEN + + IMP_REWRITE_TAC[ARITH_RULE `0x50 * i + 0x40 = (0x50 * i + 0x30) + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `(aes256_xts_encrypt pt_in (0x50 * val (num_5blocks:int64) + 0x40) iv key1_lst key2_lst)` THEN + (*`num_of_bytelist + (SUB_LIST (0x0,(0x50 * val num_5blocks + 0x30) + 0x10) + (aes256_xts_encrypt pt_in (0x50 * val num_5blocks + 0x40) iv key1_lst key2_lst)) = + num_of_bytelist (SUB_LIST (0x0,(0x50 * val num_5blocks + 0x30) + 0x10) + (aes256_xts_encrypt pt_in ((0x50 * val num_5blocks + 0x30) + 0x10) iv key1_lst key2_lst)) /\ + (0x50 * val num_5blocks + 0x30) + 0x10 <= + LENGTH (aes256_xts_encrypt pt_in (0x50 * val num_5blocks + 0x40) iv key1_lst key2_lst) /\ + read (memory :> bytes128 (word_add ctxt_p (word (0x50 * val num_5blocks + 0x30)))) s138 = + bytes_to_int128 (SUB_LIST (0x50 * val num_5blocks + 0x30,0x10) + (aes256_xts_encrypt pt_in (0x50 * val num_5blocks + 0x40) iv key1_lst key2_lst)) /\ + read (memory :> bytes (ctxt_p,0x50 * val num_5blocks + 0x30)) s138 = + num_of_bytelist (SUB_LIST (0x0,0x50 * val num_5blocks + 0x30) + (aes256_xts_encrypt pt_in (0x50 * val num_5blocks + 0x40) iv key1_lst key2_lst))`*) + REPEAT CONJ_TAC THENL [ (* 4 subgoals *) + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x30) + 0x10 = 0x50 * i + 0x40`]; +(* `(0x50 * val num_5blocks + 0x30) + 0x10 <= + LENGTH (aes256_xts_encrypt pt_in (0x50 * val num_5blocks + 0x40) iv key1_lst key2_lst)` *) + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x4:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + ASM_REWRITE_TAC[] THEN ARITH_TAC; +(* `read (memory :> bytes128 (word_add ctxt_p (word (0x50 * val num_5blocks + 0x30)))) s138 = + bytes_to_int128 (SUB_LIST (0x50 * val num_5blocks + 0x30,0x10) + (aes256_xts_encrypt pt_in (0x50 * val num_5blocks + 0x40) iv key1_lst key2_lst))` *) + + (* Establish that one xts encrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + CHANGED_TAC(RULE_ASSUM_TAC(REWRITE_RULE + [ARITH_RULE `(0x50 * val (num_5blocks:int64) + 0x20) + 0x10 = 0x50 * val num_5blocks + 0x30`])) THEN + ASM_REWRITE_TAC[] THEN +(* +`aes256_xts_encrypt_round + (bytes_to_int128 (SUB_LIST (val num_5blocks * 0x50 + 0x30,0x10) pt_in)) + (calculate_tweak (val num_5blocks * 0x5 + 0x3) iv key2_lst) + key1_lst = + bytes_to_int128 + (SUB_LIST (0x50 * val num_5blocks + 0x30,0x10) + (aes256_xts_encrypt pt_in (0x50 * val num_5blocks + 0x40) iv key1_lst + key2_lst))` +*) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * val (num_5blocks:int64) + 0x40 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks:int64) + 0x40) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 64 = 16 * (5 * i + 4)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x40) DIV 0x10 = 0x5 * i + 0x4`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x4 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x4) - 0x2 = 0x5 * i + 0x2`; + ARITH_RULE `(0x5 * i + 0x4) - 0x1 = 0x5 * i + 0x3`] THEN +(* +`aes256_xts_encrypt_round + (bytes_to_int128 (SUB_LIST (val num_5blocks * 0x50 + 0x30,0x10) pt_in)) + (calculate_tweak (val num_5blocks * 0x5 + 0x3) iv key2_lst) + key1_lst = + bytes_to_int128 + (SUB_LIST (0x50 * val num_5blocks + 0x30,0x10) + (APPEND + (aes256_xts_encrypt_rec 0x0 (0x5 * val num_5blocks + 0x2) pt_in iv key1_lst + key2_lst) + (aes256_xts_encrypt_tail (0x5 * val num_5blocks + 0x3) 0x0 pt_in iv key1_lst + key2_lst)))` +*) + MP_TAC (SPECL [`0`;`5 * val (num_5blocks:int64) + 2:num`; `pt_in:byte list`; `iv:int128`; + `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i + 2 < 0)`; + ARITH_RULE `((0x5 * i + 0x2) - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x30`] THEN +(* +`LENGTH + (aes256_xts_encrypt_rec 0x0 (0x5 * val num_5blocks + 0x2) pt_in iv key1_lst + key2_lst) = + 0x50 * val num_5blocks + 0x30 + ==> aes256_xts_encrypt_round + (bytes_to_int128 (SUB_LIST (val num_5blocks * 0x50 + 0x30,0x10) pt_in)) + (calculate_tweak (val num_5blocks * 0x5 + 0x3) iv key2_lst) + key1_lst = + bytes_to_int128 + (SUB_LIST (0x50 * val num_5blocks + 0x30,0x10) + (APPEND + (aes256_xts_encrypt_rec 0x0 (0x5 * val num_5blocks + 0x2) pt_in iv + key1_lst + key2_lst) + (aes256_xts_encrypt_tail (0x5 * val num_5blocks + 0x3) 0x0 pt_in iv + key1_lst + key2_lst)))` +*) + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN +(* +`aes256_xts_encrypt_round + (bytes_to_int128 (SUB_LIST (val num_5blocks * 0x50 + 0x30,0x10) pt_in)) + (calculate_tweak (val num_5blocks * 0x5 + 0x3) iv key2_lst) + key1_lst = + bytes_to_int128 + (SUB_LIST (0x0,0x10) + (aes256_xts_encrypt_tail (0x5 * val num_5blocks + 0x3) 0x0 pt_in iv key1_lst + key2_lst))` +*) + + MP_TAC (SPECL [`5 * val (num_5blocks:int64) + 3:num`; `0x0:num`; `pt_in:byte list`; `iv:int128`; + `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN +(* +`aes256_xts_encrypt_round + (bytes_to_int128 (SUB_LIST (val num_5blocks * 0x50 + 0x30,0x10) pt_in)) + (calculate_tweak (val num_5blocks * 0x5 + 0x3) iv key2_lst) + key1_lst = + bytes_to_int128 + (SUB_LIST (0x0,0x10) + (aes256_xts_encrypt_tail (0x5 * val num_5blocks + 0x3) 0x0 pt_in iv key1_lst + key2_lst))` +*) + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN +(* +`aes256_xts_encrypt_round + (bytes_to_int128 (SUB_LIST (val num_5blocks * 0x50 + 0x30,0x10) pt_in)) + (calculate_tweak (val num_5blocks * 0x5 + 0x3) iv key2_lst) + key1_lst = + bytes_to_int128 + (aes256_xts_encrypt_tail (0x5 * val num_5blocks + 0x3) 0x0 pt_in iv key1_lst + key2_lst)` +*) + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + ASM_SIMP_TAC[ARITH_RULE `(i * 0x5 + 0x3) * 0x10 = i * 0x50 + 0x30`; + ARITH_RULE `5 * i + 3 = i * 5 + 3`]; (* 3 total *) +(*`read (memory :> bytes (ctxt_p,0x50 * val num_5blocks + 0x30)) s138 = + num_of_bytelist (SUB_LIST (0x0,0x50 * val num_5blocks + 0x30) + (aes256_xts_encrypt pt_in (0x50 * val num_5blocks + 0x40) iv key1_lst key2_lst))` *) + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x30 = 0x10 * (5 * i + 3)`; + ARITH_RULE `0x50 * i + 0x40 = 0x10 * (5 * i + 3) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV (* 3 total *) + ] THEN + + IMP_REWRITE_TAC[ARITH_RULE `0x50 * i + 0x30 = (0x50 * i + 0x20) + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `(aes256_xts_encrypt pt_in (0x50 * val (num_5blocks:int64) + 0x30) iv key1_lst key2_lst)` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x3:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES]; + + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x20) + 0x10 = 0x50 * i + 0x30`] THEN + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x3:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts encrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x30 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks:int64) + 0x30) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 48 = 16 * (5 * i + 3)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x30) DIV 0x10 = 0x5 * i + 0x3`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x3 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x3) - 0x2 = 0x5 * i + 0x1`; + ARITH_RULE `(0x5 * i + 0x3) - 0x1 = 0x5 * i + 0x2`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks:int64) + 1:num`; `pt_in:byte list`; `iv:int128`; + `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i + 1 < 0)`] THEN + REWRITE_TAC[ARITH_RULE `((0x5 * i + 0x1) - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x20`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks:int64) + 2:num`; `0x0:num`; `pt_in:byte list`; `iv:int128`; + `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + ASM_SIMP_TAC[ARITH_RULE `(i * 0x5 + 0x2) * 0x10 = i * 0x50 + 0x20`; + ARITH_RULE `5 * i + 2 = i * 5 + 2`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 2)`; + ARITH_RULE `0x50 * i + 0x30 = 0x10 * (5 * i + 2) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = (0x50 * i + 0x10) + 0x10`] THEN + (* Use SPECL to force IMP_REWRITE_TAC to apply once once *) + IMP_REWRITE_TAC[(SPECL [`ctxt_p:int64`; `(0x50 * val (num_5blocks:int64) + 0x10):num`; + `x:byte list`; `s138:armstate`] READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `(aes256_xts_encrypt pt_in (0x50 * val (num_5blocks:int64) + 0x20) iv key1_lst key2_lst)` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x2:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x2:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts encrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x20 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks:int64) + 0x20) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 32 = 16 * (5 * i + 2)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x20) DIV 0x10 = 0x5 * i + 0x2`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x2 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x2) - 0x2 = 0x5 * i`; + ARITH_RULE `(0x5 * i + 0x2) - 0x1 = 0x5 * i + 0x1`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks:int64):num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i < 0)`; + ARITH_RULE `(0x5 * i - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x10`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks:int64) + 1:num`; `0x0:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 + 0x10 = (i * 0x5 + 0x1) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x10 = 0x10 * (5 * i + 1)`; + ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 1) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + IMP_REWRITE_TAC[(SPECL [`ctxt_p:int64`; `(0x50 * val (num_5blocks:int64)):num`; + `(aes256_xts_encrypt pt_in (0x50 * val (num_5blocks:int64) + 0x10) iv key1_lst key2_lst):byte list`; + `s138:armstate`] READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `iv:int128` THEN EXISTS_TAC `key1_lst:int128 list` THEN + EXISTS_TAC `key2_lst:int128 list` THEN EXISTS_TAC `pt_in:byte list` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x1:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x1:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts encrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x10 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks:int64) + 0x10) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 16 = 16 * (5 * i + 1)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x10) DIV 0x10 = 0x5 * i + 0x1`] THEN + (* Two cases: i = 0 then execute tail branch, else execute recursion branch *) + COND_CASES_TAC THENL + [ SUBGOAL_THEN `val (num_5blocks:int64) = 0` SUBST1_TAC THENL + [ UNDISCH_TAC `5 * val (num_5blocks:int64) + 1 < 2` THEN + UNDISCH_TAC `0 < val (num_5blocks:int64)` THEN + ARITH_TAC + ; ALL_TAC] THEN CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [`0x0:num`; `0x0:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[(ISPECL [`(aes256_xts_encrypt_tail 0x0 0x0 pt_in iv key1_lst key2_lst):byte list`; + `0x10:num`] SUB_LIST_LENGTH_IMPLIES)] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + CONV_TAC NUM_REDUCE_CONV; + + SIMP_TAC[ARITH_RULE `(0x5 * i + 0x1) - 0x2 = 0x5 * i - 0x1`; + ARITH_RULE `(0x5 * i + 0x1) - 0x1 = 0x5 * i`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks:int64) - 1:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SUBGOAL_THEN `~(0x5 * val (num_5blocks:int64) - 0x1 < 0x0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(0x5 * val (num_5blocks:int64) + 0x1 < 0x2)` THEN ARITH_TAC; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + IMP_REWRITE_TAC[ARITH_RULE `~(0x5 * i + 0x1 < 0x2) ==> (0x5 * i - 1 - 0x0 + 0x1) * 0x10 = 0x50 * i`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks:int64):num`; + `0x0:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 = (i * 0x5) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`] + ]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `i * 0x50 = 0x50 * i`; + ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + ARITH_RULE `0x50 * i + 0x10 = 0x10 * 5 * i + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] + ] + ] ; ALL_TAC + ] THEN (* 2 total *) + + DISCH_TAC THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (4--5) THEN + FIRST_X_ASSUM MP_TAC THEN + COND_CASES_TAC THENL + [ (* Case: len % 0x50 = 0x30 *) + DISCH_TAC THEN + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 + 0x30 = val (len_full_blocks:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (word_sub + (word_sub (len_full_blocks:int64) + (word_mul (word 0x50) (num_5blocks:int64))) + (word 0x30)) = + 0x0` THEN + REWRITE_TAC [VAL_EQ_0; WORD_SUB_EQ_0] THEN + REWRITE_TAC [WORD_RULE `!x:int64. word_mul (word 0x50) x = word(val x * 0x50)`] THEN + REWRITE_TAC[GSYM VAL_EQ] THEN + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 < 2 EXP 64` MP_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 2 EXP 24` THEN + ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[VAL_WORD_SUB_CASES] THEN + SIMP_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + NUM_REDUCE_TAC THEN ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `~(val (num_5blocks:int64) * 0x50 + 0x40 = val (len_full_blocks:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 + 0x30 = val (len_full_blocks:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 + 0x30 <= val (len:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 + 0x30 = val (len_full_blocks:int64)` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= val (len:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`ptxt_p:int64`; `num_5blocks:int64`; `len:int64`; `pt_in:byte list`; `s5:armstate`] + READ_TAIL3_LEMMA) THEN + ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (6--97) THEN + XTSENC_TAC `Q0:(armstate,int128)component` + `val (num_5blocks:int64) * 0x50` `val (num_5blocks:int64) * 0x5` THEN + XTSENC_TAC `Q1:(armstate,int128)component` + `val (num_5blocks:int64) * 0x50 + 0x10` `val (num_5blocks:int64) * 0x5 + 0x1` THEN + XTSENC_TAC `Q24:(armstate,int128)component` + `val (num_5blocks:int64) * 0x50 + 0x20` `val (num_5blocks:int64) * 0x5 + 0x2` THEN + + (* The following lemmas are for NONSELFMODIFYING_STATE_UPDATE_TAC when store back to ctxt_p *) + RULE_ASSUM_TAC(REWRITE_RULE + [WORD_RULE `word_mul (word 0x50) num_5blocks:int64 = word(0x50 * val num_5blocks)`]) THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (98--108) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `val (num_5blocks:int64) * 0x5 + 0x3` `val (num_5blocks:int64) * 0x5 + 0x2` THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + + REWRITE_TAC[acc_blocks] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; (* 3 total *) + + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[LE_REFL] THEN + SUBGOAL_THEN `val ((word (0x50 * val (num_5blocks:int64) + 0x30)):int64) = + 0x50 * val num_5blocks + 0x30` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; MOD_LT; DIMINDEX_64] THEN + UNDISCH_TAC `val (num_5blocks:int64) * 0x50 + 0x30 <= val (len:int64)` THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> REWRITE_TAC[th]) THEN + + (* Remove quantifier *) + UNDISCH_TAC + `forall i. + i < 0x50 * val (num_5blocks:int64) + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s108 = + EL i (aes256_xts_encrypt pt_in (val num_5blocks * 0x50) iv key1_lst key2_lst)` THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks:int64) + 0x30:num`; `ctxt_p:int64`; + `(aes256_xts_encrypt pt_in (0x50 * val (num_5blocks:int64) + 0x30) iv key1_lst key2_lst):byte list`; + `s108:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x30 = 0x10 * (5 * i + 3)`; + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + MP_TAC (SPECL [`0x50 * val (num_5blocks:int64):num`; `ctxt_p:int64`; + `(aes256_xts_encrypt pt_in (val (num_5blocks:int64) * 0x50) iv key1_lst key2_lst):byte list`; + `s108:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `i * 0x50 = 0x10 * 5 * i`; + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + DISCH_TAC THEN + + IMP_REWRITE_TAC[ARITH_RULE `0x50 * i + 0x30 = (0x50 * i + 0x20) + 0x10`; READ_BYTES_AND_BYTE128_SPLIT] THEN + EXISTS_TAC `(aes256_xts_encrypt pt_in (0x50 * val (num_5blocks:int64) + 0x30) iv key1_lst key2_lst)` THEN + REPEAT CONJ_TAC THENL [ + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x20) + 0x10 = 0x50 * i + 0x30`]; + + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x3:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + ASM_REWRITE_TAC[] THEN ARITH_TAC; (* 4 total *) + (* IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES]; *) + (* + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x20) + 0x10 = 0x50 * i + 0x30`] THEN + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x3:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV; (* THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; *) + *) + + (* Establish that one xts encrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x30 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks:int64) + 0x30) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 48 = 16 * (5 * i + 3)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x30) DIV 0x10 = 0x5 * i + 0x3`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x3 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x3) - 0x2 = 0x5 * i + 0x1`; + ARITH_RULE `(0x5 * i + 0x3) - 0x1 = 0x5 * i + 0x2`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks:int64) + 1:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i + 1 < 0)`] THEN + REWRITE_TAC[ARITH_RULE `((0x5 * i + 0x1) - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x20`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks:int64) + 2:num`; `0x0:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + ASM_SIMP_TAC[ARITH_RULE `(i * 0x5 + 0x2) * 0x10 = i * 0x50 + 0x20`; + ARITH_RULE `5 * i + 2 = i * 5 + 2`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 2)`; + ARITH_RULE `0x50 * i + 0x30 = 0x10 * (5 * i + 2) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV (* 3 total *) + ] THEN + + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = (0x50 * i + 0x10) + 0x10`] THEN + (* Use SPECL to force IMP_REWRITE_TAC to apply once once *) + IMP_REWRITE_TAC[(SPECL [`ctxt_p:int64`; `(0x50 * val (num_5blocks:int64) + 0x10):num`; + `x:byte list`; `s108:armstate`] READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `(aes256_xts_encrypt pt_in (0x50 * val (num_5blocks:int64) + 0x20) iv key1_lst key2_lst)` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x2:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x2:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts encrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x20 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks:int64) + 0x20) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 32 = 16 * (5 * i + 2)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x20) DIV 0x10 = 0x5 * i + 0x2`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x2 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x2) - 0x2 = 0x5 * i`; + ARITH_RULE `(0x5 * i + 0x2) - 0x1 = 0x5 * i + 0x1`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks:int64):num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i < 0)`; + ARITH_RULE `(0x5 * i - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x10`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks:int64) + 1:num`; `0x0:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 + 0x10 = (i * 0x5 + 0x1) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x10 = 0x10 * (5 * i + 1)`; + ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 1) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + IMP_REWRITE_TAC[(SPECL [`ctxt_p:int64`; `(0x50 * val (num_5blocks:int64)):num`; + `(aes256_xts_encrypt pt_in (0x50 * val (num_5blocks:int64) + 0x10) iv key1_lst key2_lst):byte list`; + `s108:armstate`] READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `iv:int128` THEN EXISTS_TAC `key1_lst:int128 list` THEN + EXISTS_TAC `key2_lst:int128 list` THEN EXISTS_TAC `pt_in:byte list` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x1:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x1:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts encrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x10 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks:int64) + 0x10) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 16 = 16 * (5 * i + 1)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x10) DIV 0x10 = 0x5 * i + 0x1`] THEN + (* Two cases: i = 0 then execute tail branch, else execute recursion branch *) + COND_CASES_TAC THENL + [ SUBGOAL_THEN `val (num_5blocks:int64) = 0` SUBST1_TAC THENL + [ UNDISCH_TAC `5 * val (num_5blocks:int64) + 1 < 2` THEN + UNDISCH_TAC `0 < val (num_5blocks:int64)` THEN + ARITH_TAC + ; ALL_TAC] THEN CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [`0x0:num`; `0x0:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[(ISPECL [`(aes256_xts_encrypt_tail 0x0 0x0 pt_in iv key1_lst key2_lst):byte list`; + `0x10:num`] SUB_LIST_LENGTH_IMPLIES)] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + CONV_TAC NUM_REDUCE_CONV; + + SIMP_TAC[ARITH_RULE `(0x5 * i + 0x1) - 0x2 = 0x5 * i - 0x1`; + ARITH_RULE `(0x5 * i + 0x1) - 0x1 = 0x5 * i`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks:int64) - 1:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SUBGOAL_THEN `~(0x5 * val (num_5blocks:int64) - 0x1 < 0x0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(0x5 * val (num_5blocks:int64) + 0x1 < 0x2)` THEN ARITH_TAC; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + IMP_REWRITE_TAC[ARITH_RULE `~(0x5 * i + 0x1 < 0x2) ==> (0x5 * i - 1 - 0x0 + 0x1) * 0x10 = 0x50 * i`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks:int64):num`; + `0x0:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 = (i * 0x5) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`] + ]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `i * 0x50 = 0x50 * i`; + ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + ARITH_RULE `0x50 * i + 0x10 = 0x10 * 5 * i + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] + ] + ] ; ALL_TAC (* 2 total *) + ] THEN + + DISCH_TAC THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (6--7) THEN + FIRST_X_ASSUM MP_TAC THEN + COND_CASES_TAC THENL + [ (* Case: len % 0x50 = 0x20 *) + DISCH_TAC THEN + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 + 0x20 = val (len_full_blocks:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (word_sub + (word_sub (len_full_blocks:int64) + (word_mul (word 0x50) (num_5blocks:int64))) + (word 0x20)) = + 0x0` THEN + REWRITE_TAC [VAL_EQ_0; WORD_SUB_EQ_0] THEN + REWRITE_TAC [WORD_RULE `!x:int64. word_mul (word 0x50) x = word(val x * 0x50)`] THEN + REWRITE_TAC[GSYM VAL_EQ] THEN + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 < 2 EXP 64` MP_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 2 EXP 24` THEN + ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[VAL_WORD_SUB_CASES] THEN + SIMP_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + NUM_REDUCE_TAC THEN ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `~(val (num_5blocks:int64) * 0x50 + 0x40 = val (len_full_blocks:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 + 0x20 = val (len_full_blocks:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_5blocks:int64) * 0x50 + 0x30 = val (len_full_blocks:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 + 0x20 = val (len_full_blocks:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 + 0x20 <= val (len:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 + 0x20 = val (len_full_blocks:int64)` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= val (len:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`ptxt_p:int64`; `num_5blocks:int64`; `len:int64`; `pt_in:byte list`; `s7:armstate`] + READ_TAIL2_LEMMA) THEN + ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (8--68) THEN + XTSENC_TAC `Q0:(armstate,int128)component` + `val (num_5blocks:int64) * 0x50` `val (num_5blocks:int64) * 0x5` THEN + XTSENC_TAC `Q1:(armstate,int128)component` + `val (num_5blocks:int64) * 0x50 + 0x10` `val (num_5blocks:int64) * 0x5 + 0x1` THEN + + (* The following lemmas are for NONSELFMODIFYING_STATE_UPDATE_TAC when store back to ctxt_p *) + RULE_ASSUM_TAC(REWRITE_RULE + [WORD_RULE `word_mul (word 0x50) num_5blocks:int64 = word(0x50 * val num_5blocks)`]) THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (69--78) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `val (num_5blocks:int64) * 0x5 + 0x2` `val (num_5blocks:int64) * 0x5 + 0x1` THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_blocks] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; (* 3 total *) + + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[LE_REFL] THEN + SUBGOAL_THEN `val ((word (0x50 * val (num_5blocks:int64) + 0x20)):int64) = + 0x50 * val num_5blocks + 0x20` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; MOD_LT; DIMINDEX_64] THEN + UNDISCH_TAC `val (num_5blocks:int64) * 0x50 + 0x20 <= val (len:int64)` THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> REWRITE_TAC[th]) THEN + + (* Remove quantifier *) + UNDISCH_TAC + `forall i. + i < 0x50 * val (num_5blocks:int64) + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s78 = + EL i (aes256_xts_encrypt pt_in (val num_5blocks * 0x50) iv key1_lst key2_lst)` THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks:int64) + 0x20:num`; `ctxt_p:int64`; + `(aes256_xts_encrypt pt_in (0x50 * val (num_5blocks:int64) + 0x20) iv key1_lst key2_lst):byte list`; + `s78:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 2)`; + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + MP_TAC (SPECL [`0x50 * val (num_5blocks:int64):num`; `ctxt_p:int64`; + `(aes256_xts_encrypt pt_in (val (num_5blocks:int64) * 0x50) iv key1_lst key2_lst):byte list`; + `s78:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i = i * 0x50`; + ARITH_RULE `i * 0x50 = 0x10 * 5 * i`; + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + DISCH_TAC THEN + + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x20 = (0x50 * i + 0x10) + 0x10`] THEN + (* Use SPECL to force IMP_REWRITE_TAC to apply once once *) + IMP_REWRITE_TAC[(SPECL [`ctxt_p:int64`; `(0x50 * val (num_5blocks:int64) + 0x10):num`; + `x:byte list`; `s78:armstate`] READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `(aes256_xts_encrypt pt_in (0x50 * val (num_5blocks:int64) + 0x20) iv key1_lst key2_lst)` THEN + REPEAT CONJ_TAC THENL [ + REWRITE_TAC [ARITH_RULE `(0x50 * i + 0x10) + 0x10 = 0x50 * i + 0x20`]; + + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x2:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts encrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x20 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks:int64) + 0x20) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 32 = 16 * (5 * i + 2)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x20) DIV 0x10 = 0x5 * i + 0x2`] THEN + SIMP_TAC[ARITH_RULE `~(0x5 * i + 0x2 < 0x2)`; + ARITH_RULE `(0x5 * i + 0x2) - 0x2 = 0x5 * i`; + ARITH_RULE `(0x5 * i + 0x2) - 0x1 = 0x5 * i + 0x1`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks:int64):num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SIMP_TAC[ARITH_RULE `~(5 * i < 0)`; + ARITH_RULE `(0x5 * i - 0x0 + 0x1) * 0x10 = 0x50 * i + 0x10`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks:int64) + 1:num`; `0x0:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 + 0x10 = (i * 0x5 + 0x1) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x10 = 0x10 * (5 * i + 1)`; + ARITH_RULE `0x50 * i + 0x20 = 0x10 * (5 * i + 1) + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ASM_REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC] THEN CONV_TAC NUM_REDUCE_CONV + ] THEN + + IMP_REWRITE_TAC[(SPECL [`ctxt_p:int64`; `(0x50 * val (num_5blocks:int64)):num`; + `(aes256_xts_encrypt pt_in (0x50 * val (num_5blocks:int64) + 0x10) iv key1_lst key2_lst):byte list`; + `s78:armstate`] READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `iv:int128` THEN EXISTS_TAC `key1_lst:int128 list` THEN + EXISTS_TAC `key2_lst:int128 list` THEN EXISTS_TAC `pt_in:byte list` THEN + REPEAT CONJ_TAC THENL [ + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x1:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x1:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN ARITH_TAC; + + (* Establish that one xts encrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x10 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks:int64) + 0x10) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 16 = 16 * (5 * i + 1)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x10) DIV 0x10 = 0x5 * i + 0x1`] THEN + (* Two cases: i = 0 then execute tail branch, else execute recursion branch *) + COND_CASES_TAC THENL + [ SUBGOAL_THEN `val (num_5blocks:int64) = 0` SUBST1_TAC THENL + [ UNDISCH_TAC `5 * val (num_5blocks:int64) + 1 < 2` THEN + UNDISCH_TAC `0 < val (num_5blocks:int64)` THEN + ARITH_TAC + ; ALL_TAC] THEN CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [`0x0:num`; `0x0:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[(ISPECL [`(aes256_xts_encrypt_tail 0x0 0x0 pt_in iv key1_lst key2_lst):byte list`; + `0x10:num`] SUB_LIST_LENGTH_IMPLIES)] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + CONV_TAC NUM_REDUCE_CONV; + + SIMP_TAC[ARITH_RULE `(0x5 * i + 0x1) - 0x2 = 0x5 * i - 0x1`; + ARITH_RULE `(0x5 * i + 0x1) - 0x1 = 0x5 * i`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks:int64) - 1:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SUBGOAL_THEN `~(0x5 * val (num_5blocks:int64) - 0x1 < 0x0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(0x5 * val (num_5blocks:int64) + 0x1 < 0x2)` THEN ARITH_TAC; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + IMP_REWRITE_TAC[ARITH_RULE `~(0x5 * i + 0x1 < 0x2) ==> (0x5 * i - 1 - 0x0 + 0x1) * 0x10 = 0x50 * i`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks:int64):num`; + `0x0:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 = (i * 0x5) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`] + ]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `i * 0x50 = 0x50 * i`; + ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + ARITH_RULE `0x50 * i + 0x10 = 0x10 * 5 * i + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] + ] + ] ; ALL_TAC (* 2 total *) + ] THEN + + DISCH_TAC THEN + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (8--9) THEN + FIRST_X_ASSUM MP_TAC THEN + COND_CASES_TAC THENL (*?? *) + [ (* Case: len % 0x50 = 0x10 *) + DISCH_TAC THEN + + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 + 0x10 = val (len_full_blocks:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (word_sub + (word_sub (len_full_blocks:int64) + (word_mul (word 0x50) (num_5blocks:int64))) + (word 0x10)) = + 0x0` THEN + REWRITE_TAC [VAL_EQ_0; WORD_SUB_EQ_0] THEN + REWRITE_TAC [WORD_RULE `!x:int64. word_mul (word 0x50) x = word(val x * 0x50)`] THEN + REWRITE_TAC[GSYM VAL_EQ] THEN + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 < 2 EXP 64` MP_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 2 EXP 24` THEN + ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[VAL_WORD_SUB_CASES] THEN + SIMP_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + NUM_REDUCE_TAC THEN ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `~(val (num_5blocks:int64) * 0x50 + 0x40 = val (len_full_blocks:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 + 0x10 = val (len_full_blocks:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_5blocks:int64) * 0x50 + 0x30 = val (len_full_blocks:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 + 0x10 = val (len_full_blocks:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_5blocks:int64) * 0x50 + 0x20 = val (len_full_blocks:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 + 0x10 = val (len_full_blocks:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 + 0x10 <= val (len:int64)` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 + 0x10 = val (len_full_blocks:int64)` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= val (len:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`ptxt_p:int64`; `num_5blocks:int64`; `len:int64`; `pt_in:byte list`; `s9:armstate`] + READ_TAIL1_LEMMA) THEN + ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (10--40) THEN + XTSENC_TAC `Q0:(armstate,int128)component` + `val (num_5blocks:int64) * 0x50` `val (num_5blocks:int64) * 0x5` THEN + + (* The following lemmas are for NONSELFMODIFYING_STATE_UPDATE_TAC when store back to ctxt_p *) + RULE_ASSUM_TAC(REWRITE_RULE + [WORD_RULE `word_mul (word 0x50) num_5blocks:int64 = word(0x50 * val num_5blocks)`]) THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (41--50) THEN + TWEAK_TAC `Q6:(armstate,int128)component` `val (num_5blocks:int64) * 0x5 + 0x1` `val (num_5blocks:int64) * 0x5` THEN + + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL + [ + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_blocks] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; (* 3 total *) + + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[LE_REFL] THEN + SUBGOAL_THEN `val ((word (0x50 * val (num_5blocks:int64) + 0x10)):int64) = + 0x50 * val num_5blocks + 0x10` ASSUME_TAC THENL + [ IMP_REWRITE_TAC[VAL_WORD; MOD_LT; DIMINDEX_64] THEN + UNDISCH_TAC `val (num_5blocks:int64) * 0x50 + 0x10 <= val (len:int64)` THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; ALL_TAC] THEN + POP_ASSUM(fun th -> REWRITE_TAC[th]) THEN + + (* Remove quantifier *) + UNDISCH_TAC + `forall i. + i < 0x50 * val (num_5blocks:int64) + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s50 = + EL i (aes256_xts_encrypt pt_in (val num_5blocks * 0x50) iv key1_lst key2_lst)` THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks:int64) + 0x10:num`; `ctxt_p:int64`; + `(aes256_xts_encrypt pt_in (0x50 * val (num_5blocks:int64) + 0x10) iv key1_lst key2_lst):byte list`; + `s50:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i + 0x10 = 0x10 * (5 * i + 1)`; + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + MP_TAC (SPECL [`0x50 * val (num_5blocks:int64):num`; `ctxt_p:int64`; + `(aes256_xts_encrypt pt_in (val (num_5blocks:int64) * 0x50) iv key1_lst key2_lst):byte list`; + `s50:armstate`] BYTE_LIST_TO_NUM_THM) THEN + ANTS_TAC THENL[ + REWRITE_TAC[ARITH_RULE `0x50 * i = i * 0x50`; + ARITH_RULE `i * 0x50 = 0x10 * 5 * i`; + LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + ARITH_TAC + ; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + DISCH_TAC THEN + + IMP_REWRITE_TAC[(SPECL [`ctxt_p:int64`; `(0x50 * val (num_5blocks:int64)):num`; + `(aes256_xts_encrypt pt_in (0x50 * val (num_5blocks:int64) + 0x10) iv key1_lst key2_lst):byte list`; + `s50:armstate`] READ_BYTES_AND_BYTE128_SPLIT)] THEN + EXISTS_TAC `iv:int128` THEN EXISTS_TAC `key1_lst:int128 list` THEN + EXISTS_TAC `key2_lst:int128 list` THEN EXISTS_TAC `pt_in:byte list` THEN + REPEAT CONJ_TAC THENL [ + REFL_TAC; + + MP_TAC (SPECL [`0x5 * val (num_5blocks:int64) + 0x1:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; + `key2_lst:int128 list`] LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS) THEN + REWRITE_TAC[LEFT_ADD_DISTRIB; MULT_ASSOC; GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN ARITH_TAC; + + (* Establish that one xts encrypt round is the same as + selecting one block of bytes from calling the top-level function. *) + REWRITE_TAC[aes256_xts_encrypt] THEN + SIMP_TAC[ARITH_RULE `~(0x50 * i + 0x10 < 0x10)`] THEN + SUBGOAL_THEN `(0x50 * val (num_5blocks:int64) + 0x10) MOD 0x10 = 0` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `80 * i + 16 = 16 * (5 * i + 1)`] THEN + REWRITE_TAC[MOD_MULT] + ; ALL_TAC] THEN + CONV_TAC (DEPTH_CONV let_CONV) THEN + REWRITE_TAC[SUB_0; ARITH_RULE `(0x50 * i + 0x10) DIV 0x10 = 0x5 * i + 0x1`] THEN + (* Two cases: i = 0 then execute tail branch, else execute recursion branch *) + COND_CASES_TAC THENL + [ SUBGOAL_THEN `val (num_5blocks:int64) = 0` SUBST1_TAC THENL + [ UNDISCH_TAC `5 * val (num_5blocks:int64) + 1 < 2` THEN + UNDISCH_TAC `0 < val (num_5blocks:int64)` THEN + ARITH_TAC + ; ALL_TAC] THEN CONV_TAC NUM_REDUCE_CONV THEN + + MP_TAC (SPECL [`0x0:num`; `0x0:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[(ISPECL [`(aes256_xts_encrypt_tail 0x0 0x0 pt_in iv key1_lst key2_lst):byte list`; + `0x10:num`] SUB_LIST_LENGTH_IMPLIES)] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + CONV_TAC NUM_REDUCE_CONV; + + SIMP_TAC[ARITH_RULE `(0x5 * i + 0x1) - 0x2 = 0x5 * i - 0x1`; + ARITH_RULE `(0x5 * i + 0x1) - 0x1 = 0x5 * i`] THEN + + MP_TAC (SPECL [`0`;`5 * val (num_5blocks:int64) - 1:num`; + `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_REC) THEN + SUBGOAL_THEN `~(0x5 * val (num_5blocks:int64) - 0x1 < 0x0)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(0x5 * val (num_5blocks:int64) + 0x1 < 0x2)` THEN ARITH_TAC; ALL_TAC ] THEN + ASM_SIMP_TAC[] THEN + IMP_REWRITE_TAC[ARITH_RULE `~(0x5 * i + 0x1 < 0x2) ==> (0x5 * i - 1 - 0x0 + 0x1) * 0x10 = 0x50 * i`] THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_RIGHT_LEMMA] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`5 * val (num_5blocks:int64):num`; + `0x0:num`; `pt_in:byte list`; `iv:int128`; `key1_lst:int128 list`; `key2_lst:int128 list`] + LENGTH_OF_AES256_XTS_ENCRYPT_TAIL) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[ADD_0] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + + REWRITE_TAC[AES256_XTS_ENCRYPT_TAIL_WHEN_1BLOCK] THEN + SIMP_TAC[ARITH_RULE `i * 0x50 = (i * 0x5) * 0x10`; + ARITH_RULE `i * 0x5 = 0x5 * i`] + ]; + + (* Proving that reading previous bytes is the same as the spec *) + REWRITE_TAC[ARITH_RULE `i * 0x50 = 0x50 * i`; + ARITH_RULE `0x50 * i = 0x10 * 5 * i`; + ARITH_RULE `0x50 * i + 0x10 = 0x10 * 5 * i + 0x10`] THEN + REWRITE_TAC[SUB_LIST_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + REWRITE_TAC[LENGTH_OF_AES256_XTS_ENCRYPT_FULL_BLOCKS] + ] + ] ; ALL_TAC (* 2 total *) + ] THEN + + (* Case: len % 0x50 = 0 *) + DISCH_TAC THEN + SUBGOAL_THEN `val (num_5blocks:int64) * 0x50 = val (len_full_blocks:int64)` ASSUME_TAC THENL + [ MATCH_MP_TAC (SPECL [`val (len_full_blocks:int64)`; `val (num_5blocks:int64)`] + DIVISION_BY_80_LEMMA) THEN + REPEAT CONJ_TAC THENL + [ + EXPAND_TAC "num_5blocks" THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; + + EXPAND_TAC "len_full_blocks" THEN + REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT; DIVIDES_RMUL; DIVIDES_REFL] THEN + UNDISCH_TAC `val (len:int64) <= 0x2 EXP 0x18` THEN + ARITH_TAC; + + UNDISCH_TAC `~(val (word_sub + (word_sub (len_full_blocks:int64) + (word_mul (word 0x50) (num_5blocks:int64))) + (word 0x10)) = 0x0)` THEN + REWRITE_TAC[CONTRAPOS_THM] THEN + REWRITE_TAC[VAL_WORD_SUB_EQ_0; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x10 MOD 0x2 EXP 0x40 = 0x10`] THEN + REWRITE_TAC[VAL_WORD_SUB; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x50 MOD 0x2 EXP 0x40 = 0x50`] THEN + + SUBGOAL_THEN `0x50 * val (num_5blocks:int64) < 2 EXP 64` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 2 EXP 24` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks:int64)`; `2 EXP 64`] MOD_LT) THEN + ANTS_TAC THENL [ASM_SIMP_TAC[]; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`val (len_full_blocks:int64)`; `0x2 EXP 0x40`; + `0x50 * val (num_5blocks:int64)`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ + UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + SIMP_TAC[MULT_SYM]; ALL_TAC] THEN + ANTS_TAC THENL [ + UNDISCH_TAC `0x50 * val (num_5blocks:int64) < 2 EXP 64` THEN + ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; + `val (len_full_blocks:int64) - 0x50 * val (num_5blocks:int64)`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + REWRITE_TAC[ARITH_RULE `1 * 2 EXP 64 = 2 EXP 64`] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + SIMP_TAC[MULT_SYM] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV; + + UNDISCH_TAC `~(val (word_sub + (word_sub (len_full_blocks:int64) + (word_mul (word 0x50) (num_5blocks:int64))) + (word 0x20)) = 0x0)` THEN + REWRITE_TAC[CONTRAPOS_THM] THEN + REWRITE_TAC[VAL_WORD_SUB_EQ_0; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x10 MOD 0x2 EXP 0x40 = 0x10`] THEN + REWRITE_TAC[VAL_WORD_SUB; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x50 MOD 0x2 EXP 0x40 = 0x50`] THEN + + SUBGOAL_THEN `0x50 * val (num_5blocks:int64) < 2 EXP 64` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 2 EXP 24` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks:int64)`; `2 EXP 64`] MOD_LT) THEN + ANTS_TAC THENL [ASM_SIMP_TAC[]; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`val (len_full_blocks:int64)`; `0x2 EXP 0x40`; + `0x50 * val (num_5blocks:int64)`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ + UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + SIMP_TAC[MULT_SYM]; ALL_TAC] THEN + ANTS_TAC THENL [ + UNDISCH_TAC `0x50 * val (num_5blocks:int64) < 2 EXP 64` THEN + ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; + `val (len_full_blocks:int64) - 0x50 * val (num_5blocks:int64)`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + REWRITE_TAC[ARITH_RULE `1 * 2 EXP 64 = 2 EXP 64`] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + SIMP_TAC[MULT_SYM] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV; + + UNDISCH_TAC `~(val (word_sub + (word_sub (len_full_blocks:int64) + (word_mul (word 0x50) (num_5blocks:int64))) + (word 0x30)) = 0x0)` THEN + REWRITE_TAC[CONTRAPOS_THM] THEN + REWRITE_TAC[VAL_WORD_SUB_EQ_0; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x10 MOD 0x2 EXP 0x40 = 0x10`] THEN + REWRITE_TAC[VAL_WORD_SUB; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x50 MOD 0x2 EXP 0x40 = 0x50`] THEN + + SUBGOAL_THEN `0x50 * val (num_5blocks:int64) < 2 EXP 64` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 2 EXP 24` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks:int64)`; `2 EXP 64`] MOD_LT) THEN + ANTS_TAC THENL [ASM_SIMP_TAC[]; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`val (len_full_blocks:int64)`; `0x2 EXP 0x40`; + `0x50 * val (num_5blocks:int64)`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ + UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + SIMP_TAC[MULT_SYM]; ALL_TAC] THEN + ANTS_TAC THENL [ + UNDISCH_TAC `0x50 * val (num_5blocks:int64) < 2 EXP 64` THEN + ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; + `val (len_full_blocks:int64) - 0x50 * val (num_5blocks:int64)`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + REWRITE_TAC[ARITH_RULE `1 * 2 EXP 64 = 2 EXP 64`] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + SIMP_TAC[MULT_SYM] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV; + + UNDISCH_TAC `~(val (word_sub + (word_sub (len_full_blocks:int64) + (word_mul (word 0x50) (num_5blocks:int64))) + (word 0x40)) = 0x0)` THEN + REWRITE_TAC[CONTRAPOS_THM] THEN + REWRITE_TAC[VAL_WORD_SUB_EQ_0; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x10 MOD 0x2 EXP 0x40 = 0x10`] THEN + REWRITE_TAC[VAL_WORD_SUB; VAL_WORD_MUL; VAL_WORD; DIMINDEX_64; + ARITH_RULE `0x50 MOD 0x2 EXP 0x40 = 0x50`] THEN + + SUBGOAL_THEN `0x50 * val (num_5blocks:int64) < 2 EXP 64` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + UNDISCH_TAC `val (len_full_blocks:int64) <= 2 EXP 24` THEN + ARITH_TAC; ALL_TAC] THEN + MP_TAC (SPECL [`0x50 * val (num_5blocks:int64)`; `2 EXP 64`] MOD_LT) THEN + ANTS_TAC THENL [ASM_SIMP_TAC[]; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`val (len_full_blocks:int64)`; `0x2 EXP 0x40`; + `0x50 * val (num_5blocks:int64)`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ + UNDISCH_TAC `val (num_5blocks:int64) * 0x50 <= val (len_full_blocks:int64)` THEN + SIMP_TAC[MULT_SYM]; ALL_TAC] THEN + ANTS_TAC THENL [ + UNDISCH_TAC `0x50 * val (num_5blocks:int64) < 2 EXP 64` THEN + ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; + `val (len_full_blocks:int64) - 0x50 * val (num_5blocks:int64)`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + REWRITE_TAC[ARITH_RULE `1 * 2 EXP 64 = 2 EXP 64`] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + SIMP_TAC[MULT_SYM] THEN DISCH_TAC THEN + CONV_TAC NUM_REDUCE_CONV; + ] ; ALL_TAC + ] THEN + + SUBGOAL_THEN `~(val (num_5blocks:int64) * 0x50 + 0x40 = val (len_full_blocks:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 = val (len_full_blocks:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_5blocks:int64) * 0x50 + 0x30 = val (len_full_blocks:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 = val (len_full_blocks:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_5blocks:int64) * 0x50 + 0x20 = val (len_full_blocks:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 = val (len_full_blocks:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(val (num_5blocks:int64) * 0x50 + 0x10 = val (len_full_blocks:int64))` ASSUME_TAC THENL + [ UNDISCH_TAC `val (num_5blocks:int64) * 0x50 = val (len_full_blocks:int64)` THEN + ARITH_TAC; ALL_TAC] THEN + + ARM_ACCSTEPS_TAC AES256_XTS_ENCRYPT_EXEC [] (10--10) THEN + ENSURES_FINAL_STATE_TAC THEN ASM_REWRITE_TAC[] THEN + REPEAT CONJ_TAC THENL [ + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + REWRITE_TAC[acc_blocks] THEN ASM_SIMP_TAC[] THEN CONV_TAC WORD_RULE; + + REWRITE_TAC[acc_len] THEN ASM_SIMP_TAC[] THEN + + (* Rewrite to help reasoning about nonoverlapping + so that the universally quantified assumption stays. + See: https://hol-light.zulipchat.com/#narrow/channel/474190-s2n-bignum/topic/.E2.9C.94.20Symbolic.20simulation.20removed.20assumption/with/541554894 *) + SUBGOAL_THEN `val (word (0x50 * val (num_5blocks:int64)):int64) = 0x50 * val num_5blocks` MP_TAC THENL [ + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + UNDISCH_TAC `val (num_5blocks:int64) * 0x50 < 0x2 EXP 0x40` THEN + ARITH_TAC; ALL_TAC] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + + UNDISCH_TAC + `forall i. + i < 0x50 * val (num_5blocks:int64) + ==> read (memory :> bytes8 (word_add ctxt_p (word i))) s10 = + EL i + (aes256_xts_encrypt pt_in (val num_5blocks * 0x50) iv key1_lst + key2_lst)` THEN + REWRITE_TAC[ARITH_RULE `i * 0x50 = 0x50 * i`] + ] + ] (* End of loop invariant proof *) + ; ALL_TAC + ] THEN + + (* Reuse the cipher stealing proof *) + MP_TAC CIPHER_STEALING_ENC_CORRECT THEN + REWRITE_TAC [(REWRITE_CONV [aes256_xts_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_xts_encrypt_mc`] THEN + REWRITE_TAC[byte_list_at; PAIRWISE; ALL; MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI] THEN + DISCH_THEN MATCH_MP_TAC THEN + ASM_SIMP_TAC[] +);; + +let AES_XTS_ENCRYPT_SUBROUTINE_CORRECT = prove( + `!ptxt_p ctxt_p len key1_p key2_p iv_p + pt_in iv + k1_0 k1_1 k1_2 k1_3 k1_4 k1_5 k1_6 k1_7 k1_8 k1_9 k1_10 k1_11 k1_12 k1_13 k1_14 + k2_0 k2_1 k2_2 k2_3 k2_4 k2_5 k2_6 k2_7 k2_8 k2_9 k2_10 k2_11 k2_12 k2_13 k2_14 + pc stackpointer returnaddress. + aligned 16 stackpointer /\ + PAIRWISE nonoverlapping + [(word_sub stackpointer (word 96), 96); + (word pc, LENGTH aes256_xts_encrypt_mc); + (ptxt_p, val len); + (ctxt_p, val len); + (iv_p, 16); + (key1_p, 244); + (key2_p, 244)] /\ + val len >= 16 /\ val len <= 2 EXP 24 /\ LENGTH pt_in = val len + ==> ensures arm + (\s. aligned_bytes_loaded s (word pc) aes256_xts_encrypt_mc /\ + read PC s = word pc /\ + read SP s = stackpointer /\ + read X30 s = returnaddress /\ + C_ARGUMENTS [ptxt_p; ctxt_p; len; key1_p; key2_p; iv_p] s /\ + byte_list_at pt_in ptxt_p len s /\ + read(memory :> bytes128 iv_p) s = iv /\ + set_key_schedule s key1_p k1_0 k1_1 k1_2 k1_3 k1_4 k1_5 k1_6 k1_7 k1_8 k1_9 k1_10 k1_11 k1_12 k1_13 k1_14 /\ + set_key_schedule s key2_p k2_0 k2_1 k2_2 k2_3 k2_4 k2_5 k2_6 k2_7 k2_8 k2_9 k2_10 k2_11 k2_12 k2_13 k2_14 ) + (\s. read PC s = returnaddress /\ + byte_list_at (aes256_xts_encrypt pt_in (val len) iv + [k1_0; k1_1; k1_2; k1_3; k1_4; k1_5; k1_6; k1_7; k1_8; k1_9; k1_10; k1_11; k1_12; k1_13; k1_14] + [k2_0; k2_1; k2_2; k2_3; k2_4; k2_5; k2_6; k2_7; k2_8; k2_9; k2_10; k2_11; k2_12; k2_13; k2_14]) + ctxt_p len s ) + (MAYCHANGE_REGS_AND_FLAGS_PERMITTED_BY_ABI,, + MAYCHANGE [memory :> bytes(ctxt_p, val len); + memory :> bytes(word_sub stackpointer (word 96), 96)])`, + REWRITE_TAC[byte_list_at; set_key_schedule; + fst AES256_XTS_ENCRYPT_EXEC] THEN + (* ~pre_post_nsteps:(7,7): 7 instructions before and after program body + for handling stack. + 96: the byte size occupied on stack for storing preserved registers *) + ARM_ADD_RETURN_STACK_TAC + ~pre_post_nsteps:(7,7) AES256_XTS_ENCRYPT_EXEC + (REWRITE_RULE[byte_list_at; set_key_schedule; + fst AES256_XTS_ENCRYPT_EXEC] AES256_XTS_ENCRYPT_CORRECT) + `[X19; X20; X21; X22; D8; D9; D10; D11; D12; D13; D14; D15]` 96 + );; diff --git a/arm/proofs/base.ml b/arm/proofs/base.ml index a9021f9f0..5c3c6046c 100644 --- a/arm/proofs/base.ml +++ b/arm/proofs/base.ml @@ -60,7 +60,7 @@ extra_word_CONV := (* Additional Cryptographic AES intrinsics *) (* ------------------------------------------------------------------------- *) -loadt "arm/proofs/aes.ml";; +loadt "arm/proofs/utils/aes.ml";; extra_word_CONV := [AESE_REDUCE_CONV; AESMC_REDUCE_CONV; AESD_REDUCE_CONV; AESIMC_REDUCE_CONV] diff --git a/arm/proofs/simulator_iclasses.ml b/arm/proofs/simulator_iclasses.ml index 11221bef6..51f3b9a62 100644 --- a/arm/proofs/simulator_iclasses.ml +++ b/arm/proofs/simulator_iclasses.ml @@ -458,6 +458,9 @@ let check_insns () = "00111000010xxxxxxxxx11xxxxxxxxxx"; "0011100101xxxxxxxxxxxxxxxxxxxxxx"; + (*** ldrb / strb (shifted register, no shift S = 0) ***) + "001110000x1xxxxxxxx010xxxxxxxxxx"; + (*** ld1 (1 register, Post-immediate offset) ***) "0x001100110111110111xxxxxxxxxxxx"; diff --git a/arm/proofs/specifications.txt b/arm/proofs/specifications.txt index c5fc448bd..a42a78736 100644 --- a/arm/proofs/specifications.txt +++ b/arm/proofs/specifications.txt @@ -1,3 +1,5 @@ +AES_XTS_DECRYPT_SUBROUTINE_CORRECT +AES_XTS_ENCRYPT_SUBROUTINE_CORRECT BIGNUM_ADD_P25519_SUBROUTINE_CORRECT BIGNUM_ADD_P256K1_SUBROUTINE_CORRECT BIGNUM_ADD_P256_SUBROUTINE_CORRECT diff --git a/arm/proofs/subroutine_signatures.ml b/arm/proofs/subroutine_signatures.ml index dfc6c3869..abd89babc 100644 --- a/arm/proofs/subroutine_signatures.ml +++ b/arm/proofs/subroutine_signatures.ml @@ -1,4 +1,50 @@ let subroutine_signatures = [ +("aes_xts_decrypt", + ([(*args*) + ("in", "uint8_t*", (*is const?*)"true"); + ("out", "uint8_t*", (*is const?*)"false"); + ("length", "size_t", (*is const?*)"false"); + ("key1", "s2n_bignum_AES_KEY*", (*is const?*)"true"); + ("key2", "s2n_bignum_AES_KEY*", (*is const?*)"true"); + ("iv", "uint8_t[static 16]", (*is const?*)"true"); + ], + "void", + [(* input buffers *) + ("in", "length"(* num elems *), 1(* elem bytesize *)); + ("key1", "244"(* num elems *), 1(* elem bytesize *)); + ("key2", "244"(* num elems *), 1(* elem bytesize *)); + ("iv", "16"(* num elems *), 1(* elem bytesize *)); + ], + [(* output buffers *) + ("out", "length"(* num elems *), 1(* elem bytesize *)); + ], + [(* temporary buffers *) + ]) +); + +("aes_xts_encrypt", + ([(*args*) + ("in", "uint8_t*", (*is const?*)"true"); + ("out", "uint8_t*", (*is const?*)"false"); + ("length", "size_t", (*is const?*)"false"); + ("key1", "s2n_bignum_AES_KEY*", (*is const?*)"true"); + ("key2", "s2n_bignum_AES_KEY*", (*is const?*)"true"); + ("iv", "uint8_t[static 16]", (*is const?*)"true"); + ], + "void", + [(* input buffers *) + ("in", "length"(* num elems *), 1(* elem bytesize *)); + ("key1", "244"(* num elems *), 1(* elem bytesize *)); + ("key2", "244"(* num elems *), 1(* elem bytesize *)); + ("iv", "16"(* num elems *), 1(* elem bytesize *)); + ], + [(* output buffers *) + ("out", "length"(* num elems *), 1(* elem bytesize *)); + ], + [(* temporary buffers *) + ]) +); + ("bignum_add", ([(*args*) ("p", "uint64_t", (*is const?*)"false"); diff --git a/arm/proofs/aes.ml b/arm/proofs/utils/aes.ml similarity index 100% rename from arm/proofs/aes.ml rename to arm/proofs/utils/aes.ml diff --git a/arm/proofs/utils/aes_decrypt_spec.ml b/arm/proofs/utils/aes_decrypt_spec.ml new file mode 100644 index 000000000..620eb2631 --- /dev/null +++ b/arm/proofs/utils/aes_decrypt_spec.ml @@ -0,0 +1,144 @@ +(* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0 + *) +(* ====================================================================================== *) +(* AES-256 decryption spec https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf. *) +(* ====================================================================================== *) + +needs "common/aes.ml";; + +(* let pp_print_num fmt tm = + let n = dest_numeral tm in + pp_print_string fmt (string_of_num_hex n) in +install_user_printer("pp_print_num",pp_print_num);; +*) + +(* +procedure EQINVCIPHER(in, Nr, dw) +2: state ← in +3: state ← ADDROUNDKEY(state,dw[4 ∗Nr..4 ∗Nr +3]) +4: for round from Nr −1 downto 1 do +5: state ← INVSUBBYTES(state) +6: state ← INVSHIFTROWS(state) +7: state ← INVMIXCOLUMNS(state) +8: state ← ADDROUNDKEY(state,dw[4 ∗ round..4 ∗ round +3]) +9: end for +10: state ← INVSUBBYTES(state) +11: state ← INVSHIFTROWS(state) +12: state ← ADDROUNDKEY(state,dw[0..3]) +13: return state +14: end procedure +*) + +let aes256_decrypt_round = new_definition + `aes256_decrypt_round (block:int128) (round_key:int128) = + let res2 = aes_inv_shift_rows block in + let res3 = aes_sub_bytes joined_GF2_inv res2 in + let res1 = aes_inv_mix_columns res3 in + word_xor res1 round_key + `;; + +let aes256_decrypt = new_definition + `aes256_decrypt (block:int128) (key_schedule:int128 list) = + let res0 = word_xor block (EL 0 key_schedule) in + let res1 = aes256_decrypt_round res0 (EL 1 key_schedule) in + let res2 = aes256_decrypt_round res1 (EL 2 key_schedule) in + let res3 = aes256_decrypt_round res2 (EL 3 key_schedule) in + let res4 = aes256_decrypt_round res3 (EL 4 key_schedule) in + let res5 = aes256_decrypt_round res4 (EL 5 key_schedule) in + let res6 = aes256_decrypt_round res5 (EL 6 key_schedule) in + let res7 = aes256_decrypt_round res6 (EL 7 key_schedule) in + let res8 = aes256_decrypt_round res7 (EL 8 key_schedule) in + let res9 = aes256_decrypt_round res8 (EL 9 key_schedule) in + let res10 = aes256_decrypt_round res9 (EL 10 key_schedule) in + let res11 = aes256_decrypt_round res10 (EL 11 key_schedule) in + let res12 = aes256_decrypt_round res11 (EL 12 key_schedule) in + let res13 = aes256_decrypt_round res12 (EL 13 key_schedule) in + let res14 = aes_inv_shift_rows res13 in + let res15 = aes_sub_bytes joined_GF2_inv res14 in + word_xor res15 (EL 14 key_schedule) + `;; + +let AESDEC_ROUND_HELPER_CONV = + REWRITE_CONV [aes256_decrypt_round] THENC + AES_INV_SHIFT_ROWS_CONV THENC + AES_SUB_BYTES_CONV THENC + AES_INV_MIX_COLUMNS_CONV THENC + DEPTH_CONV (WORD_RED_CONV ORELSEC NUM_RED_CONV);; + +let AESDEC_ROUND_REDUCE_CONV tm = + match tm with + Comb(Comb(Const("aes256_decrypt_round",_), + Comb(Const("word",_),state)), + Comb(Const("word",_),roundkey)) + when is_numeral state && is_numeral roundkey -> AESDEC_ROUND_HELPER_CONV tm + | _ -> failwith "AESDEC_ROUND_REDUCE_CONV: inapplicable";; + +(* +Test case from AWS-LC + +Round keys: +0x36DE686D3CC21A37E97909BFCC79FC24 +0x6E0158255FE2E9FC2FAACEBFFFD1F134 +0x84E680DC46B771750A354C38EB48165E +0x31E3B1D970482743D07B3F8B8005A3C8 +0xC251F1A94C823D4DE17D5A66138E70B5 +0x41AB969AA03318C8507E9C43A37BDA74 +0x8ED3CCE4ADFF672BF2F32AD31597A63C +0xE1988E52F04D848BF3054637F3C45FF8 +0x232CABCF5F0C4DF8E7648CEF9A4069DE +0x11D50AD90348C2BC00C119CF1658D5AE +0x7C20E637B868C1177D24E531BD68C615 +0x129DC8650389DB731699CC610F85D77F +0xC4482720C54C2426C04C2324C940282A +0x1114131615101712191C1B1E1D181F1A +0x0F0E0D0C0B0A09080706050403020100 + +ciphertext: +0x8960494b9049fceabf456751cab7a28e + +plaintext: +0xffeeddccbbaa99887766554433221100 +*) + +(* These are the round keys with the bytes reversed to become little endian *) +let DEC_ROUND_KEYS = new_definition `DEC_ROUND_KEYS:int128 list = + [ word 0x36DE686D3CC21A37E97909BFCC79FC24 + ; word 0x6E0158255FE2E9FC2FAACEBFFFD1F134 + ; word 0x84E680DC46B771750A354C38EB48165E + ; word 0x31E3B1D970482743D07B3F8B8005A3C8 + ; word 0xC251F1A94C823D4DE17D5A66138E70B5 + ; word 0x41AB969AA03318C8507E9C43A37BDA74 + ; word 0x8ED3CCE4ADFF672BF2F32AD31597A63C + ; word 0xE1988E52F04D848BF3054637F3C45FF8 + ; word 0x232CABCF5F0C4DF8E7648CEF9A4069DE + ; word 0x11D50AD90348C2BC00C119CF1658D5AE + ; word 0x7C20E637B868C1177D24E531BD68C615 + ; word 0x129DC8650389DB731699CC610F85D77F + ; word 0xC4482720C54C2426C04C2324C940282A + ; word 0x1114131615101712191C1B1E1D181F1A + ; word 0x0F0E0D0C0B0A09080706050403020100 + ]`;; + +let EL_15_128_CLAUSES = + let pat = `EL n [x0;x1;x2;x3;x4;x5;x6;x7;x8;x9;x10;x11;x12;x13;x14]:128 word` in + map (fun n -> EL_CONV(subst [mk_small_numeral n,`n:num`] pat)) (0--14);; + +let AESDEC_HELPER_CONV = + REWR_CONV aes256_decrypt THENC + REWRITE_CONV EL_15_128_CLAUSES THENC + REPEATC let_CONV THENC + DEPTH_CONV (WORD_RED_CONV ORELSEC NUM_RED_CONV) THENC + DEPTH_CONV AESDEC_ROUND_REDUCE_CONV THENC + AES_INV_SHIFT_ROWS_CONV THENC + AES_SUB_BYTES_CONV THENC + DEPTH_CONV (WORD_RED_CONV ORELSEC NUM_RED_CONV) + ;; + +(* +time prove (`aes256_decrypt + (word 0x8960494b9049fceabf456751cab7a28e) + DEC_ROUND_KEYS = word 0xffeeddccbbaa99887766554433221100`, + CONV_TAC(LAND_CONV (REWRITE_CONV [DEC_ROUND_KEYS] THENC AESDEC_HELPER_CONV)) THEN REFL_TAC);; +*) \ No newline at end of file diff --git a/arm/proofs/utils/aes_encrypt_spec.ml b/arm/proofs/utils/aes_encrypt_spec.ml new file mode 100644 index 000000000..ca1fbdc45 --- /dev/null +++ b/arm/proofs/utils/aes_encrypt_spec.ml @@ -0,0 +1,181 @@ +(* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0 + *) +(* ====================================================================================== *) +(* AES-256 encryption spec https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf. *) +(* ====================================================================================== *) +needs "common/aes.ml";; + +(* let pp_print_num fmt tm = + let n = dest_numeral tm in + pp_print_string fmt (string_of_num_hex n) in +install_user_printer("pp_print_num",pp_print_num);; +*) + +(* +// NIST FIPS 197 - Advanced Encryption Standard (AES) +// `Nb` = number of columns in the state (4 for AES) +// `Nr` = number of rounds (14 for AES-256) + +Cipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)]) + +begin + +byte state[4,Nb] +state = in + +AddRoundKey(state, w[0, Nb-1]) // See Sec. 5.1.4 + +for round = 1 step 1 to Nr–1 + +SubBytes(state) // See Sec. 5.1.1 +ShiftRows(state) // See Sec. 5.1.2 +MixColumns(state) // See Sec. 5.1.3 +AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) + +end for + +SubBytes(state) +ShiftRows(state) +AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) + +out = state + +end +*) + +(* Note: In the spec, SubBytes precedes ShiftRows, but the instruction + definition of aese in arm/proofs/aes.ml has them interchanged. + This is possible but requires a modified lookup table, joined_GF2, + from the specs. + We will follow the same pattern below as the instruction definition + TODO: prove the equivalence with the spec later.*) + +let aes256_encrypt_round = new_definition + `aes256_encrypt_round (block:int128) (round_key:int128) = + let res2 = aes_shift_rows block in + let res3 = aes_sub_bytes joined_GF2 res2 in + let res1 = aes_mix_columns res3 in + word_xor res1 round_key + `;; + +let aes256_encrypt = new_definition + `aes256_encrypt (block:int128) (key_schedule:int128 list) = + let res0 = word_xor block (EL 0 key_schedule) in + let res1 = aes256_encrypt_round res0 (EL 1 key_schedule) in + let res2 = aes256_encrypt_round res1 (EL 2 key_schedule) in + let res3 = aes256_encrypt_round res2 (EL 3 key_schedule) in + let res4 = aes256_encrypt_round res3 (EL 4 key_schedule) in + let res5 = aes256_encrypt_round res4 (EL 5 key_schedule) in + let res6 = aes256_encrypt_round res5 (EL 6 key_schedule) in + let res7 = aes256_encrypt_round res6 (EL 7 key_schedule) in + let res8 = aes256_encrypt_round res7 (EL 8 key_schedule) in + let res9 = aes256_encrypt_round res8 (EL 9 key_schedule) in + let res10 = aes256_encrypt_round res9 (EL 10 key_schedule) in + let res11 = aes256_encrypt_round res10 (EL 11 key_schedule) in + let res12 = aes256_encrypt_round res11 (EL 12 key_schedule) in + let res13 = aes256_encrypt_round res12 (EL 13 key_schedule) in + let res14 = aes_shift_rows res13 in + let res15 = aes_sub_bytes joined_GF2 res14 in + word_xor res15 (EL 14 key_schedule) + `;; + +let AESENC_ROUND_HELPER_CONV = + REWRITE_CONV [aes256_encrypt_round] THENC + AES_SHIFT_ROWS_CONV THENC + AES_SUB_BYTES_CONV THENC + AES_MIX_COLUMNS_CONV THENC + DEPTH_CONV (WORD_RED_CONV ORELSEC NUM_RED_CONV);; + +let AESENC_ROUND_REDUCE_CONV tm = + match tm with + Comb(Comb(Const("aes256_encrypt_round",_), + Comb(Const("word",_),state)), + Comb(Const("word",_),roundkey)) + when is_numeral state && is_numeral roundkey -> AESENC_ROUND_HELPER_CONV tm + | _ -> failwith "AESENC_ROUND_REDUCE_CONV: inapplicable";; + +(* +prove(`aes256_encrypt_round (word 0x7b5b54657374566563746f725d53475d) + (word 0x48692853686179295b477565726f6e5d) = + word 0xa8311c2f9fdba3c58b104b58ded7e595`, + CONV_TAC(LAND_CONV AESENC_ROUND_REDUCE_CONV) THEN REFL_TAC);; + +prove(`aes256_encrypt_round (word 0xAB60EEF6E1D04EC228EE8A3BF255FC0B) + (word 0xF4DF1409A310982DD708613B072C351F) = + word 0x416EAD9670A2C6D71CFE3FCCB03F10D9`, + CONV_TAC(LAND_CONV AESENC_ROUND_REDUCE_CONV) THEN REFL_TAC);; +*) + +(* +https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_Core256.pdf +has the same test vector as +https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf +The vector values appear in the code in reverse byte order to be little endian. + +AES256_TEST_KEY[] = +603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +AES_TEST_VECTOR[] = +6BC1BEE22E409F96E93D7E117393172A +ECB256_EXPECTED[] = +F3EED1BDB5D2A03C064B5A7E3DB181F8 + +Round keys in big endian generated from the key via a python code +Round 0: 603DEB1015CA71BE2B73AEF0857D7781 +Round 1: 1F352C073B6108D72D9810A30914DFF4 +Round 2: 9BA354118E6925AFA51A8B5F2067FCDE +Round 3: A8B09C1A93D194CDBE49846EB75D5B9A +Round 4: D59AECB85BF3C917FEE94248DE8EBE96 +Round 5: B5A9328A2678A647983122292F6C79B3 +Round 6: 812C81ADDADF48BA24360AF2FAB8B464 +Round 7: 98C5BFC9BEBD198E268C3BA709E04214 +Round 8: 68007BACB2DF331696E939E46C518D80 +Round 9: C814E20476A9FB8A5025C02D59C58239 +Round 10: DE1369676CCC5A71FA2563959674EE15 +Round 11: 5886CA5D2E2F31D77E0AF1FA27CF73C3 +Round 12: 749C47AB18501DDAE2757E4F7401905A +Round 13: CAFAAAE3E4D59B349ADF6ACEBD10190D +Round 14: FE4890D1E6188D0B046DF344706C631E +*) + +(* These are the ound keys with the bytes reversed to become little endian *) +let ROUND_KEYS = new_definition `ROUND_KEYS:int128 list = + [ word 0x81777D85F0AE732BBE71CA1510EB3D60 + ; word 0xF4DF1409A310982DD708613B072C351F + ; word 0xDEFC67205F8B1AA5AF25698E1154A39B + ; word 0x9A5B5DB76E8449BECD94D1931A9CB0A8 + ; word 0x96BE8EDE4842E9FE17C9F35BB8EC9AD5 + ; word 0xB3796C2F2922319847A678268A32A9B5 + ; word 0x64B4B8FAF20A3624BA48DFDAAD812C81 + ; word 0x1442E009A73B8C268E19BDBEC9BFC598 + ; word 0x808D516CE439E9961633DFB2AC7B0068 + ; word 0x3982C5592DC025508AFBA97604E214C8 + ; word 0x15EE7496956325FA715ACC6C676913DE + ; word 0xC373CF27FAF10A7ED7312F2E5DCA8658 + ; word 0x5A9001744F7E75E2DA1D5018AB479C74 + ; word 0x0D1910BDCE6ADF9A349BD5E4E3AAFACA + ; word 0x1E636C7044F36D040B8D18E6D19048FE + ]`;; + + +let EL_15_128_CLAUSES = + let pat = `EL n [x0;x1;x2;x3;x4;x5;x6;x7;x8;x9;x10;x11;x12;x13;x14]:128 word` in + map (fun n -> EL_CONV(subst [mk_small_numeral n,`n:num`] pat)) (0--14);; + +let AESENC_HELPER_CONV = + REWRITE_CONV [aes256_encrypt] THENC + REWRITE_CONV EL_15_128_CLAUSES THENC + REPEATC let_CONV THENC + DEPTH_CONV (WORD_RED_CONV ORELSEC NUM_RED_CONV) THENC + DEPTH_CONV AESENC_ROUND_REDUCE_CONV THENC + AES_SHIFT_ROWS_CONV THENC + AES_SUB_BYTES_CONV THENC + DEPTH_CONV (WORD_RED_CONV ORELSEC NUM_RED_CONV);; + +(* +time prove (`aes256_encrypt + (word 0x2A179373117E3DE9969F402EE2BEC16B) + ROUND_KEYS = word 0xF881B13D7E5A4B063CA0D2B5BDD1EEF3`, + CONV_TAC(LAND_CONV (REWRITE_CONV [ROUND_KEYS] THENC AESENC_HELPER_CONV)) THEN REFL_TAC);; +*) diff --git a/arm/proofs/utils/aes_xts_common.ml b/arm/proofs/utils/aes_xts_common.ml new file mode 100644 index 000000000..15f2b5041 --- /dev/null +++ b/arm/proofs/utils/aes_xts_common.ml @@ -0,0 +1,2443 @@ +(* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0 + *) + +(* BOZO: Do I need all of base?*) +needs "arm/proofs/base.ml";; +needs "arm/proofs/utils/aes_xts_encrypt_spec.ml";; +needs "arm/proofs/utils/aes_xts_decrypt_spec.ml";; + +(**********************************************************************) +(** Common definitions **) + +(* For defining the input and output buffers of arbitrary length len. + byte_list_at is adapted from Amanda's code at + https://github.com/amanda-zx/s2n-bignum/blob/ed25519/arm/sha512/utils.ml *) +let byte_list_at = define + `byte_list_at (m : byte list) (m_p : int64) (len: int64) s = + ! i. i < val len ==> read (memory :> bytes8(word_add m_p (word i))) s = EL i m`;; + +(** Function for initializing key schedule *) +let set_key_schedule = new_definition + `set_key_schedule (s:armstate) (key_ptr:int64) (k0:int128) + (k1:int128) (k2:int128) (k3:int128) (k4:int128) (k5:int128) + (k6:int128) (k7:int128) (k8:int128) (k9:int128) (ka:int128) + (kb:int128) (kc:int128) (kd:int128) (ke:int128) : bool = + (read(memory :> bytes128 key_ptr) s = k0 /\ + read(memory :> bytes128 (word_add key_ptr (word 16))) s = k1 /\ + read(memory :> bytes128 (word_add key_ptr (word 32))) s = k2 /\ + read(memory :> bytes128 (word_add key_ptr (word 48))) s = k3 /\ + read(memory :> bytes128 (word_add key_ptr (word 64))) s = k4 /\ + read(memory :> bytes128 (word_add key_ptr (word 80))) s = k5 /\ + read(memory :> bytes128 (word_add key_ptr (word 96))) s = k6 /\ + read(memory :> bytes128 (word_add key_ptr (word 112))) s = k7 /\ + read(memory :> bytes128 (word_add key_ptr (word 128))) s = k8 /\ + read(memory :> bytes128 (word_add key_ptr (word 144))) s = k9 /\ + read(memory :> bytes128 (word_add key_ptr (word 160))) s = ka /\ + read(memory :> bytes128 (word_add key_ptr (word 176))) s = kb /\ + read(memory :> bytes128 (word_add key_ptr (word 192))) s = kc /\ + read(memory :> bytes128 (word_add key_ptr (word 208))) s = kd /\ + read(memory :> bytes128 (word_add key_ptr (word 224))) s = ke /\ + read(memory :> bytes32 (word_add key_ptr (word 240))) s = word 14)`;; + +(** Define length of rest of input in bytes after the loop *) +let acc_len = new_definition +`acc_len (i:int64) (len:int64) : num = + if val i * 0x50 + 0x40 = val len then 0x50 * val i + 0x40 + else + if val i * 0x50 + 0x30 = val len then 0x50 * val i + 0x30 + else + if val i * 0x50 + 0x20 = val len then 0x50 * val i + 0x20 + else + if val i * 0x50 + 0x10 = val len then 0x50 * val i + 0x10 + else 0x50 * val i`;; + +(** Define length of rest of input in blocks after the loop *) +let acc_blocks = new_definition +`acc_blocks (i:int64) (len:int64) (last:bool) : num = + if val i * 0x50 + 0x40 = val len then val i * 0x5 + 4 + else + if val i * 0x50 + 0x30 = val len then val i * 0x5 + 3 + else + if val i * 0x50 + 0x20 = val len then val i * 0x5 + 2 + else + if val i * 0x50 + 0x10 = val len then val i * 0x5 + 1 + else val i * 0x5`;; + +(* The cipher-stealing invariant is the block read at ctxt_p + curr_len - 16 where Cm is being replaced by Pm + one byte at a time with a decreasing offset i from the beginning of the block. + Differs from decrypt in that, there, it's curr_len. + The following is copied from decrypt and will be instantiated with l1_curr_len (= curr_len-16) instead of curr_len *) +let cipher_stealing_inv = new_definition +`cipher_stealing_inv (i:num) (curr_len:num) (tail_len:num) (PP:int128) (ct:byte list): int128 = + bytes_to_int128( + APPEND (SUB_LIST (0, i) (int128_to_bytes PP)) + (APPEND (SUB_LIST (i, tail_len - i) (SUB_LIST (curr_len + 16, tail_len) ct)) + (SUB_LIST (tail_len, 16 - tail_len) (int128_to_bytes PP))))`;; + + +(**********************************************************************) +(** Common List Lemmas **) + +let SUB_LIST_SUCSPLIT = prove( + `!(l:A list) n p. SUB_LIST(p,SUC n) l = APPEND (SUB_LIST(p,1) l) (SUB_LIST(p+1,n) l)`, + REPEAT STRIP_TAC THEN + REWRITE_TAC [ARITH_RULE `SUC n = 1 + n`] THEN + REWRITE_TAC [SUB_LIST_SPLIT] +);; + +let HD_SUB_LIST_CONS = prove + (`!(h:A) (t:A list) n. 0 < n ==> HD (SUB_LIST (0,n) (CONS h t)) = h`, + REPEAT GEN_TAC THEN STRIP_TAC THEN + MP_TAC(SPEC `n:num` num_CASES) THEN + ASM_SIMP_TAC[ARITH_RULE `0 < n ==> ~(n = 0)`] THEN + DISCH_THEN(X_CHOOSE_THEN `m:num` SUBST_ALL_TAC) THEN + REWRITE_TAC[SUB_LIST_CLAUSES; HD]);; + +let HD_SUB_LIST_CONS_GENERAL = prove( + `!p n (l:A list). p < LENGTH l /\ 0 < n ==> HD (SUB_LIST (p,n) l) = EL p l`, + INDUCT_TAC THENL + [ + GEN_TAC THEN + LIST_INDUCT_TAC THENL + [ + REWRITE_TAC[LENGTH] THEN ARITH_TAC; + REPEAT STRIP_TAC THEN + REWRITE_TAC[EL; HD] THEN + MP_TAC (SPECL [`h:A`; `t:A list`; `n:num`] HD_SUB_LIST_CONS) THEN + ASM_SIMP_TAC[] + ]; ALL_TAC + ] THEN + GEN_TAC THEN + LIST_INDUCT_TAC THENL + [ + REWRITE_TAC[LENGTH] THEN ARITH_TAC; + REPEAT STRIP_TAC THEN + REWRITE_TAC[SUB_LIST_CLAUSES] THEN + REWRITE_TAC[EL; TL] THEN + FIRST_X_ASSUM (fun th -> MATCH_MP_TAC (SPECL [`n:num`; `t:A list`] th)) THEN + ASM_SIMP_TAC[] THEN + UNDISCH_TAC `SUC p < LENGTH (CONS h (t:A list))` THEN + REWRITE_TAC[LENGTH] THEN + ARITH_TAC + ] +);; + +let TL_SUB_LIST_CONS = prove +(`!(h:A) (t:A list) n. 0 < n ==> TL (SUB_LIST (0,n) (CONS h t)) = SUB_LIST (0, n - 1) t`, + REPEAT GEN_TAC THEN STRIP_TAC THEN + MP_TAC(SPEC `n:num` num_CASES) THEN + ASM_SIMP_TAC[ARITH_RULE `0 < n ==> ~(n = 0)`] THEN + DISCH_THEN(X_CHOOSE_THEN `m:num` SUBST_ALL_TAC) THEN + REWRITE_TAC[SUB_LIST_CLAUSES; TL] THEN + REWRITE_TAC[ARITH_RULE `SUC m - 1 = m`]);; + +let TL_SUB_LIST_CONS_GENERAL = prove( + `!p n (l:A list). p < LENGTH l ==> 0 < n + ==> TL (SUB_LIST (p, n) l) = SUB_LIST (p + 1, n - 1) l`, + INDUCT_TAC THENL + [ + GEN_TAC THEN + LIST_INDUCT_TAC THENL + [ + REWRITE_TAC[LENGTH] THEN ARITH_TAC; + CONV_TAC NUM_REDUCE_CONV THEN + REPEAT STRIP_TAC THEN + MP_TAC (SPECL [`h:A`; `t:A list`; `n:num`] TL_SUB_LIST_CONS) THEN + ASM_SIMP_TAC[num_CONV `1`; SUB_LIST_CLAUSES] + ]; ALL_TAC + ] THEN + GEN_TAC THEN + LIST_INDUCT_TAC THENL + [ + REWRITE_TAC[LENGTH] THEN ARITH_TAC; + REPEAT STRIP_TAC THEN + REWRITE_TAC[ARITH_RULE `SUC p + 1 = SUC (p + 1)`] THEN + REWRITE_TAC[SUB_LIST_CLAUSES] THEN + FIRST_X_ASSUM (fun th -> MP_TAC (SPECL [`n:num`; `t:A list`] th)) THEN + SUBGOAL_THEN `p < LENGTH (t:A list)` ASSUME_TAC THENL + [ UNDISCH_TAC `SUC p < LENGTH (CONS h (t:A list))` THEN + REWRITE_TAC[LENGTH] THEN ARITH_TAC + ; ALL_TAC] THEN + ASM_SIMP_TAC[] + ] +);; + +let EL_SUB_LIST_TRIVIAL = prove( + `!i n (l:A list). i < LENGTH l /\ 0 < n ==> EL 0x0 (SUB_LIST (i, n) l) = EL i l`, + REWRITE_TAC[EL] THEN + SIMP_TAC[HD_SUB_LIST_CONS_GENERAL] +);; + +let EL_SUB_LIST = prove( + `!(i:num) n (l:A list). i < n /\ n <= LENGTH l ==> + EL i (SUB_LIST (0, n) l) = EL i l`, + INDUCT_TAC THENL + [ (* i = 0 *) + ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN + LIST_INDUCT_TAC THENL + [ + REPEAT STRIP_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_TRIVIAL] THEN + REWRITE_TAC[LENGTH] THEN + ARITH_TAC; ALL_TAC + ] THEN + REPEAT STRIP_TAC THEN + IMP_REWRITE_TAC[EL; HD; HD_SUB_LIST_CONS]; + ALL_TAC + ] THEN + (* i != 0 *) + ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN + LIST_INDUCT_TAC THENL + [ + REPEAT STRIP_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_TRIVIAL] THEN + REWRITE_TAC[LENGTH] THEN + ARITH_TAC; ALL_TAC + ] THEN + REPEAT STRIP_TAC THEN + REWRITE_TAC[EL; TL] THEN + IMP_REWRITE_TAC[TL_SUB_LIST_CONS] THEN + REPEAT CONJ_TAC THENL + [ ASM_SIMP_TAC[ARITH_RULE `SUC i < n ==> i < n - 1`]; + SUBGOAL_THEN `LENGTH (CONS h (t:A list)) = SUC (LENGTH t)` ASSUME_TAC THENL + [ REWRITE_TAC[LENGTH]; ALL_TAC ] THEN + ASM_ARITH_TAC; + MP_TAC (ARITH_RULE `SUC i < n ==> 0 < n`) THEN + ASM_SIMP_TAC[] + ] +);; + +let EL_SUB_LIST_GENERAL = prove( + `!p (l:A list) i n. i >= p /\ i < p + n /\ p + n <= LENGTH l ==> + EL (i - p) (SUB_LIST (p, n) l) = EL i l`, + INDUCT_TAC THENL + [ IMP_REWRITE_TAC[ADD; SUB_0; EL_SUB_LIST]; + ALL_TAC + ] THEN + LIST_INDUCT_TAC THENL + [ REWRITE_TAC[SUB_LIST_CLAUSES; LENGTH] THEN + REPEAT STRIP_TAC THEN + ASM_ARITH_TAC; + ALL_TAC + ] THEN + REWRITE_TAC[LENGTH] THEN + REPEAT STRIP_TAC THEN + REWRITE_TAC[SUB_LIST_CLAUSES] THEN + SUBGOAL_THEN `EL i (CONS h (t:A list)) = EL (i - 1) t` SUBST1_TAC THENL + [ SUBGOAL_THEN `i = SUC (i - 1)` SUBST1_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[EL; TL] THEN + AP_THM_TAC THEN AP_TERM_TAC THEN + ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[ARITH_RULE `i - SUC p = i - 1 - p`] THEN + FIRST_X_ASSUM (fun th -> MP_TAC (SPECL [`t:A list`; `(i - 1):num`; `n:num`] th)) THEN + ANTS_TAC THENL [ ASM_ARITH_TAC; ALL_TAC ] THEN + SIMP_TAC[] +);; + +let EL_SUB_LIST_SHIFT = prove( + `!(i:num) p (l:A list) n. 0 < i /\ i < n /\ n <= LENGTH l - p ==> + EL (i - 1) (SUB_LIST (p + 1, n - 1) l) = EL i (SUB_LIST (p, n) l)`, + REPEAT STRIP_TAC THEN + SUBGOAL_THEN `EL i (SUB_LIST (p, n) (l:A list)) = EL (SUC (i - 1)) (SUB_LIST (p, SUC (n - 1)) l)` SUBST1_TAC THENL + [ IMP_REWRITE_TAC[ARITH_RULE `0 < i ==> SUC (i - 1) = i`] THEN + ASM_ARITH_TAC; ALL_TAC ] THEN + DISJ_CASES_TAC (ISPEC `l:(A)list` list_CASES) THENL [ + FIRST_X_ASSUM SUBST_ALL_TAC THEN + UNDISCH_TAC `n <= LENGTH ([]:A list) - p` THEN + REWRITE_TAC[LENGTH] THEN + ASM_ARITH_TAC; ALL_TAC + ] THEN + + REPEAT_N 2 (FIRST_X_ASSUM CHOOSE_TAC) THEN + FIRST_X_ASSUM SUBST_ALL_TAC THEN + REWRITE_TAC[EL; TL] THEN + IMP_REWRITE_TAC[TL_SUB_LIST_CONS_GENERAL] THEN + IMP_REWRITE_TAC[ARITH_RULE `0 < n ==> SUC (n - 1) = n`] THEN + ASM_ARITH_TAC + );; + + +let SUB_LIST_APPEND_RIGHT_LEMMA = prove( + `!(x:A list) y n m. LENGTH x = n ==> SUB_LIST (n,m) (APPEND x y) = SUB_LIST (0,m) y`, + LIST_INDUCT_TAC THENL + [ REPEAT GEN_TAC THEN + SIMP_TAC[CONJUNCT1 LENGTH; APPEND; SUB_LIST_CLAUSES]; + + ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN + INDUCT_TAC THENL[ + SIMP_TAC[LENGTH_EQ_NIL] THEN REWRITE_TAC[APPEND]; + ASM_SIMP_TAC[APPEND; LENGTH; SUB_LIST_CLAUSES; SUC_INJ]]]);; + +let SUB_LIST_APPEND_RIGHT_GENERAL = prove( + `!(x:A list) y n m p. LENGTH x = p ==> n >= p ==> + SUB_LIST (n,m) (APPEND x y) = SUB_LIST (n - p,m) y`, + LIST_INDUCT_TAC THENL + [ + REPEAT GEN_TAC THEN + SIMP_TAC[CONJUNCT1 LENGTH; APPEND; SUB_LIST_CLAUSES] THEN + DISCH_THEN (fun th -> REWRITE_TAC[GSYM th]) THEN + REWRITE_TAC[SUB_0]; + + ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN + INDUCT_TAC THENL + [ + REPEAT STRIP_TAC THEN + SUBGOAL_THEN `p = 0` SUBST_ALL_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `CONS h t = ([]:A list)` ASSUME_TAC THENL + [ UNDISCH_TAC `LENGTH (CONS h (t:A list)) = 0` THEN + SIMP_TAC[LENGTH_EQ_NIL]; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + REWRITE_TAC[APPEND]; + + REPEAT STRIP_TAC THEN + SUBGOAL_THEN `p > 0` ASSUME_TAC THENL + [ UNDISCH_TAC `LENGTH (CONS h (t:A list)) = p` THEN + ASM_REWRITE_TAC[LENGTH] THEN + MP_TAC (SPEC `LENGTH (t:A list)` (ARITH_RULE `!x. SUC x > 0`)) THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `LENGTH (t:A list) = p - 1` ASSUME_TAC THENL + [ UNDISCH_TAC `LENGTH (CONS h (t:A list)) = p` THEN + ASM_REWRITE_TAC[LENGTH] THEN + MP_TAC (SPECL [`LENGTH (t:A list)`; `p:num`] (ARITH_RULE `!n m. SUC n = m ==> n = m - 1`)) THEN + SIMP_TAC[]; ALL_TAC] THEN + SUBGOAL_THEN `n >= p - 1` ASSUME_TAC THENL + [ MP_TAC (ARITH_RULE `SUC n >= p /\ p > 0 ==> n >= p - 1`) THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `SUC n - p = n - (p - 1)` ASSUME_TAC THENL + [ MP_TAC (ARITH_RULE `SUC n >= p /\ p > 0 ==> SUC n - p = n - (p - 1)`) THEN + ASM_ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[APPEND; LENGTH; SUB_LIST_CLAUSES; SUC_INJ] THEN + FIRST_X_ASSUM (fun th -> MP_TAC (SPECL [`y:A list`; `n:num`; `m:num`; `(p-1):num`] th)) THEN + ASM_SIMP_TAC[] + ] + ] +);; + +let SUB_LIST_LENGTH_IMPLIES = prove( + `!(l:A list) n. LENGTH l = n ==> SUB_LIST(0,n) l = l`, + REPEAT STRIP_TAC THEN + UNDISCH_THEN `LENGTH (l:A list) = n` (fun th -> REWRITE_TAC[GSYM th]) THEN + REWRITE_TAC[SUB_LIST_LENGTH] +);; + +let SUB_LIST_IDEMPOTENT_P = prove( + `!p n (l:(A)list). SUB_LIST (0,n) (SUB_LIST (p,n) l) = SUB_LIST (p,n) l`, + INDUCT_TAC THENL[ + REWRITE_TAC[SUB_LIST_IDEMPOTENT]; + + REPEAT STRIP_TAC THEN + DISJ_CASES_TAC (ISPEC `l:(A)list` list_CASES) THENL [ + ASM_REWRITE_TAC[] THEN REWRITE_TAC[SUB_LIST_CLAUSES]; + ALL_TAC + ] THEN + FIRST_X_ASSUM MP_TAC THEN STRIP_TAC THEN + ASM_REWRITE_TAC[] THEN REWRITE_TAC[SUB_LIST_CLAUSES] THEN + ASM_REWRITE_TAC[] + ]);; + +let SUB_LIST_MIN_RIGHT = prove( + `!p (l:(A)list) (n:num) m. SUB_LIST (0,n) (SUB_LIST (p,m) l) = SUB_LIST (p, MIN n m) l`, + REPEAT STRIP_TAC THEN + ASM_CASES_TAC `(m:num) <= n` THENL [ + FIRST_X_ASSUM MP_TAC THEN REWRITE_TAC[LE_EXISTS] THEN + STRIP_TAC THEN ASM_REWRITE_TAC[] THEN + REWRITE_TAC[SUB_LIST_SPLIT;ADD_CLAUSES;ARITH_RULE`MIN ((x:num)+y) x = x`] THEN + REWRITE_TAC[SUB_LIST_IDEMPOTENT_P] THEN + GEN_REWRITE_TAC RAND_CONV [GSYM APPEND_NIL] THEN + AP_TERM_TAC THEN MATCH_MP_TAC SUB_LIST_TRIVIAL THEN + REWRITE_TAC[LENGTH_SUB_LIST] THEN ARITH_TAC; ALL_TAC] THEN + + IMP_REWRITE_TAC[ARITH_RULE `~(m <= n) ==> MIN n m = n`] THEN + FIRST_X_ASSUM MP_TAC THEN REWRITE_TAC[NOT_LE;LT_EXISTS] THEN + STRIP_TAC THEN ASM_REWRITE_TAC[] THEN + REWRITE_TAC[SUB_LIST_SPLIT;ADD_CLAUSES;ARITH_RULE`MIN (x:num) (x+y) = x`] THEN + + MP_TAC (ISPECL [`l:A list`; `p:num`; `n:num`] LENGTH_SUB_LIST) THEN + ASM_CASES_TAC `n <= LENGTH (l:A list) - p` THENL [ + IMP_REWRITE_TAC[ARITH_RULE `!n m. n <= m ==> MIN n m = n`] THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_APPEND_LEFT] THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] THEN + ARITH_TAC; ALL_TAC + ] THEN + + IMP_REWRITE_TAC[ARITH_RULE `!n m. ~(n <= m) ==> MIN n m = m`] THEN + SUBGOAL_THEN `SUB_LIST (p + n,SUC d) (l:A list) = []` SUBST1_TAC THENL + [ MATCH_MP_TAC SUB_LIST_TRIVIAL THEN + ASM_ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[APPEND_NIL] THEN + REWRITE_TAC[SUB_LIST_IDEMPOTENT_P] +);; + +let SUB_LIST_MIN_LEFT = prove( + `!q (l:A list) n m. + SUB_LIST (q,n) (SUB_LIST (0,m) l) = SUB_LIST (q, MIN n (m - q)) l`, + REPEAT STRIP_TAC THEN + ASM_CASES_TAC `n <= m - q` THENL [ + IMP_REWRITE_TAC[ARITH_RULE `x <= y ==> MIN x y = x`] THEN + UNDISCH_TAC `n <= m - q` THEN + MAP_EVERY SPEC1_TAC [`n:num`; `l:A list`; `q:num`; `m:num`] THEN + (* Induct over m *) + INDUCT_TAC THENL + [ + REPEAT STRIP_TAC THEN + IMP_REWRITE_TAC[ARITH_RULE `n <= 0 - q ==> n = 0`] THEN + REWRITE_TAC[SUB_LIST_CLAUSES]; + + INDUCT_TAC THENL + [ + REWRITE_TAC[SUB_0] THEN + REPEAT STRIP_TAC THEN + MP_TAC (SPECL [`0:num`; `l:A list`; `n:num`; `SUC m:num`] SUB_LIST_MIN_RIGHT) THEN + IMP_REWRITE_TAC[ARITH_RULE `x <= y ==> MIN x y = x`]; + + LIST_INDUCT_TAC THENL[ + REWRITE_TAC[SUB_LIST_CLAUSES]; + REWRITE_TAC[SUB_LIST_CLAUSES] THEN + REPEAT STRIP_TAC THEN + FIRST_X_ASSUM + (fun th -> MP_TAC + (SPECL [`q:num`; `t:A list`; `n:num`] th)) THEN + ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[] + ] + ] + ]; ALL_TAC + ] THEN + + (* Case n > m - q*) + IMP_REWRITE_TAC[ARITH_RULE `~(x <= y) ==> MIN x y = y`] THEN + UNDISCH_TAC `~(n <= m - q)` THEN + MAP_EVERY SPEC1_TAC [`n:num`; `l:A list`; `q:num`; `m:num`] THEN + INDUCT_TAC THENL + [ + REPEAT STRIP_TAC THEN + REWRITE_TAC[ARITH_RULE `0 - q = 0`] THEN + REWRITE_TAC[SUB_LIST_CLAUSES]; + + INDUCT_TAC THENL + [ + REWRITE_TAC[SUB_0] THEN + REPEAT STRIP_TAC THEN + MP_TAC (SPECL [`0:num`; `l:A list`; `n:num`; `SUC m:num`] SUB_LIST_MIN_RIGHT) THEN + IMP_REWRITE_TAC[ARITH_RULE `~(x <= y) ==> MIN x y = y`]; + + LIST_INDUCT_TAC THENL[ + REWRITE_TAC[SUB_LIST_CLAUSES]; + REWRITE_TAC[SUB_LIST_CLAUSES] THEN + REPEAT STRIP_TAC THEN + REWRITE_TAC[ARITH_RULE `SUC m - SUC q = m - q`] THEN + FIRST_X_ASSUM + (fun th -> MP_TAC + (SPECL [`q:num`; `t:A list`; `n:num`] th)) THEN + ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[] + ] + ] + ] +);; + +let SUB_LIST_MIN_GENERAL = prove( + `!p q (l:(A)list) (n:num) m. + SUB_LIST (q,n) (SUB_LIST (p,m) l) = SUB_LIST (p + q, MIN n (m - q)) l`, + REPEAT STRIP_TAC THEN + (* Case n <= m - q *) + ASM_CASES_TAC `n <= m - q` THENL [ + IMP_REWRITE_TAC[ARITH_RULE `x <= y ==> MIN x y = x`] THEN + (* Induct over p *) + UNDISCH_TAC `n <= m - q` THEN + MAP_EVERY SPEC1_TAC [`m:num`; `n:num`; `l:A list`; `q:num`; `p:num`] THEN + INDUCT_TAC THENL + [ + REWRITE_TAC[ADD] THEN + REPEAT STRIP_TAC THEN + MP_TAC (SPECL [`q:num`; `l:A list`; `n:num`; `m:num`] SUB_LIST_MIN_LEFT) THEN + IMP_REWRITE_TAC[ARITH_RULE `x <= y ==> MIN x y = x`]; + ALL_TAC + ] THEN + + ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN + LIST_INDUCT_TAC THENL[ + REWRITE_TAC[SUB_LIST_CLAUSES]; + REWRITE_TAC[ARITH_RULE `SUC p + q = SUC (p + q)`] THEN + REWRITE_TAC[SUB_LIST_CLAUSES] THEN + ASM_REWRITE_TAC[] + ]; ALL_TAC + ] THEN + + (* Case n > m - q*) + IMP_REWRITE_TAC[ARITH_RULE `~(x <= y) ==> MIN x y = y`] THEN + UNDISCH_TAC `~(n <= m - q)` THEN + MAP_EVERY SPEC1_TAC [`m:num`; `n:num`; `l:A list`; `q:num`; `p:num`] THEN + INDUCT_TAC THENL + [ + REWRITE_TAC[ADD] THEN + REPEAT STRIP_TAC THEN + MP_TAC (SPECL [`q:num`; `l:A list`; `n:num`; `m:num`] SUB_LIST_MIN_LEFT) THEN + IMP_REWRITE_TAC[ARITH_RULE `~(x <= y) ==> MIN x y = y`]; + ALL_TAC + ] THEN + + ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN + LIST_INDUCT_TAC THENL[ + REWRITE_TAC[SUB_LIST_CLAUSES]; + REWRITE_TAC[ARITH_RULE `SUC p + q = SUC (p + q)`] THEN + REWRITE_TAC[SUB_LIST_CLAUSES] THEN + ASM_REWRITE_TAC[] + ] +);; + +let NUM_OF_BYTELIST_APPEND = prove + (`!l1 l2. num_of_bytelist (APPEND l1 l2) = + num_of_bytelist l1 + 2 EXP (8 * LENGTH l1) * num_of_bytelist l2`, + LIST_INDUCT_TAC THENL + [ REWRITE_TAC[APPEND; LENGTH; num_of_bytelist; MULT_CLAUSES; EXP; ADD_CLAUSES]; + REWRITE_TAC[APPEND; LENGTH; num_of_bytelist] THEN + ASM_REWRITE_TAC[] THEN + REWRITE_TAC[MULT_SUC; EXP_ADD] THEN + REWRITE_TAC[MULT_ASSOC; LEFT_ADD_DISTRIB] THEN + ARITH_TAC]);; + +let NUM_OF_BYTELIST_OF_SUB_LIST = prove( + `!sz len (x:byte list). + sz <= LENGTH x ==> + num_of_bytelist (SUB_LIST (0, sz + len) x) = + num_of_bytelist (SUB_LIST (0, sz) x) + + 2 EXP (8 * sz) * num_of_bytelist (SUB_LIST (sz, len) x)`, + REPEAT STRIP_TAC THEN + SUBST1_TAC(ISPECL [`x:byte list`; `sz:num`; `len:num`; `0:num`] SUB_LIST_SPLIT) THEN + REWRITE_TAC[NUM_OF_BYTELIST_APPEND] THEN + ASM_SIMP_TAC[LENGTH_SUB_LIST; SUB_0; MIN; ARITH_RULE `0 + sz = sz`] +);; + + +(**********************************************************************) +(** Common Lemmas **) + +let MEMORY_BYTES_BOUND = prove + (`read (memory :> bytes (x,16)) s < 2 EXP dimindex (:128)`, + REWRITE_TAC[READ_COMPONENT_COMPOSE; DIMINDEX_128] THEN + SUBST1_TAC(ARITH_RULE `128 = 8 * 16`) THEN REWRITE_TAC[READ_BYTES_BOUND] + );; + +(* Copied from bignum_copy_row_from_table_8n.ml *) +let READ_MEMORY_BYTES_BYTES128 = prove(`!z s. + read (memory :> bytes (z,16)) s = val (read (memory :> bytes128 z) s)`, + REPEAT GEN_TAC THEN + REWRITE_TAC[el 1 (CONJUNCTS READ_MEMORY_BYTESIZED_SPLIT)] THEN + REWRITE_TAC[VAL_WORD_JOIN;DIMINDEX_64;DIMINDEX_128] THEN + IMP_REWRITE_TAC[MOD_LT] THEN + REWRITE_TAC[ARITH_RULE`2 EXP 128 = 2 EXP 64 * 2 EXP 64`] THEN + IMP_REWRITE_TAC[LT_MULT_ADD_MULT] THEN + REWRITE_TAC[VAL_BOUND_64;ARITH_RULE`0<2 EXP 64`;LE_REFL] THEN + REWRITE_TAC[ARITH_RULE`16 = 8*(1+1)`;GSYM BIGNUM_FROM_MEMORY_BYTES;BIGNUM_FROM_MEMORY_STEP;BIGNUM_FROM_MEMORY_SING] THEN + REWRITE_TAC[ARITH_RULE`8*1=8`;ARITH_RULE`64*1=64`] THEN ARITH_TAC);; + + +let WORD_AND_MASK16 = prove( + `word_and (len:int64) (word 0xfffffffffffffff0) = word_sub len (word_and len (word 0xf))`, + BITBLAST_TAC +);; + +let WORD_AND_MASK16_EQ_0 = prove( + `!(x:int64). val x < 16 ==> ~(val x = 0x0) ==> ~(val (word_and x (word 0xf)) = 0x0)`, + BITBLAST_TAC);; + +let word_split_lemma = prove( + `!len:int64. word_add (word_and len (word 0xf)) + (word_and len (word 0xfffffffffffffff0)) = len`, + BITBLAST_TAC);; + +let BYTE_LIST_AT_ADD_ASSUM_TAC new_pos bound = + let rule = subst [new_pos, `new_pos:num`; bound, `bound:num`] + `(pos:num) + bound <= LENGTH (bl:byte list) ==> new_pos < LENGTH bl` in + let p = subst [new_pos, `new_pos:num`] `new_pos:num` in + MP_TAC (ARITH_RULE rule) THEN + ASM_REWRITE_TAC[] THEN DISCH_THEN (LABEL_TAC "tmp") THEN + FIRST_ASSUM(fun th -> MP_TAC(SPEC p th)) THEN + USE_THEN "tmp" (fun th -> REWRITE_TAC[th]) THEN + POP_ASSUM (K ALL_TAC);; + +let BYTES128_TO_BYTES8_THM = prove( + `!pos bl_ptr s. + read (memory :> bytes128 (word_add bl_ptr (word pos))) s = + bytes_to_int128 + [read (memory :> bytes8 (word_add bl_ptr (word (pos + 0x0)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0x1)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0x2)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0x3)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0x4)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0x5)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0x6)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0x7)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0x8)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0x9)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0xa)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0xb)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0xc)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0xd)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0xe)))) s; + read (memory :> bytes8 (word_add bl_ptr (word (pos + 0xf)))) s]`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[bytes_to_int128] THEN + REWRITE_TAC EL_16_8_CLAUSES THEN + GEN_REWRITE_TAC TOP_DEPTH_CONV [READ_MEMORY_BYTESIZED_SPLIT; WORD_ADD_ASSOC_CONSTS] THEN + CONV_TAC(DEPTH_CONV WORD_NUM_RED_CONV) THEN + ONCE_REWRITE_TAC [ARITH_RULE `pos + 0 = (pos:num)`] THEN + REFL_TAC +);; + +let SUB_LIST_16_TAC n exp = + let subgoal = subst [exp, `exp:num`] `exp < LENGTH (l:A list)` in + CONV_TAC(RAND_CONV (REWRITE_CONV[num_CONV n; SUB_LIST_SUCSPLIT])) THEN + SUBGOAL_THEN subgoal ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[SUB_LIST_1] THEN ASM_SIMP_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC;; + +let SUB_LIST_16 = prove( + `!(l:A list) n. n + 16 <= LENGTH l ==> + [ EL (n + 0) l; EL (n + 1) l; EL (n + 2) l; EL (n + 3) l; + EL (n + 4) l; EL (n + 5) l; EL (n + 6) l; EL (n + 7) l; + EL (n + 8) l; EL (n + 9) l; EL (n + 10) l; EL (n + 11) l; + EL (n + 12) l; EL (n + 13) l; EL (n + 14) l; EL (n + 15) l + ] = SUB_LIST (n,16) l`, + REPEAT STRIP_TAC THEN + MAP_EVERY (fun i -> + if i == 0 + then SUB_LIST_16_TAC `0x10` `n:num` + else SUB_LIST_16_TAC (mk_numeral (num (16 - i))) + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("n", `:num`)) + (mk_numeral (num i)))) (0--14) THEN + SUBGOAL_THEN `n + 15 < LENGTH (l:A list)` ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[APPEND; ARITH_RULE `n + 0 = n`] +);; + +let BYTE_LIST_AT_5BLOCKS = prove( + `! pos bl bl_ptr len s. + byte_list_at bl bl_ptr len s + ==> LENGTH bl = val len + ==> pos + 0x50 <= LENGTH bl + ==> (read (memory :> bytes128 (word_add bl_ptr (word pos))) s = + bytes_to_int128 (SUB_LIST (pos, 0x10) bl) /\ + read (memory :> bytes128 (word_add (word_add bl_ptr (word pos)) (word 0x10))) s = + bytes_to_int128 (SUB_LIST (pos + 0x10, 0x10) bl) /\ + read (memory :> bytes128 (word_add (word_add bl_ptr (word pos)) (word 0x20))) s = + bytes_to_int128 (SUB_LIST (pos + 0x20, 0x10) bl) /\ + read (memory :> bytes128 (word_add (word_add bl_ptr (word pos)) (word 0x30))) s = + bytes_to_int128 (SUB_LIST (pos + 0x30, 0x10) bl) /\ + read (memory :> bytes128 (word_add (word_add bl_ptr (word pos)) (word 0x40))) s = + bytes_to_int128 (SUB_LIST (pos + 0x40, 0x10) bl))`, + REWRITE_TAC[byte_list_at] THEN + REPEAT STRIP_TAC THENL + [ (* Subgoal1 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x50`) (0--15) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `pos:num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC; + (* Subgoal2 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x50`) (16--31) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `(pos+0x10):num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC; + (* Subgoal3 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x50`) (32--47) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `(pos+0x20):num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC; + (* Subgoal4 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x50`) (48--63) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `(pos+0x30):num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC; + (* Subgoal 5 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x50`) (64--79) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `(pos+0x40):num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC + ] +);; + +let BYTE_LIST_AT_4BLOCKS = prove( + `! pos bl bl_ptr len s. + byte_list_at bl bl_ptr len s + ==> LENGTH bl = val len + ==> pos + 0x40 <= LENGTH bl + ==> (read (memory :> bytes128 (word_add bl_ptr (word pos))) s = + bytes_to_int128 (SUB_LIST (pos, 0x10) bl) /\ + read (memory :> bytes128 (word_add (word_add bl_ptr (word pos)) (word 0x10))) s = + bytes_to_int128 (SUB_LIST (pos + 0x10, 0x10) bl) /\ + read (memory :> bytes128 (word_add (word_add bl_ptr (word pos)) (word 0x20))) s = + bytes_to_int128 (SUB_LIST (pos + 0x20, 0x10) bl) /\ + read (memory :> bytes128 (word_add (word_add bl_ptr (word pos)) (word 0x30))) s = + bytes_to_int128 (SUB_LIST (pos + 0x30, 0x10) bl))`, + REWRITE_TAC[byte_list_at] THEN + REPEAT STRIP_TAC THENL + [ (* Subgoal1 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x40`) (0--15) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `pos:num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC; + (* Subgoal2 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x40`) (16--31) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `(pos+0x10):num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC; + (* Subgoal3 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x40`) (32--47) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `(pos+0x20):num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC; + (* Subgoal4 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x40`) (48--63) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `(pos+0x30):num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC + ] +);; + +let BYTE_LIST_AT_3BLOCKS = prove( + `! pos bl bl_ptr len s. + byte_list_at bl bl_ptr len s + ==> LENGTH bl = val len + ==> pos + 0x30 <= LENGTH bl + ==> (read (memory :> bytes128 (word_add bl_ptr (word pos))) s = + bytes_to_int128 (SUB_LIST (pos, 0x10) bl) /\ + read (memory :> bytes128 (word_add (word_add bl_ptr (word pos)) (word 0x10))) s = + bytes_to_int128 (SUB_LIST (pos + 0x10, 0x10) bl) /\ + read (memory :> bytes128 (word_add (word_add bl_ptr (word pos)) (word 0x20))) s = + bytes_to_int128 (SUB_LIST (pos + 0x20, 0x10) bl))`, + REWRITE_TAC[byte_list_at] THEN + REPEAT STRIP_TAC THENL + [ (* Subgoal1 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x30`) (0--15) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `pos:num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC; + (* Subgoal2 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x30`) (16--31) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `(pos+0x10):num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC; + (* Subgoal3 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x30`) (32--47) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `(pos+0x20):num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC + ] +);; + +let BYTE_LIST_AT_2BLOCKS = prove( + `! pos bl bl_ptr len s. + byte_list_at bl bl_ptr len s + ==> LENGTH bl = val len + ==> pos + 0x20 <= LENGTH bl + ==> (read (memory :> bytes128 (word_add bl_ptr (word pos))) s = + bytes_to_int128 (SUB_LIST (pos, 0x10) bl) /\ + read (memory :> bytes128 (word_add (word_add bl_ptr (word pos)) (word 0x10))) s = + bytes_to_int128 (SUB_LIST (pos + 0x10, 0x10) bl))`, + REWRITE_TAC[byte_list_at] THEN + REPEAT STRIP_TAC THENL + [ (* Subgoal1 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x20`) (0--15) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `pos:num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC; + (* Subgoal2 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x20`) (16--31) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `(pos+0x10):num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC + ] +);; + +let BYTE_LIST_AT_1BLOCKS = prove( + `! pos bl bl_ptr len s. + byte_list_at bl bl_ptr len s + ==> LENGTH bl = val len + ==> pos + 0x10 <= LENGTH bl + ==> read (memory :> bytes128 (word_add bl_ptr (word pos))) s = + bytes_to_int128 (SUB_LIST (pos, 0x10) bl)`, + REWRITE_TAC[byte_list_at] THEN + REPEAT STRIP_TAC THENL + [ (* Subgoal1 *) + MAP_EVERY (fun i -> BYTE_LIST_AT_ADD_ASSUM_TAC + (mk_binop (mk_const("+", [`:num`, `:A`])) (mk_var("pos", `:num`)) + (mk_numeral (num i))) `0x10`) (0--15) THEN + REWRITE_TAC[WORD_ADD_ASSOC_CONSTS] THEN + REPEAT STRIP_TAC THEN + ASM_REWRITE_TAC[BYTES128_TO_BYTES8_THM; GSYM ADD_ASSOC] THEN + NUM_REDUCE_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN + MP_TAC (ISPECL [`bl:byte list`; `pos:num`] SUB_LIST_16) THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN NUM_REDUCE_TAC THEN + DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC + ] +);; + +let READ_BL_LEMMA = prove( + `!ptr i (len:int64) (bl:byte list) s. + (forall j. j < val len ==> read (memory :> bytes8 (word_add ptr (word j))) s = EL j bl) + /\ i * 0x50 + 0x50 <= val len + /\ LENGTH bl = val len + ==> + read (memory :> bytes128 (word_add ptr (word_mul (word 0x50) (word i)))) s = + bytes_to_int128 (SUB_LIST (i * 80, 16) bl) /\ + read (memory :> bytes128 (word_add (word_add ptr (word_mul (word 0x50) (word i))) (word 0x10))) s = + bytes_to_int128 (SUB_LIST (i * 80 + 16, 16) bl) /\ + read (memory :> bytes128 (word_add (word_add ptr (word_mul (word 0x50) (word i))) (word 0x20))) s = + bytes_to_int128 (SUB_LIST (i * 80 + 32, 16) bl) /\ + read (memory :> bytes128 (word_add (word_add ptr (word_mul (word 0x50) (word i))) (word 0x30))) s = + bytes_to_int128 (SUB_LIST (i * 80 + 48, 16) bl) /\ + read (memory :> bytes128 (word_add (word_add ptr (word_mul (word 0x50) (word i))) (word 0x40))) s = + bytes_to_int128 (SUB_LIST (i * 80 + 64, 16) bl) + `, + REPEAT GEN_TAC THEN STRIP_TAC THEN + REWRITE_TAC [WORD_RULE `word_mul (word 0x50) (word i) = word (i * 80)`] THEN + MP_TAC + (SPECL [`(i * 80):num`; `bl:byte list`; `ptr:int64`; `len:int64`; `s:armstate`] + BYTE_LIST_AT_5BLOCKS) THEN + REWRITE_TAC[byte_list_at] THEN ASM_SIMP_TAC[] +);; + +let READ_TAIL4_LEMMA = prove( + `!ptr (n5blocks:int64) (len:int64) (bl:byte list) s. + (forall j. j < val len ==> read (memory :> bytes8 (word_add ptr (word j))) s = EL j bl) + /\ val n5blocks * 0x50 + 0x40 <= val len + /\ LENGTH bl = val len + ==> + read (memory :> bytes128 (word_add + (word_add ptr (word_mul (word 0x50) n5blocks)) + (word 0x30))) s = + bytes_to_int128 (SUB_LIST (val n5blocks * 80 + 0x30, 16) bl) /\ + read (memory :> bytes128 (word_add + (word_add ptr (word_mul (word 0x50) n5blocks)) + (word 0x20))) s = + bytes_to_int128 (SUB_LIST (val n5blocks * 80 + 0x20, 16) bl) /\ + read (memory :> bytes128 (word_add + (word_add ptr (word_mul (word 0x50) n5blocks)) + (word 0x10))) s = + bytes_to_int128 (SUB_LIST (val n5blocks * 80 + 0x10, 16) bl) /\ + read (memory :> bytes128 + (word_add ptr (word_mul (word 0x50) n5blocks))) s = + bytes_to_int128 (SUB_LIST (val n5blocks * 80, 16) bl) + `, + REPEAT GEN_TAC THEN STRIP_TAC THEN + REWRITE_TAC [WORD_RULE `(word_mul (word 0x50) (n5blocks:int64)) = word (val n5blocks * 80)`] THEN + MP_TAC + (SPECL [`(val (n5blocks:int64) * 80):num`; `bl:byte list`; `ptr:int64`; `len:int64`; `s:armstate`] + BYTE_LIST_AT_4BLOCKS) THEN + REWRITE_TAC[byte_list_at] THEN ASM_SIMP_TAC[] +);; + +let READ_TAIL3_LEMMA = prove( + `!ptr (n5blocks:int64) (len:int64) (bl:byte list) s. + (forall j. j < val len ==> read (memory :> bytes8 (word_add ptr (word j))) s = EL j bl) + /\ val n5blocks * 0x50 + 0x30 <= val len + /\ LENGTH bl = val len + ==> + read (memory :> bytes128 (word_add + (word_add ptr (word_mul (word 0x50) n5blocks)) + (word 0x20))) s = + bytes_to_int128 (SUB_LIST (val n5blocks * 80 + 0x20, 16) bl) /\ + read (memory :> bytes128 (word_add + (word_add ptr (word_mul (word 0x50) n5blocks)) + (word 0x10))) s = + bytes_to_int128 (SUB_LIST (val n5blocks * 80 + 0x10, 16) bl) /\ + read (memory :> bytes128 + (word_add ptr (word_mul (word 0x50) n5blocks))) s = + bytes_to_int128 (SUB_LIST (val n5blocks * 80, 16) bl) + `, + REPEAT GEN_TAC THEN STRIP_TAC THEN + REWRITE_TAC [WORD_RULE `(word_mul (word 0x50) (n5blocks:int64)) = word (val n5blocks * 80)`] THEN + MP_TAC + (SPECL [`(val (n5blocks:int64) * 80):num`; `bl:byte list`; `ptr:int64`; `len:int64`; `s:armstate`] + BYTE_LIST_AT_3BLOCKS) THEN + REWRITE_TAC[byte_list_at] THEN ASM_SIMP_TAC[] +);; + +let READ_TAIL2_LEMMA = prove( + `!ptr (n5blocks:int64) (len:int64) (bl:byte list) s. + (forall j. j < val len ==> read (memory :> bytes8 (word_add ptr (word j))) s = EL j bl) + /\ val n5blocks * 0x50 + 0x20 <= val len + /\ LENGTH bl = val len + ==> + read (memory :> bytes128 (word_add + (word_add ptr (word_mul (word 0x50) n5blocks)) + (word 0x10))) s = + bytes_to_int128 (SUB_LIST (val n5blocks * 80 + 0x10, 16) bl) /\ + read (memory :> bytes128 + (word_add ptr (word_mul (word 0x50) n5blocks))) s = + bytes_to_int128 (SUB_LIST (val n5blocks * 80, 16) bl) + `, + REPEAT GEN_TAC THEN STRIP_TAC THEN + REWRITE_TAC [WORD_RULE `(word_mul (word 0x50) (n5blocks:int64)) = word (val n5blocks * 80)`] THEN + MP_TAC + (SPECL [`(val (n5blocks:int64) * 80):num`; `bl:byte list`; `ptr:int64`; `len:int64`; `s:armstate`] + BYTE_LIST_AT_2BLOCKS) THEN + REWRITE_TAC[byte_list_at] THEN ASM_SIMP_TAC[] +);; + +let READ_TAIL1_LEMMA = prove( + `!ptr (n5blocks:int64) (len:int64) (bl:byte list) s. + (forall j. j < val len ==> read (memory :> bytes8 (word_add ptr (word j))) s = EL j bl) + /\ val n5blocks * 0x50 + 0x10 <= val len + /\ LENGTH bl = val len + ==> + read (memory :> bytes128 + (word_add ptr (word_mul (word 0x50) n5blocks))) s = + bytes_to_int128 (SUB_LIST (val n5blocks * 80, 16) bl) + `, + REPEAT GEN_TAC THEN STRIP_TAC THEN + REWRITE_TAC [WORD_RULE `(word_mul (word 0x50) (n5blocks:int64)) = word (val n5blocks * 80)`] THEN + MP_TAC + (SPECL [`(val (n5blocks:int64) * 80):num`; `bl:byte list`; `ptr:int64`; `len:int64`; `s:armstate`] + BYTE_LIST_AT_1BLOCKS) THEN + REWRITE_TAC[byte_list_at] THEN ASM_SIMP_TAC[] +);; + +let READ_LAST_LEMMA = prove( + `!ptr (curr_len:num) (len:int64) (bl:byte list) s. + (forall j. j < val len ==> read (memory :> bytes8 (word_add ptr (word j))) s = EL j bl) + /\ curr_len + 0x10 <= val len + /\ LENGTH bl = val len + ==> + read (memory :> bytes128 (word_add ptr (word curr_len))) s = + bytes_to_int128 (SUB_LIST (curr_len, 16) bl) + `, + REPEAT GEN_TAC THEN STRIP_TAC THEN + MP_TAC + (SPECL [`curr_len:num`; `bl:byte list`; `ptr:int64`; `len:int64`; `s:armstate`] + BYTE_LIST_AT_1BLOCKS) THEN + REWRITE_TAC[byte_list_at] THEN ASM_SIMP_TAC[] +);; + +let UDIV_OPT_THM = prove(`!n:num. n < 0x2 EXP 0x40 + ==> (word (val ((word ((n * 0xcccccccccccccccd) DIV 0x2 EXP 0x40)):int64) DIV 0x2 EXP 0x6)):int64 = word (n DIV 0x50)`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[VAL_WORD; DIMINDEX_64] THEN + SUBGOAL_THEN `!p n:num. ~(p = 0) /\ n < p * p ==> n DIV p MOD p = n DIV p` + (MP_TAC o SPECL [`0x2 EXP 0x40`; `n * 0xcccccccccccccccd`]) THENL + [ REPEAT STRIP_TAC THEN + REWRITE_TAC[DIV_MOD] THEN + AP_THM_TAC THEN AP_TERM_TAC THEN + MATCH_MP_TAC MOD_LT THEN + ASM_ARITH_TAC; ALL_TAC] THEN + ANTS_TAC THENL [ASM_ARITH_TAC;ALL_TAC] THEN + DISCH_TAC THEN ASM_REWRITE_TAC[] THEN + AP_TERM_TAC THEN ASM_ARITH_TAC);; + +(* For encrypt *) +let LEN_FULL_BLOCKS_LO_BOUND_THM = prove( + `!(len:int64) len_full_blocks. word_and len (word 0xfffffffffffffff0) = len_full_blocks + ==> ~(val len < 0x50) + ==> ~(val len_full_blocks < 0x50)`, + BITBLAST_TAC);; + +(* For decrypt *) +let NUM_BLOCKS_LO_BOUND_THM = prove( + `!(len:int64) num_blocks. word_and len (word 0xfffffffffffffff0) = num_blocks + ==> ~(val len < 0x60) + ==> ~(val num_blocks < 0x60)`, + BITBLAST_TAC);; + +let NUM_BLOCKS_LO_BOUND_1BLOCK_THM = prove( + `!(len:int64) num_blocks. word_and len (word 0xfffffffffffffff0) = num_blocks + ==> ~(val len < 16) + ==> ~(val num_blocks < 16)`, + BITBLAST_TAC);; + +let NUM_BLOCKS_HI_BOUND_THM = prove( + `!(len:int64) num_blocks. word_and len (word 0xfffffffffffffff0) = num_blocks + ==> val len <= 2 EXP 24 + ==> val num_blocks <= 2 EXP 24`, + BITBLAST_TAC);; + +let TAIL_LEN_BOUND_THM = prove( + `!(len:int64) tail_len. word_and len (word 0xf) = tail_len + ==> val tail_len < 0x10`, + BITBLAST_TAC);; + +let NUM_BLOCKS_LT_LEN_THM = prove( + `!(len:int64). val (word_and len (word 0xfffffffffffffff0)) <= val len`, + BITBLAST_TAC +);; + +(* For encrypt *) +let NUM_5BLOCKS_LO_BOUND_THM = prove( + `!(len_full_blocks:int64) (num_5blocks:int64). + val len_full_blocks <= 2 EXP 24 + ==> ~(val len_full_blocks < 0x50) + ==> word (val len_full_blocks DIV 0x50) = num_5blocks + ==> 0x0 < val num_5blocks`, + REPEAT STRIP_TAC THEN + EXPAND_TAC "num_5blocks" THEN + REWRITE_TAC[VAL_WORD; DIMINDEX_64] THEN + UNDISCH_TAC `~(val (len_full_blocks:int64) < 0x50)` THEN + ABBREV_TAC `n = val (len_full_blocks:int64)` THEN + SUBGOAL_THEN `n DIV 0x50 < 2 EXP 64` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[MOD_LT] THEN + ARITH_TAC +);; + +(* For decrypt *) +let NUM_BLOCKS_ADJUSTED_LO_BOUND_THM = prove( + `!(num_blocks:int64) (tail_len:int64) num_blocks_adjusted. + (if val tail_len = 0x0 then num_blocks else word_sub num_blocks (word 0x10)) = num_blocks_adjusted + ==> ~(val num_blocks < 0x60) + ==> ~(val num_blocks_adjusted < 0x50)`, + BITBLAST_TAC +);; + +let NUM_BLOCKS_ADJUSTED_LO_BOUND_1BLOCK_THM = prove( + `!(num_blocks:int64) (tail_len:int64) num_blocks_adjusted. + (if val tail_len = 0x0 then num_blocks else word_sub num_blocks (word 0x10)) = num_blocks_adjusted + ==> ~(val num_blocks < 16) + ==> ~(val num_blocks_adjusted < 0)`, + BITBLAST_TAC +);; + +let NUM_BLOCKS_ADJUSTED_HI_BOUND_THM = prove( + `!(num_blocks:int64) (tail_len:int64) num_blocks_adjusted. + (if val tail_len = 0x0 then num_blocks else word_sub num_blocks (word 0x10)) = num_blocks_adjusted + ==> val num_blocks <= 2 EXP 24 + ==> ~(val num_blocks < 16) + ==> val num_blocks_adjusted <= 2 EXP 24`, + BITBLAST_TAC +);; + +let NUM_5BLOCKS_ADJUSTED_LO_BOUND_THM = prove( + `!(num_blocks_adjusted:int64) (num_5blocks_adjusted:int64). + val num_blocks_adjusted <= 0x2 EXP 0x18 + ==> ~(val num_blocks_adjusted < 0x50) + ==> word (val num_blocks_adjusted DIV 0x50) = num_5blocks_adjusted + ==> 0x0 < val num_5blocks_adjusted`, + REPEAT STRIP_TAC THEN + EXPAND_TAC "num_5blocks_adjusted" THEN + REWRITE_TAC[VAL_WORD; DIMINDEX_64] THEN + UNDISCH_TAC `~(val (num_blocks_adjusted:int64) < 0x50)` THEN + ABBREV_TAC `n = val (num_blocks_adjusted:int64)` THEN + SUBGOAL_THEN `n DIV 80 < 2 EXP 64` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[MOD_LT] THEN + ARITH_TAC +);; + +let NUM_BLOCKS_ADJUSTED_LT_LEN_THM = prove( + `!(len:int64) num_blocks. + word_and len (word 0xfffffffffffffff0) = num_blocks + ==> ~(val num_blocks < 16) + ==> val (word_sub num_blocks (word 0x10)) <= val len`, + BITBLAST_TAC +);; + + +let MEMORY_READ_SUBSET_LEMMA = prove + (`!len (ptr:int64) (bl:byte list) s. + (forall i. + i < SUC len + ==> read (memory :> bytes8 (word_add ptr (word i))) s = EL i bl) ==> + (forall i. + i < len + ==> read (memory :> bytes8 (word_add ptr (word i))) s = EL i bl) /\ + read (memory :> bytes (word_add ptr (word len),1)) s = + val(read (memory :> bytes8 (word_add ptr (word len))) s) + `, + REPEAT GEN_TAC THEN + DISCH_TAC THEN + CONJ_TAC THENL + [ GEN_TAC THEN DISCH_TAC THEN + FIRST_X_ASSUM MATCH_MP_TAC THEN + ASM_REWRITE_TAC[LT_SUC_LE] THEN + ASM_ARITH_TAC; + ALL_TAC] THEN + REWRITE_TAC[bytes8; READ_COMPONENT_COMPOSE; asword; through; read] THEN + REWRITE_TAC[VAL_WORD; DIMINDEX_8] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[MOD_LT] THEN + MP_TAC (ISPECL [`(word_add (ptr:int64) (word len)):int64`; `1:num`; `(read memory s):int64->byte`] READ_BYTES_BOUND) THEN + CONV_TAC NUM_REDUCE_CONV +);; + +let BYTE_LIST_AT_SPLIT = prove( + `!len (ptr:int64) (bl:byte list) s. + SUC len <= LENGTH bl ==> + ((forall i. + i < SUC len + ==> read (memory :> bytes8 (word_add ptr (word i))) s = EL i bl) <=> + ((forall i. + i < len + ==> read (memory :> bytes8 (word_add ptr (word i))) s = EL i bl) /\ + read (memory :> bytes8 (word_add ptr (word len))) s = EL len bl))`, + REPEAT STRIP_TAC THEN + EQ_TAC THENL + [ STRIP_TAC THEN + CONJ_TAC THENL + [ ASM_SIMP_TAC[ARITH_RULE `i < len ==> i < SUC len`]; + ASM_SIMP_TAC[ARITH_RULE `len < SUC len`]]; + ALL_TAC ] THEN + REPEAT STRIP_TAC THEN + ASM_CASES_TAC `i < len` THENL + [ FIRST_X_ASSUM MATCH_MP_TAC THEN + ASM_SIMP_TAC[]; + SUBGOAL_THEN `i = len:num` SUBST1_TAC THENL + [ASM_ARITH_TAC; ASM_REWRITE_TAC[]] + ] +);; + +let BYTE_LIST_AT_SPLIT_BACKWARDS = prove( + `!(pt_ptr:int64) i len curr_len bl s. + 0 <= i ==> i < len ==> len < 16 ==> LENGTH bl >= 16 ==> + (forall j. + j < len - (i + 1) + ==> read (memory :> bytes8 + (word_add (word_add pt_ptr (word (curr_len + 16 + i + 1))) + (word j))) s = + EL j (SUB_LIST (i + 1, len - (i + 1)) bl)) ==> + read (memory :> bytes8 (word_add pt_ptr (word (curr_len + 16 + i)))) s = (EL i bl) ==> + forall j. + j < len - i + ==> read (memory :> bytes8 + (word_add (word_add pt_ptr (word (curr_len + 16 + i))) + (word j))) s = + EL j (SUB_LIST (i, len - i) bl) + `, + REPEAT GEN_TAC THEN + REPEAT STRIP_TAC THEN + ASM_CASES_TAC `j > 0` THENL + [ + FIRST_X_ASSUM(MP_TAC o SPEC `j - 1`) THEN + ANTS_TAC THENL[ ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `(word_add (word_add (pt_ptr:int64) (word (curr_len + 0x10 + i + 0x1))) + (word (j - 0x1))) = (word_add (word_add pt_ptr (word (curr_len + 0x10 + i))) (word j))` SUBST1_TAC THENL + [ REWRITE_TAC[WORD_RULE `word_add (word_add a (word b)) (word c) = word_add a (word (b + c))`] THEN + AP_TERM_TAC THEN AP_TERM_TAC THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[ARITH_RULE `len - (i + 1) = len - i - 1`; + EL_SUB_LIST_SHIFT] THEN + ASM_ARITH_TAC; + ALL_TAC + ] THEN + + SUBGOAL_THEN `j = 0` SUBST_ALL_TAC THENL[ASM_ARITH_TAC;ALL_TAC] THEN + REWRITE_TAC[WORD_ADD_0] THEN + ASM_REWRITE_TAC[] THEN + IMP_REWRITE_TAC[EL_SUB_LIST_TRIVIAL] THEN + ASM_ARITH_TAC +);; + +(* Differs from Encrypt in that the address is written in a canonical form *) +let BYTE_LIST_AT_SPLIT_BACKWARDS_CARNONICAL = prove( + `!(pt_ptr:int64) i len curr_len bl s. + 0 <= i ==> i < len ==> len < 16 ==> LENGTH bl >= 16 ==> + (forall j. + j < len - (i + 1) + ==> read (memory :> bytes8 + (word_add pt_ptr (word (curr_len + 16 + i + 1 + j)))) s = + EL j (SUB_LIST (i + 1, len - (i + 1)) bl)) ==> + read (memory :> bytes8 (word_add pt_ptr (word (curr_len + 16 + i)))) s = (EL i bl) ==> + forall j. + j < len - i + ==> read (memory :> bytes8 + (word_add pt_ptr (word (curr_len + 16 + i + j)))) s = + EL j (SUB_LIST (i, len - i) bl) + `, + REPEAT GEN_TAC THEN + REPEAT STRIP_TAC THEN + ASM_CASES_TAC `j > 0` THENL + [ + FIRST_X_ASSUM(MP_TAC o SPEC `j - 1`) THEN + ANTS_TAC THENL[ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[ADD_ASSOC; ARITH_RULE `j > 0 ==> curr_len + 0x10 + i + 0x1 + j - 0x1 = curr_len + 0x10 + i + j`] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[ARITH_RULE `len - (i + 1) = len - i - 1`; + EL_SUB_LIST_SHIFT] THEN + ASM_ARITH_TAC; + ALL_TAC + ] THEN + + SUBGOAL_THEN `j = 0` SUBST_ALL_TAC THENL[ASM_ARITH_TAC;ALL_TAC] THEN + REWRITE_TAC[ADD_0] THEN + ASM_REWRITE_TAC[] THEN + IMP_REWRITE_TAC[EL_SUB_LIST_TRIVIAL] THEN + ASM_ARITH_TAC +);; + +let MEMORY_READ_BYTES_SUBSET_LEMMA = prove( + `!len (ptr:int64) (bl:byte list) s. + SUC len <= LENGTH bl ==> + read (memory :> bytes (ptr,SUC len)) s = + num_of_bytelist (SUB_LIST (0x0,SUC len) bl) ==> + read (memory :> bytes (ptr,len)) s = + num_of_bytelist (SUB_LIST (0x0,len) bl) /\ + read (memory :> bytes8 (word_add ptr (word len))) s = EL len bl`, + REPEAT GEN_TAC THEN STRIP_TAC THEN + SUBGOAL_THEN `SUC len = len + 1` SUBST_ALL_TAC THENL [ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[READ_COMPONENT_COMPOSE] THEN + SUBGOAL_THEN `len <= LENGTH (bl:byte list)` ASSUME_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + (* Use READ_BYTES_COMBINE to decompose the memory read *) + MP_TAC(ISPECL [`ptr:int64`; `len:num`; `1:num`; `(read memory s):int64->byte`] READ_BYTES_COMBINE) THEN + DISCH_TAC THEN + (* Use SUB_LIST_SPLIT to decompose the byte list *) + MP_TAC(ISPECL [`bl:byte list`; `len:num`; `1:num`; `0:num`] SUB_LIST_SPLIT) THEN + REWRITE_TAC[ADD_CLAUSES] THEN DISCH_TAC THEN + (* Decompose num_of_bytelist *) + SUBGOAL_THEN + `num_of_bytelist (SUB_LIST (0,len + 1) (bl:byte list)) = + num_of_bytelist (SUB_LIST (0,len) bl) + + 2 EXP (8 * len) * num_of_bytelist (SUB_LIST (len,1) bl)` + ASSUME_TAC THENL + [ ASM_REWRITE_TAC[] THEN + REWRITE_TAC[NUM_OF_BYTELIST_APPEND] THEN + AP_TERM_TAC THEN AP_THM_TAC THEN REPEAT_N 3 AP_TERM_TAC THEN + IMP_REWRITE_TAC[LENGTH_SUB_LIST; MIN; SUB_0] THEN + ASM_SIMP_TAC[] + ; ALL_TAC] THEN + (* Rewrite in goal *) + ASM_REWRITE_TAC[] THEN + DISCH_TAC THEN + CONJ_TAC THENL + [ (* First part: read (memory :> bytes (ptr,len)) s = num_of_bytelist (SUB_LIST (0,len) bl) *) + FIRST_X_ASSUM(MP_TAC o AP_TERM `\x. x MOD 2 EXP (8 * len)`) THEN + ASM_REWRITE_TAC[] THEN + REWRITE_TAC[MOD_MULT_ADD; MOD_LT] THEN + REWRITE_TAC[READ_BYTES_MOD; MIN] THEN + SIMP_TAC[ARITH_RULE `len <= len`] THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[MOD_LT] THEN + MP_TAC (SPEC `(SUB_LIST (0,len) bl:byte list)` NUM_OF_BYTELIST_BOUND) THEN + IMP_REWRITE_TAC[LENGTH_SUB_LIST; SUB_0; MIN] THEN + SUBGOAL_THEN `256 EXP len = 2 EXP (8 * len)` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `256 = 2 EXP 8`; EXP_EXP]; ALL_TAC] THEN + SIMP_TAC[]; + ALL_TAC + ] THEN + (* Second part: read (memory :> bytes8 (word_add ptr (word len))) s = EL len bl *) + FIRST_X_ASSUM(MP_TAC o AP_TERM `\x. x DIV 2 EXP (8 * len)`) THEN + ASM_REWRITE_TAC[] THEN + SUBGOAL_THEN `~(0x2 EXP (0x8 * len) = 0x0)` ASSUME_TAC THENL + [ REWRITE_TAC[EXP_EQ_0; ARITH_EQ]; ALL_TAC] THEN + IMP_REWRITE_TAC[DIV_MULT_ADD] THEN + SUBGOAL_THEN `read (bytes (ptr,len)) (read memory s) < 0x2 EXP (0x8 * len)` ASSUME_TAC THENL + [ REWRITE_TAC[READ_BYTES_BOUND]; ALL_TAC] THEN + SUBGOAL_THEN `num_of_bytelist (SUB_LIST (0x0,len) bl) < 0x2 EXP (0x8 * len)` ASSUME_TAC THENL + [ MP_TAC (SPEC `(SUB_LIST (0,len) bl:byte list)` NUM_OF_BYTELIST_BOUND) THEN + IMP_REWRITE_TAC[LENGTH_SUB_LIST; SUB_0; MIN] THEN + SUBGOAL_THEN `256 EXP len = 2 EXP (8 * len)` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `256 = 2 EXP 8`; EXP_EXP]; ALL_TAC] THEN SIMP_TAC[]; ALL_TAC] THEN + IMP_REWRITE_TAC[DIV_LT; ADD] THEN + (* Some rewrites to close the goal *) + REWRITE_TAC[bytes8; READ_COMPONENT_COMPOSE; asword; through; read] THEN + SUBGOAL_THEN `len < LENGTH (bl:byte list)` ASSUME_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[SUB_LIST_1] THEN + REWRITE_TAC[num_of_bytelist; MULT_CLAUSES; ADD_CLAUSES; WORD_VAL] +);; + +let BYTE_LIST_TO_NUM_THM = prove( + `!len (ptr:int64) (bl:byte list) s. + len <= LENGTH bl ==> + ((forall i. i < len + ==> read (memory :> bytes8 (word_add ptr (word i))) s = EL i bl) <=> + (read (memory :> bytes (ptr, len)) s = num_of_bytelist (SUB_LIST (0, len) bl)))`, + REPEAT GEN_TAC THEN + SPEC_TAC (`len:num`, `len:num`) THEN + (* Base case: len = 0 *) + INDUCT_TAC THENL + [ STRIP_TAC THEN + REWRITE_TAC[READ_COMPONENT_COMPOSE; READ_BYTES_TRIVIAL; + CONJUNCT1 SUB_LIST; CONJUNCT1 num_of_bytelist] THEN + GEN_TAC THEN MESON_TAC[ARITH_RULE `~(i < 0)`]; + ALL_TAC] THEN + + (* Inductive step: left to right *) + STRIP_TAC THEN + EQ_TAC THENL + [ MP_TAC (ARITH_RULE `SUC len <= LENGTH (bl:byte list) ==> len <= LENGTH bl`) THEN + ASM_SIMP_TAC[] THEN REPEAT DISCH_TAC THEN + MP_TAC (SPECL [`len:num`; `ptr:int64`; `bl:byte list`; `s:armstate`] MEMORY_READ_SUBSET_LEMMA) THEN + ASM_SIMP_TAC[] THEN + DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN + REWRITE_TAC[READ_COMPONENT_COMPOSE; ADD1] THEN + ONCE_REWRITE_TAC[READ_BYTES_COMBINE] THEN + REWRITE_TAC[SUB_LIST_SPLIT; NUM_OF_BYTELIST_APPEND; CONJUNCT1 ADD] THEN + IMP_REWRITE_TAC[ARITH_RULE `a = c ==> (a + b = c + d) = (b = d)`] THEN + CONJ_TAC THENL [ + REWRITE_TAC[LENGTH_SUB_LIST; MIN; SUB_0] THEN + ASM_SIMP_TAC[] THEN + AP_TERM_TAC THEN + REWRITE_TAC[GSYM READ_COMPONENT_COMPOSE] THEN + FIRST_X_ASSUM (fun th -> MP_TAC (SPEC `len:num` th)) THEN + REWRITE_TAC[ARITH_RULE `len < SUC len`] THEN + SUBGOAL_THEN `len < LENGTH (bl:byte list)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[SUB_LIST_1; num_of_bytelist] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[ADD_0] THEN + STRIP_TAC THEN AP_TERM_TAC THEN ASM_SIMP_TAC[] + ; ALL_TAC] THEN + REWRITE_TAC[GSYM READ_COMPONENT_COMPOSE] THEN + ASM_SIMP_TAC[] + ; ALL_TAC] THEN + + (* Inductive step: right to left *) + MP_TAC (ARITH_RULE `SUC len <= LENGTH (bl:byte list) ==> len <= LENGTH bl`) THEN + ASM_SIMP_TAC[] THEN REPEAT DISCH_TAC THEN + MP_TAC (SPECL [`len:num`; `ptr:int64`; `bl:byte list`; `s:armstate`] MEMORY_READ_BYTES_SUBSET_LEMMA) THEN + ASM_SIMP_TAC[] THEN + DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN + IMP_REWRITE_TAC[BYTE_LIST_AT_SPLIT] THEN + CONJ_TAC THENL [ASM_SIMP_TAC[]; ALL_TAC] THEN + ASM_SIMP_TAC[] +);; + + +let READ_MEMORY_BYTES128_BYTES = prove(`!z s. + read (memory :> bytes128 z) s = word (read (memory :> bytes (z,16)) s)`, + REPEAT STRIP_TAC THEN + ONCE_REWRITE_TAC[GSYM VAL_EQ] THEN + IMP_REWRITE_TAC [VAL_WORD_EQ] THEN + CONJ_TAC THENL [REWRITE_TAC [READ_MEMORY_BYTES_BYTES128]; ALL_TAC] THEN + REWRITE_TAC [MEMORY_BYTES_BOUND] + );; + +let WORD_JOIN_BOUND_TAC x y = + REWRITE_TAC[VAL_WORD_JOIN; DIMINDEX_CLAUSES] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[MOD_LT] THEN + CONJ_TAC THENL[ REWRITE_TAC[ADD_SYM]; ALL_TAC ] THEN + MP_TAC (ISPECL [x] VAL_BOUND) THEN + MP_TAC (ISPECL [y] VAL_BOUND) THEN + REWRITE_TAC[DIMINDEX_CLAUSES] THEN + CONV_TAC NUM_REDUCE_CONV THEN + ARITH_TAC;; + +let WORD_JOIN_16_8_ASSOC = WORD_BLAST + `!(x0:byte) (x1:byte) (x2:byte) (x3:byte) + (x4:byte) (x5:byte) (x6:byte) (x7:byte) + (x8:byte) (x9:byte) (x10:byte) (x11:byte) + (x12:byte) (x13:byte) (x14:byte) (x15:byte). + (word_join + (word_join + (word_join (word_join x15 x14 : int16) (word_join x13 x12 : int16) : int32) + (word_join (word_join x11 x10 : int16) (word_join x9 x8 : int16) : int32) : int64) + (word_join + (word_join (word_join x7 x6 : int16) (word_join x5 x4 : int16) : int32) + (word_join (word_join x3 x2 : int16) (word_join x1 x0 : int16) : int32) : int64)) = + (word_join + (word_join + (word_join + (word_join + (word_join + (word_join + (word_join + (word_join + (word_join + (word_join + (word_join + (word_join + (word_join + (word_join + (word_join x15 x14:16 word) + x13:24 word) + x12:32 word) + x11:40 word) + x10:48 word) + x9:56 word) + x8:64 word) + x7:72 word) + x6:80 word) + x5:88 word) + x4:96 word) + x3:104 word) + x2:112 word) + x1:120 word) + x0:128 word)`;; + +let VAL_OF_BYTES_TO_INT128_EQ_NUM_OF_BYTELIST = prove( + `!x:byte list. LENGTH x = 16 ==> val (bytes_to_int128 x) = num_of_bytelist x`, + REPEAT STRIP_TAC THEN + (* conversion for breaking down a list *) + MP_TAC ((GEN_REWRITE_CONV I [LENGTH_EQ_LIST_OF_SEQ] THENC + RAND_CONV LIST_OF_SEQ_CONV) `LENGTH (x:byte list) = 16`) THEN + ASM_SIMP_TAC[] THEN + DISCH_THEN (fun th -> ONCE_REWRITE_TAC[th]) THEN + REWRITE_TAC[bytes_to_int128] THEN + REWRITE_TAC EL_16_8_CLAUSES THEN + REPEAT_N 16 (ONCE_REWRITE_TAC[num_of_bytelist]) THEN + REWRITE_TAC[CONJUNCT1 num_of_bytelist] THEN + MAP_EVERY ABBREV_TAC + [`x0 = EL 0 x:byte`; `x1 = EL 1 x:byte`; `x2 = EL 2 x:byte`; `x3 = EL 3 x:byte`; + `x4 = EL 4 x:byte`; `x5 = EL 5 x:byte`; `x6 = EL 6 x:byte`; `x7 = EL 7 x:byte`; + `x8 = EL 8 x:byte`; `x9 = EL 9 x:byte`; `x10 = EL 10 x:byte`; `x11 = EL 11 x:byte`; + `x12 = EL 12 x:byte`; `x13 = EL 13 x:byte`; `x14 = EL 14 x:byte`; `x15 = EL 15 x:byte`] THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[ADD_0; WORD_JOIN_16_8_ASSOC] THEN + (* reduce RHS to LHS *) + SUBGOAL_THEN `val (x14:byte) + 0x100 * val (x15:byte) = val ((word_join x15 x14):int16)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `x15:byte` `x14:byte`; ALL_TAC] THEN ABBREV_TAC `y14:int16 = word_join (x15:byte) (x14:byte)` THEN + SUBGOAL_THEN `val (x13:byte) + 0x100 * val (y14:16 word) = val ((word_join y14 x13):24 word)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `y14:16 word` `x13:byte`; ALL_TAC] THEN ABBREV_TAC `y13:24 word = word_join (y14:16 word) (x13:byte)` THEN + SUBGOAL_THEN `val (x12:byte) + 0x100 * val (y13:24 word) = val ((word_join y13 x12):32 word)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `y13:24 word` `x12:byte`; ALL_TAC] THEN ABBREV_TAC `y12:32 word = word_join (y13:24 word) (x12:byte)` THEN + SUBGOAL_THEN `val (x11:byte) + 0x100 * val (y12:32 word) = val ((word_join y12 x11):40 word)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `y12:32 word` `x11:byte`; ALL_TAC] THEN ABBREV_TAC `y11:40 word = word_join (y12:32 word) (x11:byte)` THEN + SUBGOAL_THEN `val (x10:byte) + 0x100 * val (y11:40 word) = val ((word_join y11 x10):48 word)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `y11:40 word` `x10:byte`; ALL_TAC] THEN ABBREV_TAC `y10:48 word = word_join (y11:40 word) (x10:byte)` THEN + SUBGOAL_THEN `val (x9:byte) + 0x100 * val (y10:48 word) = val ((word_join y10 x9):56 word)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `y10:48 word` `x9:byte`; ALL_TAC] THEN ABBREV_TAC `y9:56 word = word_join (y10:48 word) (x9:byte)` THEN + SUBGOAL_THEN `val (x8:byte) + 0x100 * val (y9:56 word) = val ((word_join y9 x8):64 word)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `y9:56 word` `x8:byte`; ALL_TAC] THEN ABBREV_TAC `y8:64 word = word_join (y9:56 word) (x8:byte)` THEN + SUBGOAL_THEN `val (x7:byte) + 0x100 * val (y8:64 word) = val ((word_join y8 x7):72 word)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `y8:64 word` `x7:byte`; ALL_TAC] THEN ABBREV_TAC `y7:72 word = word_join (y8:64 word) (x7:byte)` THEN + SUBGOAL_THEN `val (x6:byte) + 0x100 * val (y7:72 word) = val ((word_join y7 x6):80 word)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `y7:72 word` `x6:byte`; ALL_TAC] THEN ABBREV_TAC `y6:80 word = word_join (y7:72 word) (x6:byte)` THEN + SUBGOAL_THEN `val (x5:byte) + 0x100 * val (y6:80 word) = val ((word_join y6 x5):88 word)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `y6:80 word` `x5:byte`; ALL_TAC] THEN ABBREV_TAC `y5:88 word = word_join (y6:80 word) (x5:byte)` THEN + SUBGOAL_THEN `val (x4:byte) + 0x100 * val (y5:88 word) = val ((word_join y5 x4):96 word)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `y5:88 word` `x4:byte`; ALL_TAC] THEN ABBREV_TAC `y4:96 word = word_join (y5:88 word) (x4:byte)` THEN + SUBGOAL_THEN `val (x3:byte) + 0x100 * val (y4:96 word) = val ((word_join y4 x3):104 word)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `y4:96 word` `x3:byte`; ALL_TAC] THEN ABBREV_TAC `y3:104 word = word_join (y4:96 word) (x3:byte)` THEN + SUBGOAL_THEN `val (x2:byte) + 0x100 * val (y3:104 word) = val ((word_join y3 x2):112 word)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `y3:104 word` `x2:byte`; ALL_TAC] THEN ABBREV_TAC `y2:112 word = word_join (y3:104 word) (x2:byte)` THEN + SUBGOAL_THEN `val (x1:byte) + 0x100 * val (y2:112 word) = val ((word_join y2 x1):120 word)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `y2:112 word` `x1:byte`; ALL_TAC] THEN ABBREV_TAC `y1:120 word = word_join (y2:112 word) (x1:byte)` THEN + SUBGOAL_THEN `val (x0:byte) + 0x100 * val (y1:120 word) = val ((word_join y1 x0):128 word)` SUBST1_TAC THENL + [ WORD_JOIN_BOUND_TAC `y1:120 word` `x0:byte`; ALL_TAC] THEN ABBREV_TAC `y0:128 word = word_join (y1:120 word) (x0:byte)` THEN + REFL_TAC +);; + + +let READ_BYTES_AND_BYTE128_SPLIT = prove( + `!(pt_ptr:int64) (sz:num) (x:byte list) (s:armstate). + sz + 16 <= LENGTH x ==> + read (memory :> bytes128 (word_add pt_ptr (word sz))) s = bytes_to_int128 (SUB_LIST (sz, 0x10) x) + /\ read (memory :> bytes (pt_ptr, sz)) s = num_of_bytelist (SUB_LIST (0, sz) x) + ==> read (memory :> bytes (pt_ptr,sz + 0x10)) s = num_of_bytelist (SUB_LIST (0, sz + 0x10) x)`, + REWRITE_TAC[READ_MEMORY_BYTES128_BYTES] THEN + REPEAT STRIP_TAC THEN + + SUBGOAL_THEN `sz <= LENGTH (x:byte list)` ASSUME_TAC THENL + [ UNDISCH_TAC `sz + 16 <= LENGTH (x:byte list)` THEN ARITH_TAC; ALL_TAC ] THEN + + SUBGOAL_THEN `16 <= LENGTH (x:byte list) - sz` ASSUME_TAC THENL + [ UNDISCH_TAC `sz + 16 <= LENGTH (x:byte list)` THEN ARITH_TAC; ALL_TAC ] THEN + + SUBGOAL_THEN `read (memory :> bytes (pt_ptr, sz + 16)) s = + read (memory :> bytes (pt_ptr, sz)) s + + 2 EXP (8 * sz) * (read (memory :> bytes (word_add pt_ptr (word sz), 16)) s)` SUBST1_TAC THENL + [ REWRITE_TAC[READ_COMPONENT_COMPOSE] THEN + REWRITE_TAC[READ_BYTES_COMBINE]; ALL_TAC] THEN + + ASM_REWRITE_TAC[] THEN + SUBGOAL_THEN `read (memory :> bytes (word_add pt_ptr (word sz),0x10)) s = + val (bytes_to_int128 (SUB_LIST (sz,0x10) x))` SUBST1_TAC THENL + [ UNDISCH_THEN + `word (read (memory :> bytes (word_add (pt_ptr:int64) (word sz),0x10)) s) = + bytes_to_int128 (SUB_LIST (sz,0x10) x)` + (fun th -> MP_TAC (AP_TERM `val:int128->num` th)) THEN + IMP_REWRITE_TAC[VAL_WORD] THEN + SUBGOAL_THEN `read (memory :> bytes (word_add pt_ptr (word sz),0x10)) s < 2 EXP dimindex (:128)` ASSUME_TAC THENL + [ SIMP_TAC[MEMORY_BYTES_BOUND] ; ALL_TAC] THEN + SUBST_ALL_TAC DIMINDEX_128 THEN + ASM_SIMP_TAC[MOD_LT]; ALL_TAC] THEN + + IMP_REWRITE_TAC[NUM_OF_BYTELIST_OF_SUB_LIST] THEN + IMP_REWRITE_TAC[VAL_OF_BYTES_TO_INT128_EQ_NUM_OF_BYTELIST] THEN + REWRITE_TAC[LENGTH_SUB_LIST; MIN] THEN ASM_SIMP_TAC[] +);; + +let READ_BYTES_AND_BYTE128_MERGE = prove( + `!(pt_ptr:int64) (sz:num) (x:byte list) (s:armstate). + sz + 16 <= LENGTH x ==> + read (memory :> bytes (pt_ptr,sz + 0x10)) s = num_of_bytelist (SUB_LIST (0, sz + 0x10) x) + ==> (read (memory :> bytes (pt_ptr, sz)) s = num_of_bytelist (SUB_LIST (0, sz) x) /\ + read (memory :> bytes128 (word_add pt_ptr (word sz))) s = bytes_to_int128 (SUB_LIST (sz, 0x10) x))`, + REPEAT GEN_TAC THEN + STRIP_TAC THEN + REWRITE_TAC[READ_MEMORY_BYTES128_BYTES] THEN + + SUBGOAL_THEN `sz <= LENGTH (x:byte list)` ASSUME_TAC THENL + [ UNDISCH_TAC `sz + 16 <= LENGTH (x:byte list)` THEN ARITH_TAC; ALL_TAC ] THEN + + SUBGOAL_THEN `16 <= LENGTH (x:byte list) - sz` ASSUME_TAC THENL + [ UNDISCH_TAC `sz + 16 <= LENGTH (x:byte list)` THEN ARITH_TAC; ALL_TAC ] THEN + + SUBGOAL_THEN `read (memory :> bytes (pt_ptr, sz + 16)) s = + read (memory :> bytes (pt_ptr, sz)) s + + 2 EXP (8 * sz) * (read (memory :> bytes (word_add pt_ptr (word sz), 16)) s)` SUBST1_TAC THENL + [ REWRITE_TAC[READ_COMPONENT_COMPOSE] THEN + REWRITE_TAC[READ_BYTES_COMBINE]; ALL_TAC] THEN + + IMP_REWRITE_TAC[NUM_OF_BYTELIST_OF_SUB_LIST] THEN + REWRITE_TAC[READ_COMPONENT_COMPOSE] THEN + + DISCH_TAC THEN + CONJ_TAC THENL + [ (* First part: `read (bytes (pt_ptr,sz)) (read memory s) = + num_of_bytelist (SUB_LIST (0x0,sz) x)`*) + FIRST_X_ASSUM(MP_TAC o AP_TERM `\x. x MOD 2 EXP (8 * sz)`) THEN + ASM_REWRITE_TAC[] THEN + REWRITE_TAC[MOD_MULT_ADD; MOD_LT] THEN + REWRITE_TAC[READ_BYTES_MOD; MIN] THEN + SIMP_TAC[ARITH_RULE `len <= len`] THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[MOD_LT] THEN + MP_TAC (SPEC `(SUB_LIST (0,sz) x:byte list)` NUM_OF_BYTELIST_BOUND) THEN + IMP_REWRITE_TAC[LENGTH_SUB_LIST; SUB_0; MIN] THEN + SUBGOAL_THEN `256 EXP sz = 2 EXP (8 * sz)` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `256 = 2 EXP 8`; EXP_EXP]; ALL_TAC] THEN + SIMP_TAC[]; + ALL_TAC + ] THEN + (* Second part: word (read (bytes (word_add pt_ptr (word sz),0x10)) (read memory s)) = + bytes_to_int128 (SUB_LIST (sz,0x10) x) *) + FIRST_X_ASSUM(MP_TAC o AP_TERM `\x. x DIV 2 EXP (8 * sz)`) THEN + ASM_REWRITE_TAC[] THEN + SUBGOAL_THEN `~(0x2 EXP (0x8 * sz) = 0x0)` ASSUME_TAC THENL + [ REWRITE_TAC[EXP_EQ_0; ARITH_EQ]; ALL_TAC] THEN + IMP_REWRITE_TAC[DIV_MULT_ADD] THEN + SUBGOAL_THEN `read (bytes (pt_ptr,sz)) (read memory s) < 0x2 EXP (0x8 * sz)` ASSUME_TAC THENL + [ REWRITE_TAC[READ_BYTES_BOUND]; ALL_TAC] THEN + SUBGOAL_THEN `num_of_bytelist (SUB_LIST (0x0,sz) x) < 0x2 EXP (0x8 * sz)` ASSUME_TAC THENL + [ MP_TAC (SPEC `(SUB_LIST (0,sz) x:byte list)` NUM_OF_BYTELIST_BOUND) THEN + IMP_REWRITE_TAC[LENGTH_SUB_LIST; SUB_0; MIN] THEN + SUBGOAL_THEN `256 EXP sz = 2 EXP (8 * sz)` SUBST1_TAC THENL + [ REWRITE_TAC[ARITH_RULE `256 = 2 EXP 8`; EXP_EXP]; ALL_TAC] THEN SIMP_TAC[]; ALL_TAC] THEN + IMP_REWRITE_TAC[DIV_LT; ADD] THEN + DISCH_TAC THEN + + ONCE_REWRITE_TAC[GSYM VAL_EQ] THEN + IMP_REWRITE_TAC[VAL_OF_BYTES_TO_INT128_EQ_NUM_OF_BYTELIST] THEN + REWRITE_TAC[LENGTH_SUB_LIST; MIN] THEN ASM_SIMP_TAC[] THEN + REWRITE_TAC[VAL_WORD; DIMINDEX_128] THEN + SUBGOAL_THEN `num_of_bytelist (SUB_LIST (sz,0x10) x) < 2 EXP 0x80` ASSUME_TAC THENL + [ MP_TAC (SPEC `(SUB_LIST (sz,0x10) x:byte list)` NUM_OF_BYTELIST_BOUND) THEN + IMP_REWRITE_TAC[LENGTH_SUB_LIST; SUB_0; MIN] THEN + ARITH_TAC; ALL_TAC] THEN + IMP_REWRITE_TAC[MOD_LT] +);; + + +let DIVISION_BY_80_LEMMA = prove( + `!(a:num) b. a DIV 0x50 = b /\ + 0x10 divides a /\ + ~(a - b * 0x50 = 0x10) /\ + ~(a - b * 0x50 = 0x20) /\ + ~(a - b * 0x50 = 0x30) /\ + ~(a - b * 0x50 = 0x40) ==> + b * 0x50 = a`, + REPEAT STRIP_TAC THEN + (* Use the division theorem: a = b * 0x50 + (a MOD 0x50) *) + MP_TAC (SPECL [`a:num`; `0x50`] DIVISION) THEN + CONV_TAC NUM_REDUCE_CONV THEN + REPEAT STRIP_TAC THEN + + (* We have a = b * 0x50 + (a MOD 0x50) and a DIV 0x50 = b *) + SUBGOAL_THEN `a = b * 0x50 + (a MOD 0x50)` ASSUME_TAC THENL [ + ASM_ARITH_TAC; ALL_TAC] THEN + + (* Show that a MOD 0x50 = 0 by case analysis *) + SUBGOAL_THEN `a MOD 0x50 = 0` ASSUME_TAC THENL [ + (* Since 0x10 divides a, we know a = k * 0x10 for some k *) + UNDISCH_TAC `0x10 divides a` THEN + REWRITE_TAC[divides] THEN + STRIP_TAC THEN + + (* The remainder a MOD 0x50 must be a multiple of 0x10 and < 0x50 *) + (* So it's one of: 0, 0x10, 0x20, 0x30, 0x40 *) + SUBGOAL_THEN `(a MOD 0x50 = 0) \/ (a MOD 0x50 = 0x10) \/ + (a MOD 0x50 = 0x20) \/ (a MOD 0x50 = 0x30) \/ + (a MOD 0x50 = 0x40)` ASSUME_TAC THENL + [ ASM_REWRITE_TAC[] THEN + + SUBGOAL_THEN `(0x10 * x) MOD 0x50 = (x MOD 5) * 0x10` SUBST1_TAC THENL [ + SUBGOAL_THEN `0x50 = 5 * 0x10` SUBST1_TAC THENL [ + CONV_TAC NUM_REDUCE_CONV; ALL_TAC] THEN + MP_TAC (SPECL [`0x10 * x`; `0x10`; `5`] MOD_MULT_MOD) THEN + REWRITE_TAC[MOD_MULT; ADD_CLAUSES] THEN + IMP_REWRITE_TAC[DIV_MULT] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SIMP_TAC[] THEN DISCH_TAC THEN + REWRITE_TAC[MULT_SYM] + ; ALL_TAC] THEN + + SUBGOAL_THEN `x MOD 5 < 5` ASSUME_TAC THENL [ + REWRITE_TAC[MOD_LT_EQ] THEN CONV_TAC NUM_REDUCE_CONV; ALL_TAC] THEN + SUBGOAL_THEN `x MOD 5 = 0 \/ x MOD 5 = 1 \/ x MOD 5 = 2 \/ x MOD 5 = 3 \/ x MOD 5 = 4` ASSUME_TAC THENL [ + UNDISCH_TAC `x MOD 0x5 < 0x5` THEN ARITH_TAC ; ALL_TAC] THEN + + REPEAT (FIRST_X_ASSUM DISJ_CASES_TAC) THENL + [ ASM_REWRITE_TAC[] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[] THEN CONV_TAC NUM_REDUCE_CONV; + ASM_REWRITE_TAC[] THEN CONV_TAC NUM_REDUCE_CONV] + ; ALL_TAC] THEN + + (* Now eliminate the non-zero cases using the assumptions *) + SUBGOAL_THEN `~(a MOD 0x50 = 0x10)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(a - b * 0x50 = 0x10)` THEN + UNDISCH_TAC `a = b * 0x50 + a MOD 0x50` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(a MOD 0x50 = 0x20)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(a - b * 0x50 = 0x20)` THEN + UNDISCH_TAC `a = b * 0x50 + a MOD 0x50` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(a MOD 0x50 = 0x30)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(a - b * 0x50 = 0x30)` THEN + UNDISCH_TAC `a = b * 0x50 + a MOD 0x50` THEN + ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(a MOD 0x50 = 0x40)` ASSUME_TAC THENL + [ UNDISCH_TAC `~(a - b * 0x50 = 0x40)` THEN + UNDISCH_TAC `a = b * 0x50 + a MOD 0x50` THEN + ARITH_TAC; ALL_TAC] THEN + + ASM_MESON_TAC[]; ALL_TAC + ] THEN + + (* Finally conclude b * 0x50 = a *) + ASM_ARITH_TAC +);; + + +let NUM_BLOCKS_TO_VAL = prove( + `!(len:int64). word_and len (word 0xfffffffffffffff0) = word (16 * (val len DIV 16))`, + GEN_TAC THEN + REWRITE_TAC[WORD_AND_MASK16] THEN + REWRITE_TAC[GSYM VAL_EQ] THEN + SUBGOAL_THEN `16 * val (len:int64) DIV 16 = val len - (val len MOD 16)` SUBST1_TAC THENL + [REWRITE_TAC[DIVISION_SIMP] THEN ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[ARITH_RULE `0xf = 2 EXP 4 - 1`] THEN + REWRITE_TAC[WORD_AND_MASK_WORD] THEN + CONV_TAC NUM_REDUCE_CONV THEN + + REWRITE_TAC[VAL_WORD_SUB] THEN + SUBGOAL_THEN `val (len:int64) >= val ((word (val len MOD 0x10)):int64)` ASSUME_TAC THENL [ + REWRITE_TAC[VAL_WORD; DIMINDEX_64; GE] THEN + MP_TAC (SPECL [`val (len:int64) MOD 0x10`; `0x2 EXP 0x40`] MOD_LE) THEN + ARITH_TAC; + ALL_TAC + ] THEN + REWRITE_TAC[VAL_WORD; DIMINDEX_64] THEN + + SUBGOAL_THEN `val (len:int64) MOD 0x10 < 0x2 EXP 0x40` ASSUME_TAC THENL + [ TRANS_TAC LET_TRANS `val (len:int64)` THEN + REWRITE_TAC[VAL_BOUND_64; MOD_LE]; ALL_TAC] THEN + + SUBGOAL_THEN `val (len:int64) MOD 0x10 MOD 0x2 EXP 0x40 = val len MOD 0x10` ASSUME_TAC THENL + [ MP_TAC (SPECL [`val (len:int64) MOD 0x10`; `0x2 EXP 0x40`] MOD_LT) THEN + ASM_SIMP_TAC[]; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + + MP_TAC (SPECL [`val (len:int64)`; `0x2 EXP 0x40`; `val (len:int64) MOD 0x10`] + (ARITH_RULE `!a b c. c <= a ==> c <= b ==> a + b - c = (a - c) + b`)) THEN + ANTS_TAC THENL [ REWRITE_TAC[MOD_LE]; ALL_TAC] THEN + ANTS_TAC THENL [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN DISCH_TAC THEN + + MP_TAC (SPECL [`1`; `0x2 EXP 0x40`; `val (len:int64) - val len MOD 0x10`] + (CONJUNCT1 (CONJUNCT2 (CONJUNCT2 MOD_MULT_ADD)))) THEN + CONV_TAC NUM_REDUCE_CONV +);; + +let NUM_BLOCKS_MINUS1_TO_VAL = prove( + `!(len:int64). val len >= 16 ==> + word_sub (word_and (len:int64) (word 0xfffffffffffffff0)) (word 0x10) = + word (16 * (val len DIV 16 - 1))`, + REWRITE_TAC[NUM_BLOCKS_TO_VAL] THEN + REPEAT STRIP_TAC THEN + REWRITE_TAC[LEFT_SUB_DISTRIB; WORD_SUB] THEN + CONV_TAC NUM_REDUCE_CONV THEN + SUBGOAL_THEN `0x10 <= 0x10 * val (len:int64) DIV 0x10` ASSUME_TAC THENL + [ MP_TAC (SPECL [`0x10`; `val (len:int64)`; `1`] LE_RDIV_EQ) THEN + CONV_TAC NUM_REDUCE_CONV THEN + REWRITE_TAC[GSYM GE] THEN + ASM_SIMP_TAC[] THEN + ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] +);; + +let BREAK_ONE_BLOCK_INTO_BYTES = prove( + `!(addr:int64) (s:armstate) (p:int128). + read (memory :> bytes128 addr) s = p <=> + (read (memory :> bytes8 addr) s = EL 0 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 1))) s = EL 1 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 2))) s = EL 2 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 3))) s = EL 3 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 4))) s = EL 4 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 5))) s = EL 5 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 6))) s = EL 6 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 7))) s = EL 7 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 8))) s = EL 8 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 9))) s = EL 9 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 10))) s = EL 10 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 11))) s = EL 11 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 12))) s = EL 12 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 13))) s = EL 13 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 14))) s = EL 14 (int128_to_bytes p) /\ + read (memory :> bytes8 (word_add addr (word 15))) s = EL 15 (int128_to_bytes p)) + `, + REPEAT GEN_TAC THEN + EQ_TAC THENL[ + STRIP_TAC THEN + MP_TAC (SPECL [`0:num`; `addr:int64`; `s:armstate`] BYTES128_TO_BYTES8_THM) THEN + REWRITE_TAC[WORD_ADD_0] THEN CONV_TAC NUM_REDUCE_CONV THEN + ASM_REWRITE_TAC[] THEN + DISCH_TAC THEN + REWRITE_TAC[int128_to_bytes] THEN + REWRITE_TAC EL_16_8_CLAUSES THEN + ASM_REWRITE_TAC[] THEN + REWRITE_TAC[bytes_to_int128] THEN + REWRITE_TAC EL_16_8_CLAUSES THEN + REWRITE_TAC[WORD_ADD_0] THEN + ABBREV_TAC `x0 = read (memory :> bytes8 (addr:int64)) s` THEN + ABBREV_TAC `x1 = read (memory :> bytes8 (word_add (addr:int64) (word 0x1))) s` THEN + ABBREV_TAC `x2 = read (memory :> bytes8 (word_add (addr:int64) (word 0x2))) s` THEN + ABBREV_TAC `x3 = read (memory :> bytes8 (word_add (addr:int64) (word 0x3))) s` THEN + ABBREV_TAC `x4 = read (memory :> bytes8 (word_add (addr:int64) (word 0x4))) s` THEN + ABBREV_TAC `x5 = read (memory :> bytes8 (word_add (addr:int64) (word 0x5))) s` THEN + ABBREV_TAC `x6 = read (memory :> bytes8 (word_add (addr:int64) (word 0x6))) s` THEN + ABBREV_TAC `x7 = read (memory :> bytes8 (word_add (addr:int64) (word 0x7))) s` THEN + ABBREV_TAC `x8 = read (memory :> bytes8 (word_add (addr:int64) (word 0x8))) s` THEN + ABBREV_TAC `x9 = read (memory :> bytes8 (word_add (addr:int64) (word 0x9))) s` THEN + ABBREV_TAC `xa = read (memory :> bytes8 (word_add (addr:int64) (word 0xa))) s` THEN + ABBREV_TAC `xb = read (memory :> bytes8 (word_add (addr:int64) (word 0xb))) s` THEN + ABBREV_TAC `xc = read (memory :> bytes8 (word_add (addr:int64) (word 0xc))) s` THEN + ABBREV_TAC `xd = read (memory :> bytes8 (word_add (addr:int64) (word 0xd))) s` THEN + ABBREV_TAC `xe = read (memory :> bytes8 (word_add (addr:int64) (word 0xe))) s` THEN + ABBREV_TAC `xf = read (memory :> bytes8 (word_add (addr:int64) (word 0xf))) s` THEN + REPEAT STRIP_TAC THEN + REPEAT BITBLAST_TAC; ALL_TAC] THEN + + REPEAT STRIP_TAC THEN + MP_TAC (SPECL [`0:num`; `addr:int64`; `s:armstate`] BYTES128_TO_BYTES8_THM) THEN + CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[WORD_ADD_0] THEN + ASM_REWRITE_TAC[] THEN + DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN + REWRITE_TAC[int128_to_bytes] THEN + REWRITE_TAC EL_16_8_CLAUSES THEN + REWRITE_TAC[bytes_to_int128] THEN + REWRITE_TAC EL_16_8_CLAUSES THEN + BITBLAST_TAC +);; + +let SELECT_ONE_BYTE_FROM_BLOCK = prove( + `!(addr:int64) (off:int64) (s:armstate) (p:int128). + read (memory :> bytes128 addr) s = p ==> + val off < 16 ==> + read (memory :> bytes8 (word_add addr off)) s = EL (val off) (int128_to_bytes p)`, + REPEAT STRIP_TAC THEN + FIRST_ASSUM (STRIP_ASSUME_TAC o + MATCH_MP (fst (EQ_IMP_RULE + (SPECL [`addr:int64`; `s:armstate`; `p:int128`] BREAK_ONE_BLOCK_INTO_BYTES)))) THEN + SUBGOAL_THEN `word_add addr (off:int64) = word_add addr (word (val off))` SUBST1_TAC THENL + [REWRITE_TAC[WORD_VAL]; ALL_TAC] THEN + UNDISCH_TAC `val (off:int64) < 16` THEN + SPEC_TAC (`val (off:int64)`, `n:num`) THEN + CONV_TAC EXPAND_CASES_CONV THEN + ASM_REWRITE_TAC[WORD_ADD_0] +);; + +let SELECT_ONE_BYTE_FROM_FORALL = prove( + `!(ptr:int64) (len:int64) (addr:int64) (bl:byte list) (s:armstate). + (forall j. j < val len ==> read (memory :> bytes8 (word_add ptr (word j))) s = EL j bl) ==> + val addr < val len ==> + LENGTH bl = val len ==> + read (memory :> bytes8 (word_add ptr addr)) s = EL (val addr) bl`, + REPEAT STRIP_TAC THEN + FIRST_X_ASSUM (MP_TAC o SPEC `val (addr:int64)`) THEN + ASM_REWRITE_TAC[] THEN + REWRITE_TAC[WORD_VAL] +);; + +let IVAL_WORD_LT = prove( + `!i. i < 2 EXP 63 ==> ival ((word i):int64) = &i`, + GEN_TAC THEN DISCH_TAC THEN + REWRITE_TAC[ival; DIMINDEX_64; ARITH_RULE `64 - 1 = 63`] THEN + REWRITE_TAC[VAL_WORD; DIMINDEX_64] THEN + SUBGOAL_THEN `i < 2 EXP 64` ASSUME_TAC THENL + [ TRANS_TAC LT_TRANS `2 EXP 63` THEN + ASM_REWRITE_TAC[] THEN + CONV_TAC NUM_REDUCE_CONV; + ALL_TAC] THEN + ASM_SIMP_TAC[MOD_LT] +);; + +let READ_LT_2BLOCK = prove( + `!(ptr:int64) (len:int64) (bl:byte list) (s:armstate). + LENGTH bl = val len ==> + val len >= 0x10 ==> + val len < 0x20 ==> + (forall i. i < val len + ==> read (memory :> bytes8 (word_add ptr (word i))) s = EL i bl) + ==> read (memory :> bytes128 ptr) s = bytes_to_int128 (SUB_LIST (0, 16) bl)`, + REPEAT STRIP_TAC THEN + MP_TAC (SPECL [`0:num`; `bl:byte list`; `ptr:int64`; + `len:int64`; `s:armstate`] BYTE_LIST_AT_1BLOCKS) THEN + REWRITE_TAC[byte_list_at] THEN + ANTS_TAC THENL[ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL[ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL[ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[WORD_ADD_0] +);; + +let READ_LT_3BLOCK = prove( + `!(ptr:int64) (len:int64) (bl:byte list) (s:armstate). + LENGTH bl = val len ==> + ~(val len < 0x20) ==> + val len < 0x30 ==> + (forall i. i < val len + ==> read (memory :> bytes8 (word_add ptr (word i))) s = EL i bl) + ==> read (memory :> bytes128 ptr) s = bytes_to_int128 (SUB_LIST (0, 16) bl) /\ + read (memory :> bytes128 (word_add ptr (word 16))) s = + bytes_to_int128 (SUB_LIST (16, 16) bl)`, + REPEAT GEN_TAC THEN REPEAT_N 4 STRIP_TAC THEN + MP_TAC (SPECL [`0:num`; `bl:byte list`; `ptr:int64`; + `len:int64`; `s:armstate`] BYTE_LIST_AT_2BLOCKS) THEN + REWRITE_TAC[byte_list_at] THEN + ANTS_TAC THENL[ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL[ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL[ ASM_ARITH_TAC; ALL_TAC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_SIMP_TAC[WORD_ADD_0] +);; + +let READ_LT_4BLOCK = prove( + `!(ptr:int64) (len:int64) (bl:byte list) (s:armstate). + LENGTH bl = val len ==> + ~(val len < 0x30) ==> + val len < 0x40 ==> + (forall i. i < val len + ==> read (memory :> bytes8 (word_add ptr (word i))) s = EL i bl) + ==> read (memory :> bytes128 ptr) s = bytes_to_int128 (SUB_LIST (0, 16) bl) /\ + read (memory :> bytes128 (word_add ptr (word 16))) s = + bytes_to_int128 (SUB_LIST (16, 16) bl) /\ + read (memory :> bytes128 (word_add ptr (word 32))) s = + bytes_to_int128 (SUB_LIST (32, 16) bl)`, + REPEAT GEN_TAC THEN REPEAT_N 4 STRIP_TAC THEN + MP_TAC (SPECL [`0:num`; `bl:byte list`; `ptr:int64`; + `len:int64`; `s:armstate`] BYTE_LIST_AT_3BLOCKS) THEN + REWRITE_TAC[byte_list_at] THEN + ANTS_TAC THENL[ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL[ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL[ ASM_ARITH_TAC; ALL_TAC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_SIMP_TAC[WORD_ADD_0] +);; + +let READ_LT_5BLOCK = prove( + `!(ptr:int64) (len:int64) (bl:byte list) (s:armstate). + LENGTH bl = val len ==> + ~(val len < 0x40) ==> + val len < 0x50 ==> + (forall i. i < val len + ==> read (memory :> bytes8 (word_add ptr (word i))) s = EL i bl) + ==> read (memory :> bytes128 ptr) s = bytes_to_int128 (SUB_LIST (0, 16) bl) /\ + read (memory :> bytes128 (word_add ptr (word 16))) s = + bytes_to_int128 (SUB_LIST (16, 16) bl) /\ + read (memory :> bytes128 (word_add ptr (word 32))) s = + bytes_to_int128 (SUB_LIST (32, 16) bl) /\ + read (memory :> bytes128 (word_add ptr (word 48))) s = + bytes_to_int128 (SUB_LIST (48, 16) bl)`, + REPEAT GEN_TAC THEN REPEAT_N 4 STRIP_TAC THEN + MP_TAC (SPECL [`0:num`; `bl:byte list`; `ptr:int64`; + `len:int64`; `s:armstate`] BYTE_LIST_AT_4BLOCKS) THEN + REWRITE_TAC[byte_list_at] THEN + ANTS_TAC THENL[ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL[ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL[ ASM_ARITH_TAC; ALL_TAC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_SIMP_TAC[WORD_ADD_0] +);; + +let READ_LT_6BLOCK = prove( + `!(ptr:int64) (len:int64) (bl:byte list) (s:armstate). + LENGTH bl = val len ==> + ~(val len < 0x50) ==> + val len < 0x60 ==> + (forall i. i < val len + ==> read (memory :> bytes8 (word_add ptr (word i))) s = EL i bl) + ==> read (memory :> bytes128 ptr) s = bytes_to_int128 (SUB_LIST (0, 16) bl) /\ + read (memory :> bytes128 (word_add ptr (word 16))) s = + bytes_to_int128 (SUB_LIST (16, 16) bl) /\ + read (memory :> bytes128 (word_add ptr (word 32))) s = + bytes_to_int128 (SUB_LIST (32, 16) bl) /\ + read (memory :> bytes128 (word_add ptr (word 48))) s = + bytes_to_int128 (SUB_LIST (48, 16) bl) /\ + read (memory :> bytes128 (word_add ptr (word 64))) s = + bytes_to_int128 (SUB_LIST (64, 16) bl)`, + REPEAT GEN_TAC THEN REPEAT_N 4 STRIP_TAC THEN + MP_TAC (SPECL [`0:num`; `bl:byte list`; `ptr:int64`; + `len:int64`; `s:armstate`] BYTE_LIST_AT_5BLOCKS) THEN + REWRITE_TAC[byte_list_at] THEN + ANTS_TAC THENL[ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL[ ASM_SIMP_TAC[]; ALL_TAC] THEN + ANTS_TAC THENL[ ASM_ARITH_TAC; ALL_TAC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_SIMP_TAC[WORD_ADD_0] +);; + + +(**********************************************************************) +(** Common Spec function lemmas **) + +let INT128_TO_BYTES_OF_BYTES_TO_INT128 = prove( + `!x. LENGTH x = 16 ==> int128_to_bytes (bytes_to_int128 x) = x`, + REPEAT STRIP_TAC THEN + MP_TAC ((GEN_REWRITE_CONV I [LENGTH_EQ_LIST_OF_SEQ] THENC + RAND_CONV LIST_OF_SEQ_CONV) `LENGTH (x:byte list) = 16`) THEN + ASM_SIMP_TAC[] THEN + DISCH_THEN (fun th -> ONCE_REWRITE_TAC[th]) THEN + REWRITE_TAC[bytes_to_int128] THEN + REWRITE_TAC EL_16_8_CLAUSES THEN + REWRITE_TAC[int128_to_bytes] THEN + REWRITE_TAC[CONS_11] THEN + REPEAT (CONJ_TAC THEN BITBLAST_TAC) +);; + +let LENGTH_OF_INT128_TO_BYTES = prove( + `!x. LENGTH(int128_to_bytes x) = 16`, + STRIP_TAC THEN + REWRITE_TAC[int128_to_bytes] THEN + REWRITE_TAC[LENGTH] THEN + CONV_TAC NUM_REDUCE_CONV +);; + +let SUB_LIST_OF_INT128_TO_BYTES = prove( + `!x. SUB_LIST (0, 16) (int128_to_bytes x) = int128_to_bytes x`, + GEN_TAC THEN + MP_TAC (SPEC `x:int128` LENGTH_OF_INT128_TO_BYTES) THEN + DISCH_TAC THEN + IMP_REWRITE_TAC[SUB_LIST_LENGTH_IMPLIES] +);; + +let ELEM_TAC i = + CONV_TAC (RAND_CONV (REWRITE_CONV [num_CONV i])) THEN + REWRITE_TAC[bytelist_of_num] THEN + REWRITE_TAC[CONS_11] THEN + CONJ_TAC THENL [ + REWRITE_TAC[word_subword] THEN + AP_TERM_TAC THEN + (ARITH_TAC ORELSE + ( ASM_REWRITE_TAC[CONJUNCT1 EXP; DIV_1; DIV_DIV] THEN + CONV_TAC NUM_REDUCE_CONV)); ALL_TAC];; + +let INT128_TO_BYTES_EQ_BYTELIST_OF_NUM = prove( + `!x. int128_to_bytes x = bytelist_of_num 16 (val x)`, + GEN_TAC THEN + REWRITE_TAC[int128_to_bytes] THEN + + MAP_EVERY (fun i -> ELEM_TAC (mk_numeral (num i))) (List.rev (2 -- 16)) THEN + CONV_TAC (RAND_CONV (REWRITE_CONV [num_CONV `1`])) THEN + REWRITE_TAC[bytelist_of_num] THEN + REWRITE_TAC[CONS_11] THEN + REWRITE_TAC[word_subword] THEN + AP_TERM_TAC THEN + ASM_REWRITE_TAC[DIV_DIV] THEN + CONV_TAC NUM_REDUCE_CONV +);; + +let NUM_OF_BYTELIST_OF_INT128_TO_BYTES = prove( + `!x. num_of_bytelist (int128_to_bytes x) = val x`, + GEN_TAC THEN + REWRITE_TAC[INT128_TO_BYTES_EQ_BYTELIST_OF_NUM] THEN + REWRITE_TAC[NUM_OF_BYTELIST_OF_NUM] THEN + SUBGOAL_THEN `val (x:int128) < 2 EXP 128` ASSUME_TAC THENL + [ MP_TAC (ISPEC `x:int128` VAL_BOUND) THEN + REWRITE_TAC[DIMINDEX_128] THEN + ARITH_TAC; ALL_TAC + ] THEN + IMP_REWRITE_TAC[MOD_LT] THEN + ASM_ARITH_TAC +);; + +let BYTES_TO_INT128_OF_INT128_TO_BYTES = prove( + `!x. bytes_to_int128 (int128_to_bytes x) = x`, + GEN_TAC THEN + REWRITE_TAC[int128_to_bytes; bytes_to_int128] THEN + REWRITE_TAC EL_16_8_CLAUSES THEN + BITBLAST_TAC +);; + +let CALCULATE_TWEAK_EXPAND = prove( + `!x iv key. + GF_128_mult_by_primitive (calculate_tweak x iv key) = + calculate_tweak (x + 0x1) iv key`, + REPEAT GEN_TAC THEN + REWRITE_TAC[ARITH_RULE `x + 1 = SUC x`] THEN + CONV_TAC (RAND_CONV (REWRITE_CONV[CONJUNCT2 calculate_tweak])) THEN + REFL_TAC +);; + +let VALUE_OF_ACC_LEN = prove( + `!(i:int64) (len:int64). + val i * 0x50 <= val len ==> + val len DIV 0x50 = val i ==> + 0x10 divides val len ==> + acc_len i len = val len`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[acc_len] THEN + REPEAT COND_CASES_TAC THENL + [ + ASM_ARITH_TAC; + ASM_ARITH_TAC; + ASM_ARITH_TAC; + ASM_ARITH_TAC; + REWRITE_TAC[ARITH_RULE `!a. 0x50 * a = a * 0x50`] THEN + SUBGOAL_THEN `val (i:int64) * 0x50 = val (len:int64)` ASSUME_TAC THENL + [ MATCH_MP_TAC (SPECL [`val (len:int64)`; `val (i:int64)`] DIVISION_BY_80_LEMMA) THEN + REPEAT CONJ_TAC THENL + [ + ASM_SIMP_TAC[]; + ASM_SIMP_TAC[]; + UNDISCH_TAC `~(val (i:int64) * 0x50 + 0x10 = val (len:int64))` THEN + UNDISCH_TAC `val (i:int64) * 0x50 <= val (len:int64)` THEN + ARITH_TAC; + UNDISCH_TAC `~(val (i:int64) * 0x50 + 0x20 = val (len:int64))` THEN + UNDISCH_TAC `val (i:int64) * 0x50 <= val (len:int64)` THEN + ARITH_TAC; + UNDISCH_TAC `~(val (i:int64) * 0x50 + 0x30 = val (len:int64))` THEN + UNDISCH_TAC `val (i:int64) * 0x50 <= val (len:int64)` THEN + ARITH_TAC; + UNDISCH_TAC `~(val (i:int64) * 0x50 + 0x40 = val (len:int64))` THEN + UNDISCH_TAC `val (i:int64) * 0x50 <= val (len:int64)` THEN + ARITH_TAC + ]; ALL_TAC] THEN + ASM_ARITH_TAC + ] +);; + +let BOUND_OF_ACC_LEN = prove( + `!(i:int64) (len:int64) x. + val i * 0x50 <= val len ==> + val len DIV 0x50 = val i ==> + 0x10 divides val len ==> + val len < x ==> acc_len i len < x`, + REPEAT STRIP_TAC THEN + SUBGOAL_THEN `acc_len i len = val (len:int64)` ASSUME_TAC THENL + [ MP_TAC (SPECL [`i:int64`; `len:int64`] VALUE_OF_ACC_LEN) THEN + ASM_SIMP_TAC[]; ALL_TAC] THEN + ASM_ARITH_TAC +);; + + +(* In the cipher-stealing loop invariant, all bytes remain the same between iterations + except the current byte i, which is from the corresponding location i in the tail of pt *) +let CIPHER_STEALING_BYTE_EQUAL = prove( + `!(i:num) (curr_len:num) (tail_len:int64) (PP:int128) (ct:byte list). + i < val tail_len /\ val tail_len < 16 ==> + curr_len + 16 + val tail_len = LENGTH ct ==> + let InvPP = cipher_stealing_inv (i + 1) curr_len (val tail_len) PP ct + and InvPP' = cipher_stealing_inv i curr_len (val tail_len) PP ct in + (!j. 0 <= j /\ j < 16 /\ ~(j = i) ==> EL j (int128_to_bytes InvPP) = EL j (int128_to_bytes InvPP')) /\ + EL i (int128_to_bytes InvPP') = word_zx (EL (curr_len + 16 + i) ct)`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[LET_DEF; LET_END_DEF] THEN + CONJ_TAC THENL + [ + REPEAT STRIP_TAC THEN + REWRITE_TAC[cipher_stealing_inv] THEN + IMP_REWRITE_TAC[INT128_TO_BYTES_OF_BYTES_TO_INT128] THEN + REPEAT CONJ_TAC THENL + [ + (* Three cases: 0 <= j < i, i < j < val tail_len, val tail_len <= j < 16 *) + ASM_CASES_TAC `j < i` THENL + [ + SUBGOAL_THEN `j < LENGTH (SUB_LIST (0x0,i + 0x1) (int128_to_bytes PP))` ASSUME_TAC THENL + [ REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `j < LENGTH (SUB_LIST (0x0,i) (int128_to_bytes PP))` ASSUME_TAC THENL + [ REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC ; ALL_TAC] THEN + REWRITE_TAC[EL_APPEND] THEN + ASM_SIMP_TAC[] THEN + MP_TAC (ISPECL [`j:num`; `i:num`; `(int128_to_bytes PP):byte list`] EL_SUB_LIST) THEN + ANTS_TAC THENL + [ REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC ] THEN + MP_TAC (ISPECL [`j:num`; `(i + 1):num`; `(int128_to_bytes PP):byte list`] EL_SUB_LIST) THEN + ANTS_TAC THENL + [ REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC ] THEN + SIMP_TAC[]; ALL_TAC + ] THEN + ASM_CASES_TAC `j < val (tail_len:int64)` THENL + [ + SUBGOAL_THEN `j > i` ASSUME_TAC THENL[ASM_ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[EL_APPEND] THEN + SUBGOAL_THEN `LENGTH (SUB_LIST (0x0,i + 0x1) (int128_to_bytes PP)) = i + 1` SUBST1_TAC THENL + [ REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `LENGTH (SUB_LIST (0x0,i) (int128_to_bytes PP)) = i` SUBST1_TAC THENL + [ REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `LENGTH (SUB_LIST (i + 0x1,val (tail_len:int64) - (i + 0x1)) + (SUB_LIST (curr_len + 0x10,val tail_len) (ct:byte list))) + = val tail_len - (i + 1)` SUBST1_TAC THENL + [ REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `LENGTH (SUB_LIST (i,val (tail_len:int64) - i) + (SUB_LIST (curr_len + 0x10,val tail_len) (ct:byte list))) + = val tail_len - i` SUBST1_TAC THENL + [ REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(j < i)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(j < i + 1)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `j - i < val (tail_len:int64) - i` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `j - (i + 1) < val (tail_len:int64) - (i + 1)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + MP_TAC (ISPECL [`(j - i):num`; `i:num`; + `(SUB_LIST (curr_len + 16,val (tail_len:int64)) (ct:byte list)):byte list`; + `(val (tail_len:int64) - i):num`] EL_SUB_LIST_SHIFT) THEN + ASM_SIMP_TAC[] THEN + ANTS_TAC THENL [ REWRITE_TAC[LENGTH_SUB_LIST] THEN ASM_ARITH_TAC; ALL_TAC] THEN + IMP_REWRITE_TAC[ARITH_RULE `!i j. j > i ==> j - i - 1 = j - (i + 1)`] THEN + ASM_ARITH_TAC; ALL_TAC + ] THEN + (* j >= val tail_len *) + REWRITE_TAC[EL_APPEND] THEN + SUBGOAL_THEN `LENGTH (SUB_LIST (0x0,i + 0x1) (int128_to_bytes PP)) = i + 1` SUBST1_TAC THENL + [ REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `LENGTH (SUB_LIST (0x0,i) (int128_to_bytes PP)) = i` SUBST1_TAC THENL + [ REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `LENGTH (SUB_LIST (i + 0x1,val (tail_len:int64) - (i + 0x1)) + (SUB_LIST (curr_len + 0x10,val tail_len) (ct:byte list))) + = val tail_len - (i + 1)` SUBST1_TAC THENL + [ REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `LENGTH (SUB_LIST (i,val (tail_len:int64) - i) + (SUB_LIST (curr_len + 0x10,val tail_len) (ct:byte list))) + = val tail_len - i` SUBST1_TAC THENL + [ REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(j < i)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(j < i + 1)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(j - i < val (tail_len:int64) - i)` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `~(j - (i + 1) < val (tail_len:int64) - (i + 1))` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + AP_THM_TAC THEN AP_TERM_TAC THEN + ASM_ARITH_TAC; + + REWRITE_TAC[LENGTH_APPEND] THEN + REWRITE_TAC[LENGTH_SUB_LIST] THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[ARITH_RULE `i < 16 ==> MIN i 16 = i`] THEN + SUBGOAL_THEN `LENGTH (ct:byte list) - (curr_len + 16) = val (tail_len:int64)` SUBST1_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC ] THEN + REWRITE_TAC[ARITH_RULE `!x. MIN x x = x`] THEN + ASM_ARITH_TAC; + + REWRITE_TAC[LENGTH_APPEND] THEN + REWRITE_TAC[LENGTH_SUB_LIST] THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[ARITH_RULE `i < 16 ==> MIN (i + 1) 16 = i + 1`] THEN + SUBGOAL_THEN `LENGTH (ct:byte list) - (curr_len + 16) = val (tail_len:int64)` SUBST1_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC ] THEN + REWRITE_TAC[ARITH_RULE `!x. MIN x x = x`] THEN + ASM_ARITH_TAC + ] ; ALL_TAC + ] THEN + + REWRITE_TAC[cipher_stealing_inv] THEN + IMP_REWRITE_TAC[INT128_TO_BYTES_OF_BYTES_TO_INT128] THEN + CONJ_TAC THENL [ + REWRITE_TAC[EL_APPEND] THEN + SUBGOAL_THEN `LENGTH (SUB_LIST (0x0,i) (int128_to_bytes PP)) = i` SUBST1_TAC THENL + [ REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SUBGOAL_THEN `LENGTH (SUB_LIST (i,val (tail_len:int64) - i) + (SUB_LIST (curr_len + 0x10,val tail_len) (ct:byte list))) + = val tail_len - i` SUBST1_TAC THENL + [ REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[ARITH_RULE `~(i < i)`; SUB_REFL] THEN + SUBGOAL_THEN `0 < val (tail_len:int64) - i` ASSUME_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + MP_TAC (ISPECL [`curr_len + 0x10:num`; `i:num`; `ct:byte list`; + `val (tail_len:int64) - i:num`; `val (tail_len:int64)`] SUB_LIST_MIN_GENERAL) THEN + REWRITE_TAC[ARITH_RULE `!a. MIN a a = a`; GSYM ADD_ASSOC] THEN + DISCH_THEN (fun th -> (REWRITE_TAC [th])) THEN + REWRITE_TAC[WORD_ZX_TRIVIAL; EL] THEN + MATCH_MP_TAC HD_SUB_LIST_CONS_GENERAL THEN + ASM_ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[LENGTH_APPEND] THEN + REWRITE_TAC[LENGTH_SUB_LIST] THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV THEN + ASM_ARITH_TAC +);; + +let CIPHER_STEALING_INV_SELECT = prove( + `!(i:num) (curr_len:num) (tail_len:int64) (PP:int128) (ct:byte list). + i < val tail_len ==> val tail_len < 16 ==> + curr_len + 16 + (val tail_len) = LENGTH ct ==> + EL i (int128_to_bytes (cipher_stealing_inv (i + 1) curr_len (val tail_len) PP ct)) = + EL i (int128_to_bytes PP)`, + REPEAT STRIP_TAC THEN + REWRITE_TAC[cipher_stealing_inv] THEN + IMP_REWRITE_TAC[INT128_TO_BYTES_OF_BYTES_TO_INT128] THEN + CONJ_TAC THENL [ + SUBGOAL_THEN `LENGTH (SUB_LIST (0x0,i + 1) (int128_to_bytes PP)) <= i + 1` ASSUME_TAC THENL + [ REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + ARITH_TAC; ALL_TAC] THEN + REWRITE_TAC[EL_APPEND] THEN + SUBGOAL_THEN `i < LENGTH (SUB_LIST (0x0,i + 0x1) (int128_to_bytes PP))` ASSUME_TAC THENL + [ REWRITE_TAC[LENGTH_SUB_LIST; LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC] THEN + ASM_SIMP_TAC[] THEN + MATCH_MP_TAC EL_SUB_LIST THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + ASM_ARITH_TAC; ALL_TAC + ] THEN + + REWRITE_TAC[LENGTH_APPEND] THEN + REWRITE_TAC[LENGTH_SUB_LIST] THEN + REWRITE_TAC[LENGTH_OF_INT128_TO_BYTES] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[ARITH_RULE `i < 16 ==> MIN (i + 1) 16 = i + 1`] THEN + SUBGOAL_THEN `LENGTH (ct:byte list) - (curr_len + 16) = val (tail_len:int64)` SUBST1_TAC THENL + [ ASM_ARITH_TAC; ALL_TAC ] THEN + REWRITE_TAC[ARITH_RULE `!x. MIN x x = x`] THEN + ASM_ARITH_TAC +);; + +let CIPHER_STEALING_INV_SIMP_TAC i = + ( FIRST_ASSUM (fun th -> MATCH_MP_TAC(SPEC i th)) THEN CONV_TAC NUM_REDUCE_CONV) ORELSE + ( ASM_REWRITE_TAC[] THEN + REWRITE_TAC[WORD_RULE `!a b. word_add ((word a):int64) (word b) = word (a + b)`] THEN + REWRITE_TAC[GSYM ADD_ASSOC] THEN + CONV_TAC NUM_REDUCE_CONV THEN + IMP_REWRITE_TAC[WORD_ZX_ZX; WORD_ZX_TRIVIAL] THEN + REWRITE_TAC[DIMINDEX_8; DIMINDEX_32; DIMINDEX_64] THEN + IMP_REWRITE_TAC[VAL_WORD; DIMINDEX_64; MOD_LT] THEN + ASM_ARITH_TAC);; + +let BREAK_DATA_INTO_PARTS_ENCRYPT = prove( + `!curr_len (tail_len:int64) (pt_ptr:int64) (s:armstate). + ((curr_len + 0x10 + val tail_len <= LENGTH bl) /\ + (forall i. i < curr_len + ==> read (memory :> bytes8 (word_add pt_ptr (word i))) s = EL i bl) /\ + (forall i. i < 16 + ==> read (memory :> bytes8 (word_add (word_add pt_ptr (word curr_len)) (word i))) s = + EL i (SUB_LIST (curr_len, 16) bl)) /\ + (forall i. i < val tail_len + ==> read (memory :> bytes8 + (word_add (word_add pt_ptr (word (curr_len + 0x10))) (word i))) s = + EL i (SUB_LIST (curr_len + 16, val tail_len) bl))) ==> + forall i. + i < curr_len + 0x10 + val tail_len + ==> read (memory :> bytes8 (word_add pt_ptr (word i))) s = EL i bl`, + REPEAT GEN_TAC THEN + DISCH_THEN (CONJUNCTS_THEN2 (LABEL_TAC "H") + (CONJUNCTS_THEN2 (LABEL_TAC "H1") + (CONJUNCTS_THEN2 (LABEL_TAC "H2") (LABEL_TAC "H3")))) THEN + REPEAT STRIP_TAC THEN + + ASM_CASES_TAC `i < curr_len` THENL + [ + FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[]; + ALL_TAC + ] THEN + + ASM_CASES_TAC `i < curr_len + 16` THENL + [ + USE_THEN "H2" (fun th -> MP_TAC (SPEC `i - curr_len` th)) THEN + REMOVE_THEN "H2" (K ALL_TAC) THEN + SUBGOAL_THEN `(word_add (word_add (pt_ptr:int64) (word curr_len)) (word (i - curr_len))) + = (word_add pt_ptr (word i))` ASSUME_TAC THENL + [ REWRITE_TAC[WORD_RULE `word_add (word_add a (word b)) (word c) = word_add a (word (b + c))`] THEN + AP_TERM_TAC THEN AP_TERM_TAC THEN + ASM_ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + ANTS_TAC THENL[ASM_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[EL_SUB_LIST_GENERAL] THEN + ASM_ARITH_TAC; + ALL_TAC + ] THEN + + ASM_CASES_TAC `i < curr_len + 16 + val (tail_len:int64)` THENL + [ + USE_THEN "H3" (fun th -> MP_TAC (SPEC `i - curr_len - 16` th)) THEN + REMOVE_THEN "H3" (K ALL_TAC) THEN + SUBGOAL_THEN `(word_add (word_add (pt_ptr:int64) (word (curr_len + 0x10))) + (word (i - curr_len - 0x10))) = (word_add pt_ptr (word i))` ASSUME_TAC THENL + [ REWRITE_TAC[WORD_RULE `word_add (word_add a (word b)) (word c) = word_add a (word (b + c))`] THEN + AP_TERM_TAC THEN AP_TERM_TAC THEN + ASM_ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + ANTS_TAC THENL[ASM_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + REWRITE_TAC[ARITH_RULE `i - curr_len - 16 = i - (curr_len + 16)`] THEN + IMP_REWRITE_TAC[EL_SUB_LIST_GENERAL] THEN + ASM_ARITH_TAC; + ALL_TAC + ] THEN + + ASM_ARITH_TAC +);; + +let BREAK_DATA_INTO_PARTS_DECRYPT = prove( + `!curr_len (tail_len:int64) (pt_ptr:int64) (s:armstate). + ((curr_len + 0x10 + val tail_len <= LENGTH bl) /\ + (forall i. i < curr_len + ==> read (memory :> bytes8 (word_add pt_ptr (word i))) s = EL i bl) /\ + (forall i. i < 16 + ==> read (memory :> bytes8 (word_add (word_add pt_ptr (word curr_len)) (word i))) s = + EL i (SUB_LIST (curr_len, 16 + val tail_len) bl)) /\ + (forall i. i < val tail_len + ==> read (memory :> bytes8 + (word_add (word_add pt_ptr (word (curr_len + 0x10))) (word i))) s = + EL i (SUB_LIST (curr_len + 16, val tail_len) bl))) ==> + forall i. + i < curr_len + 0x10 + val tail_len + ==> read (memory :> bytes8 (word_add pt_ptr (word i))) s = EL i bl`, + REPEAT GEN_TAC THEN + DISCH_THEN (CONJUNCTS_THEN2 (LABEL_TAC "H") + (CONJUNCTS_THEN2 (LABEL_TAC "H1") + (CONJUNCTS_THEN2 (LABEL_TAC "H2") (LABEL_TAC "H3")))) THEN + REPEAT STRIP_TAC THEN + + ASM_CASES_TAC `i < curr_len` THENL + [ + FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[]; + ALL_TAC + ] THEN + + ASM_CASES_TAC `i < curr_len + 16` THENL + [ + USE_THEN "H2" (fun th -> MP_TAC (SPEC `i - curr_len` th)) THEN + REMOVE_THEN "H2" (K ALL_TAC) THEN + SUBGOAL_THEN `(word_add (word_add (pt_ptr:int64) (word curr_len)) (word (i - curr_len))) + = (word_add pt_ptr (word i))` ASSUME_TAC THENL + [ REWRITE_TAC[WORD_RULE `word_add (word_add a (word b)) (word c) = word_add a (word (b + c))`] THEN + AP_TERM_TAC THEN AP_TERM_TAC THEN + ASM_ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + ANTS_TAC THENL[ASM_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + IMP_REWRITE_TAC[EL_SUB_LIST_GENERAL] THEN + ASM_ARITH_TAC; + ALL_TAC + ] THEN + + ASM_CASES_TAC `i < curr_len + 16 + val (tail_len:int64)` THENL + [ + USE_THEN "H3" (fun th -> MP_TAC (SPEC `i - curr_len - 16` th)) THEN + REMOVE_THEN "H3" (K ALL_TAC) THEN + SUBGOAL_THEN `(word_add (word_add (pt_ptr:int64) (word (curr_len + 0x10))) + (word (i - curr_len - 0x10))) = (word_add pt_ptr (word i))` ASSUME_TAC THENL + [ REWRITE_TAC[WORD_RULE `word_add (word_add a (word b)) (word c) = word_add a (word (b + c))`] THEN + AP_TERM_TAC THEN AP_TERM_TAC THEN + ASM_ARITH_TAC; ALL_TAC] THEN + ASM_REWRITE_TAC[] THEN + ANTS_TAC THENL[ASM_ARITH_TAC; ALL_TAC] THEN + SIMP_TAC[] THEN DISCH_TAC THEN + REWRITE_TAC[ARITH_RULE `i - curr_len - 16 = i - (curr_len + 16)`] THEN + IMP_REWRITE_TAC[EL_SUB_LIST_GENERAL] THEN + ASM_ARITH_TAC; + ALL_TAC + ] THEN + + ASM_ARITH_TAC +);; diff --git a/arm/proofs/utils/aes_xts_common_spec.ml b/arm/proofs/utils/aes_xts_common_spec.ml new file mode 100644 index 000000000..59cabd5ed --- /dev/null +++ b/arm/proofs/utils/aes_xts_common_spec.ml @@ -0,0 +1,207 @@ +(* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0 + *) + (* Common definitions between AES-XTS encrypt and decrypt specs. *) + +needs "common/aes.ml";; +needs "arm/proofs/utils/aes_encrypt_spec.ml";; +(* +let pp_print_num fmt tm = + let n = dest_numeral tm in + pp_print_string fmt (string_of_num_hex n) in +install_user_printer("pp_print_num",pp_print_num);; +*) + +(* Helper functions derived from Amanda's code: + https://github.com/amanda-zx/s2n-bignum/blob/sha512/arm/sha512/sha512_specs.ml#L360 *) + + let bytes_to_int128 = define + `bytes_to_int128 (bs : byte list) : int128 = + word_join + (word_join + (word_join (word_join (EL 15 bs) (EL 14 bs) : int16) (word_join (EL 13 bs) (EL 12 bs) : int16) : int32) + (word_join (word_join (EL 11 bs) (EL 10 bs) : int16) (word_join (EL 9 bs) (EL 8 bs) : int16) : int32) : int64) + (word_join + (word_join (word_join (EL 7 bs) (EL 6 bs) : int16) (word_join (EL 5 bs) (EL 4 bs) : int16) : int32) + (word_join (word_join (EL 3 bs) (EL 2 bs) : int16) (word_join (EL 1 bs) (EL 0 bs) : int16) : int32) : int64)`;; + +let int128_to_bytes = define + `int128_to_bytes (w : int128) : byte list = + [word_subword w (0, 8); word_subword w (8, 8); word_subword w (16, 8); word_subword w (24, 8); + word_subword w (32, 8); word_subword w (40, 8); word_subword w (48, 8); word_subword w (56, 8); + word_subword w (64, 8); word_subword w (72, 8); word_subword w (80, 8); word_subword w (88, 8); + word_subword w (96, 8); word_subword w (104, 8); word_subword w (112, 8); word_subword w (120, 8)]`;; + +(* XTS tweak initialization - encrypt the IV with key2 *) +let xts_init_tweak = new_definition + `xts_init_tweak (iv:int128) (key2:int128 list) = + aes256_encrypt iv key2`;; + +(* Note: the implementation sequences the calculation of the tweak for each block, + however, the specification will calculate the tweak from the very beginning for each block. + We write the specification in the sequenced version for proof simplicity. *) + +(* Multiplication by the primitive element \alpha in GF(2^128) *) +(* Same as the pseudo code of multiplying by \alpha in Annex C of the spec. *) +let GF_128_mult_by_primitive = new_definition + `GF_128_mult_by_primitive (tweak:(128)word) = + let shifted = word_shl tweak 1 in + let mask = word_ishr tweak 127 in + word_xor (word_and mask (word 0x87)) shifted`;; + +let calculate_tweak = new_recursive_definition num_RECURSION + `calculate_tweak 0 (iv:(128)word) (key2:int128 list) = xts_init_tweak iv key2 /\ + calculate_tweak (SUC n) (iv:(128)word) (key2:int128 list) = + GF_128_mult_by_primitive (calculate_tweak n iv key2)`;; + +(***********************************************) +(* Conversions and test vectors *) + +let EL_16_8_CLAUSES = + let pat = `EL n [x0;x1;x2;x3;x4;x5;x6;x7;x8;x9;x10;x11;x12;x13;x14;x15]:byte` in + map (fun n -> EL_CONV(subst [mk_small_numeral n,`n:num`] pat)) (0--15);; + +let BYTES_TO_INT128_CONV = + REWR_CONV bytes_to_int128 THENC + REWRITE_CONV EL_16_8_CLAUSES THENC + DEPTH_CONV WORD_RED_CONV;; +(* +let ptext = new_definition + `ptext = + int128_to_bytes (word 0x0F0E0D0C0B0A09080706050403020100 : int128)`;; + +time prove(`bytes_to_int128 ptext + = (word 0x0f0e0d0c0b0a09080706050403020100 :int128)`, + CONV_TAC(REWRITE_CONV [ptext;int128_to_bytes] THENC + LAND_CONV BYTES_TO_INT128_CONV) THEN + REFL_TAC + );; +*) + +let INT128_TO_BYTES_CONV = + REWRITE_CONV [int128_to_bytes] THENC + DEPTH_CONV WORD_RED_CONV;; +(* INT128_TO_BYTES_CONV `int128_to_bytes (word 0x0102030405060708090a0b0c0d0e0f)`;; *) + +let GF_128_MULT_BY_PRIMITIVE_CONV = + REWRITE_CONV [GF_128_mult_by_primitive] THENC + REPEATC let_CONV THENC + DEPTH_CONV WORD_RED_CONV;; +(* GF_128_MULT_BY_PRIMITIVE_CONV + `GF_128_mult_by_primitive (word 0x8b2b4a71228e98aed6aa0ca97775261a)`;; *) + +time prove(`GF_128_mult_by_primitive (word 0x8b2b4a71228e98aed6aa0ca97775261a) + = (word 0x165694e2451d315dad541952eeea4cb3 : int128)`, + CONV_TAC(LAND_CONV GF_128_MULT_BY_PRIMITIVE_CONV) THEN REFL_TAC + );; + +let XTS_INIT_TWEAK_CONV = + REWR_CONV xts_init_tweak THENC AESENC_HELPER_CONV;; + +let iv1 = new_definition + `iv1 = (word 0x000000000000000000000000000000FF) : int128`;; + +let tweak_key_schedule = new_definition `tweak_key_schedule:int128 list = + [ word 0x95278333646284239397585326594131 + ; word 0x92459474098205513799931697418802 + ; word 0xD6C4705143E3F36227817741B4162F12 + ; word 0xCD03DBE05F464F9456C44AC5615DD9D3 + ; word 0xE70DA0DB31C9D08A722A23E855AB54A9 + ; word 0x310BE7DBFC083C3BA34E73AFF58A396A + ; word 0x48822C80AF8F8C5B9E465CD1EC6C7F39 + ; word 0xC9D4E0E8F8DF073304D73B08A79948A7 + ; word 0x0EFACBDA4678E75AE9F76B0177B137D0 + ; word 0x39688B23F0BC6BCB08636CF80CB457F0 + ; word 0xF0D6357CFE2CFEA6B85419FC51A372FD + ; word 0x41F54DF0789DC6D38821AD188042C1E0 + ; word 0x6B8E46189B58736465748DC2DD20943E + ; word 0x4E12BD760FE7F086777A3655FF5B9B4D + ; word 0x70ADE5BA1B23A3A2807BD0C6E50F5D04 + ]`;; + +(* +let tmp_xts_tweak = (REWRITE_CONV [iv1; tweak_key_schedule] THENC XTS_INIT_TWEAK_CONV) + `xts_init_tweak iv1 + tweak_key_schedule`;; +(* Or the following: 36 sec on M3 *) +time prove(`xts_init_tweak iv1 + tweak_key_schedule + = word 0x8b2b4a71228e98aed6aa0ca97775261a`, + CONV_TAC(REWRITE_CONV [iv1; tweak_key_schedule] THENC + LAND_CONV XTS_INIT_TWEAK_CONV) + THEN REFL_TAC + );; +*) + +let rec CALCULATE_TWEAK_CONV tm = + let BASE_CONV = + ONCE_REWRITE_CONV [calculate_tweak] THENC + XTS_INIT_TWEAK_CONV in + let INDUCT_CONV = + RATOR_CONV(LAND_CONV num_CONV) THENC (* ((calculate_tweak 1) iv) key2 *) + (* PRINT_TERM_CONV THENC*) + ONCE_REWRITE_CONV [CONJUNCT2 calculate_tweak] THENC + RAND_CONV CALCULATE_TWEAK_CONV THENC + GF_128_MULT_BY_PRIMITIVE_CONV in + match tm with + | Comb + (Comb + (Comb + (Const ("calculate_tweak",_), n), + _), + _) -> + if dest_numeral n =/ num 0 + then BASE_CONV tm + else INDUCT_CONV tm + | _ -> failwith "CALCULATE_TWEAK_CONV: inapplicable";; +(* +(* result: word 0x8b2b4a71228e98aed6aa0ca97775261a, same as xts_init_tweak test above *) +(REWRITE_CONV [iv1;tweak_key_schedule] THENC CALCULATE_TWEAK_CONV) `calculate_tweak 0 iv1 tweak_key_schedule`;; + +(* result: word 0x165694e2451d315dad541952eeea4cb3, same as GF_128_mult_by_primitive test above *) +(REWRITE_CONV [iv1;tweak_key_schedule] THENC CALCULATE_TWEAK_CONV) `calculate_tweak 1 iv1 tweak_key_schedule`;; +*) + +(* +The following conversion (in its second form) is included directly where it's used in +aes_xts_encrypt.ml and +aes_xts_decrypt.ml + +let TWEAK_UPDATE_CONV = + let ADD_SUC_1 = ARITH_RULE `!n. n + 1 = SUC(n)` in + let ADD_SUC_2 = ARITH_RULE `!n. n + 2 = SUC(n + 1)` in + let ADD_SUC_3 = ARITH_RULE `!n. n + 3 = SUC(n + 2)` in + let ADD_SUC_4 = ARITH_RULE `!n. n + 4 = SUC(n + 3)` in + let ADD_SUC_5 = ARITH_RULE `!n. n + 5 = SUC(n + 4)` in + let ADD_SUC_6 = ARITH_RULE `!n. n + 6 = SUC(n + 5)` in + let ADD_SUC_7 = ARITH_RULE `!n. n + 7 = SUC(n + 6)` in + let ADD_SUC_8 = ARITH_RULE `!n. n + 8 = SUC(n + 7)` in + let ADD_SUC_9 = ARITH_RULE `!n. n + 9 = SUC(n + 8)` in + NUM_REDUCE_CONV THENC + RATOR_CONV (LAND_CONV (num_CONV ORELSEC + FIRST_CONV + [ CHANGED_CONV (ONCE_REWRITE_CONV [ADD_SUC_1]); + CHANGED_CONV (ONCE_REWRITE_CONV [ADD_SUC_2]); + CHANGED_CONV (ONCE_REWRITE_CONV [ADD_SUC_3]); + CHANGED_CONV (ONCE_REWRITE_CONV [ADD_SUC_4]); + CHANGED_CONV (ONCE_REWRITE_CONV [ADD_SUC_5]); + CHANGED_CONV (ONCE_REWRITE_CONV [ADD_SUC_6]); + CHANGED_CONV (ONCE_REWRITE_CONV [ADD_SUC_7]); + CHANGED_CONV (ONCE_REWRITE_CONV [ADD_SUC_8]); + CHANGED_CONV (ONCE_REWRITE_CONV [ADD_SUC_9]);])) THENC + REWRITE_CONV [CONJUNCT2 calculate_tweak] THENC + GF_128_MULT_BY_PRIMITIVE_CONV;; + +let TWEAK_UPDATE_CONV = + let thms = CONJUNCTS + ((REWRITE_RULE[ARITH; ADD_0] o + CONV_RULE EXPAND_CASES_CONV o ARITH_RULE) + `forall i. i < 9 ==> forall n. n + SUC i = SUC (n + i)`) in + NUM_REDUCE_CONV THENC + RATOR_CONV (LAND_CONV (num_CONV ORELSEC + FIRST_CONV + (map (fun th -> CHANGED_CONV (ONCE_REWRITE_CONV [th])) thms))) THENC + REWRITE_CONV [CONJUNCT2 calculate_tweak] THENC + GF_128_MULT_BY_PRIMITIVE_CONV;; +*) \ No newline at end of file diff --git a/arm/proofs/utils/aes_xts_decrypt_spec.ml b/arm/proofs/utils/aes_xts_decrypt_spec.ml new file mode 100644 index 000000000..2defc36e4 --- /dev/null +++ b/arm/proofs/utils/aes_xts_decrypt_spec.ml @@ -0,0 +1,534 @@ +(* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0 + *) + +needs "arm/proofs/utils/aes_xts_common_spec.ml";; +needs "arm/proofs/utils/aes_decrypt_spec.ml";; + +(* +let pp_print_num fmt tm = + let n = dest_numeral tm in + pp_print_string fmt (string_of_num_hex n) in +install_user_printer("pp_print_num",pp_print_num);; +*) + +(*******************************************) +(* Specification *) + +(* +IEEE Standard for Cryptographic Protection of +Data on Block-Oriented Storage Devices +https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=8637988 + +Section 5.4.1 + +a) T := AES-enc(Key2, i) MUL alpha^j +b) CC := C XOR T +c) PP := AES-dec(Key1, CC) +d) P := PP XOR T + +*) + +let xts_init_tweak = new_definition + `xts_init_tweak (iv:int128) (key_schedule:int128 list) = + aes256_encrypt iv key_schedule`;; + +let aes256_xts_decrypt_round = new_definition + `aes256_xts_decrypt_round (C:int128) (tk:int128) (key_schedule:int128 list) = + let CC = word_xor C tk in + let PP = aes256_decrypt CC key_schedule in + word_xor PP tk`;; + +let aes256_xts_decrypt_1block = new_definition + `aes256_xts_decrypt_1block + (C:int128) (iv:int128) (key1:int128 list) (key2:int128 list) = + let tk = xts_init_tweak iv key2 in + aes256_xts_decrypt_round C tk key1`;; + +(*******************************************) +(* AES-XTS decryption *) + +let eth = prove_general_recursive_function_exists + `?aes256_xts_decrypt_rec. + ! (i:num) (m:num) (C:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + aes256_xts_decrypt_rec i m C iv key1 key2: byte list = + if m < i then [] + else + let current_block = bytes_to_int128 (SUB_LIST (i * 16, 16) C) in + let twk = calculate_tweak i iv key2 in + let curr = int128_to_bytes (aes256_xts_decrypt_round current_block twk key1) in + let res = aes256_xts_decrypt_rec (i + 1) m C iv key1 key2 in + APPEND curr res`;; + +let wfth = prove(hd(hyp eth), + EXISTS_TAC `MEASURE (\(i:num,m:num,C:byte list,iv:int128,key1:int128 list,key2:int128 list). (m + 1) - i)` THEN + REWRITE_TAC[WF_MEASURE; MEASURE] THEN ARITH_TAC);; + +let exists_lemma = PROVE_HYP wfth eth;; + +(* Note: results are stored in LSByte to MSByte *) +let aes256_xts_decrypt_rec = new_specification ["aes256_xts_decrypt_rec"] exists_lemma;; + +let cipher_stealing = new_definition + `cipher_stealing (block:byte list) (tail:byte list) (tail_len:num) + (iv:int128) (i:num) (key1:int128 list) (key2:int128 list): (byte list)#(byte list) = + let iv = calculate_tweak i iv key2 in + let iv_last = GF_128_mult_by_primitive iv in + let PP = int128_to_bytes (aes256_xts_decrypt_round (bytes_to_int128 block) iv_last key1) in + let Pm = SUB_LIST (0, tail_len) PP in + let CP = SUB_LIST (tail_len, 16 - tail_len) PP in + let CC = bytes_to_int128 (APPEND tail CP) in + let Pm1 = int128_to_bytes (aes256_xts_decrypt_round CC iv key1) in + (Pm1, Pm)`;; + +(* Depending on the tail, either do one block decryption or do cipher stealing *) +let aes256_xts_decrypt_tail = new_definition + `aes256_xts_decrypt_tail (i:num) (tail_len:num) (C:byte list) (iv:int128) (key1:int128 list) (key2:int128 list) : byte list = + if tail_len = 0 then + let Cm1 = bytes_to_int128 (SUB_LIST (i * 16, 16) C) in + let iv = calculate_tweak i iv key2 in + int128_to_bytes (aes256_xts_decrypt_round Cm1 iv key1) + else + let Cm1 = SUB_LIST (i * 16, 16) C in + let Ctail = SUB_LIST ((i + 1) * 16, tail_len) C in + + let res_cs = cipher_stealing Cm1 Ctail tail_len iv i key1 key2 in + APPEND (FST res_cs) (SND res_cs)`;; + +(* The main decryption function *) +(* Note: the specification does not handle the case of len < 16, which is + handled in the implementation. *) + +(* AES256-XTS assumes there is at least one block in input *) +(* + C: Input ciphertext represented as a byte list + len: Length of C + iv: Initialization vector (tweak) as an int128 + key1: Key schedule for AES-256 decryption + key2: Key schedule for AES-256 encryption for the tweak + + return: Output plaintext as a byte list + + When input len < 16, the function returns []. +*) +(* TODO: Double check if IEEE and NIST spec talks about the error case len < 16 *) +let aes256_xts_decrypt = new_definition + `aes256_xts_decrypt + (C:byte list) (len:num) (iv:int128) (key1:int128 list) (key2:int128 list) : byte list = + if len < 16 then + [] + else + let tail_len = len MOD 16 in + let m = (len - tail_len) DIV 16 in + if m < 2 then + aes256_xts_decrypt_tail 0 tail_len C iv key1 key2 + else + let res = aes256_xts_decrypt_rec 0 (m - 2) C iv key1 key2 in + let Ptail = aes256_xts_decrypt_tail (m - 1) tail_len C iv key1 key2 in + APPEND res Ptail`;; + +(*******************************************) +(* Test vectors printed from AWS-LC *) + +(* +The decrypt key schedule is different from encrypt. +This is because AWS-LC uses EQINVCIPHER() for AES decryption. +See 5.3.5 EQINVCIPHER() from NIST.FIPS.197 Advanced Encryption Standard (AES) + +key1: +c70a951e84370d1836bdd387607e94e5 +7ead95d6f74bf6b3103340cce21b473d +298c296cdf3241d53d0757ddbebda060 +89e66365e778b67ff22807f1cdc91c8f +f6be68b9e235160883baf7bd2340b902 +6e9ed51a1550b18e3fe11b7e185c513e +148b7eb1618fe1b5a0fa4ebf336ae76e +7bce64942ab1aaf027bd4a40982968cd +75049f04c175af0a9390a9d1d91a6526 +517fce640d0ce0b0bf94228de7e3085d +b471300e52e506db4a8accf7a81afe26 +5c732ed4b298c23d58772ad0be94ce31 +e69436d5186fca2ce29032d11463c620 +eeebece9eaefe8ede6e3e4e1e2e7e0e5 +f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + +key2: +b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +a0a1a2a3a4a5a6a7a8a9aaabacadaeaf +0ae0323bba5180880ee4363fb65d8c84 +67e123e2c740814163e527e6cb4c8d4d +908df02c9a6dc217203c429f2ed874a0 +685584790fb4a79bc8f426daab11013c +b241f85f22cc0873b8a1ca64989d88fb +338745cb5bd2c1b2546666299c9240f3 +af72a5d51d335d8a3fff55f9875e9f9d +d9e1a4a0ea66e16bb1b420d9e5d246f0 +ead5ca6245a76fb75894323d676b67c4 +e0e257483903f3e8d365128362d1325a +c26c685728b9a2356d1ecd82358affbf +4d05c122ade7966a94e4658247817701 +21a29367e3cefb30cb775905a6699487 + +1 block +iv: 0000000000000000000000123456789a +out: 88c87a8644e587dc7e3057edf2a80cc3 +in: 0f0e0d0c0b0a09080706050403020100 + +1 block + 6 bytes +iv: 0000000000000000000000123456789a +out: 57edf2a80cc389a4b92cde579f93da9ae5cc8b18e875 +in: 1514131211100f0e0d0c0b0a0908070605040302010 + +3 blocks + 3 bytes +iv: 0000000000000000000000123456789a +out: 41c2e1e4a22c106ace4c926e3725aa6877a4be5b7b62cb514595696240d72889208c3488c87a8644e587dc7e3057edf2a80cc3 +in: 3231302f2e2d2c2b2a292827262524232221201f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100 + +*) + +let c0 = new_definition + `c0 = [word 0xc3; word 0x0c; word 0xa8; word 0xf2 + ; word 0xed; word 0x57; word 0x30; word 0x7e + ; word 0xdc; word 0x87; word 0xe5; word 0x44 + ; word 0x86; word 0x7a; word 0xc8; word 0x88] : byte list`;; +let p0 = new_definition + `p0 = [word 0x00; word 0x01; word 0x02; word 0x03 + ; word 0x04; word 0x05; word 0x06; word 0x07 + ; word 0x08; word 0x09; word 0x0a; word 0x0b + ; word 0x0c; word 0x0d; word 0x0e; word 0x0f] : byte list`;; + +let c1 = new_definition + `c1 = [ word 0x75; word 0xe8; word 0x18; word 0x8b; + word 0xcc; word 0xe5; word 0x9a; word 0xda; + word 0x93; word 0x9f; word 0x57; word 0xde; + word 0x2c; word 0xb9; word 0xa4; word 0x89; + word 0xc3; word 0x0c; word 0xa8; word 0xf2; + word 0xed; word 0x57 ] : byte list`;; +let p1 = new_definition + `p1 = [word 0x0; word 0x1; word 0x2; word 0x3; + word 0x4; word 0x5; word 0x6; word 0x7; + word 0x8; word 0x9; word 0xa; word 0xb; + word 0xc; word 0xd; word 0xe; word 0xf; + word 0x10; word 0x11; word 0x12; word 0x13; + word 0x14; word 0x15] : byte list`;; + +let c2 = new_definition + `c2 = [ word 0xc3; word 0x0c; word 0xa8; word 0xf2; + word 0xed; word 0x57; word 0x30; word 0x7e; + word 0xdc; word 0x87; word 0xe5; word 0x44; + word 0x86; word 0x7a; word 0xc8; word 0x88; + word 0x34; word 0x8c; word 0x20; word 0x89; + word 0x28; word 0xd7; word 0x40; word 0x62; + word 0x69; word 0x95; word 0x45; word 0x51; + word 0xcb; word 0x62; word 0x7b; word 0x5b; + word 0xbe; word 0xa4; word 0x77; word 0x68; + word 0xaa; word 0x25; word 0x37; word 0x6e; + word 0x92; word 0x4c; word 0xce; word 0x6a; + word 0x10; word 0x2c; word 0xa2; word 0xe4; + word 0xe1; word 0xc2; word 0x41 ] : byte list`;; +let p2 = new_definition + `p2 = [word 0x0; word 0x1; word 0x2; word 0x3; + word 0x4; word 0x5; word 0x6; word 0x7; + word 0x8; word 0x9; word 0xa; word 0xb; + word 0xc; word 0xd; word 0xe; word 0xf; + word 0x10; word 0x11; word 0x12; word 0x13; + word 0x14; word 0x15; word 0x16; word 0x17; + word 0x18; word 0x19; word 0x1a; word 0x1b; + word 0x1c; word 0x1d; word 0x1e; word 0x1f; + word 0x20; word 0x21; word 0x22; word 0x23; + word 0x24; word 0x25; word 0x26; word 0x27; + word 0x28; word 0x29; word 0x2a; word 0x2b; + word 0x2c; word 0x2d; word 0x2e; word 0x2f; + word 0x30; word 0x31; word 0x32] : byte list`;; + +let iv_tweak = new_definition + `iv_tweak = (word 0x0000000000000000000000123456789a) : int128`;; + +let KEY1 = new_definition `KEY1:int128 list = + [ word 0xc70a951e84370d1836bdd387607e94e5 + ; word 0x7ead95d6f74bf6b3103340cce21b473d + ; word 0x298c296cdf3241d53d0757ddbebda060 + ; word 0x89e66365e778b67ff22807f1cdc91c8f + ; word 0xf6be68b9e235160883baf7bd2340b902 + ; word 0x6e9ed51a1550b18e3fe11b7e185c513e + ; word 0x148b7eb1618fe1b5a0fa4ebf336ae76e + ; word 0x7bce64942ab1aaf027bd4a40982968cd + ; word 0x75049f04c175af0a9390a9d1d91a6526 + ; word 0x517fce640d0ce0b0bf94228de7e3085d + ; word 0xb471300e52e506db4a8accf7a81afe26 + ; word 0x5c732ed4b298c23d58772ad0be94ce31 + ; word 0xe69436d5186fca2ce29032d11463c620 + ; word 0xeeebece9eaefe8ede6e3e4e1e2e7e0e5 + ; word 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + ]`;; + +let KEY2 = new_definition `KEY2:int128 list = + [ word 0xb0b1b2b3b4b5b6b7b8b9babbbcbdbebf + ; word 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf + ; word 0x0ae0323bba5180880ee4363fb65d8c84 + ; word 0x67e123e2c740814163e527e6cb4c8d4d + ; word 0x908df02c9a6dc217203c429f2ed874a0 + ; word 0x685584790fb4a79bc8f426daab11013c + ; word 0xb241f85f22cc0873b8a1ca64989d88fb + ; word 0x338745cb5bd2c1b2546666299c9240f3 + ; word 0xaf72a5d51d335d8a3fff55f9875e9f9d + ; word 0xd9e1a4a0ea66e16bb1b420d9e5d246f0 + ; word 0xead5ca6245a76fb75894323d676b67c4 + ; word 0xe0e257483903f3e8d365128362d1325a + ; word 0xc26c685728b9a2356d1ecd82358affbf + ; word 0x4d05c122ade7966a94e4658247817701 + ; word 0x21a29367e3cefb30cb775905a6699487 + ]`;; + +(*******************************************) +(* Conversions *) +let XTS_INIT_TWEAK_CONV = + REWR_CONV xts_init_tweak THENC AESENC_HELPER_CONV;; + +(* +(REWRITE_CONV [iv_tweak;KEY2] THENC XTS_INIT_TWEAK_CONV) + `xts_init_tweak iv_tweak KEY2`;; + *) + +let AES256_XTS_DECRYPT_ROUND_CONV = + REWRITE_CONV [aes256_xts_decrypt_round] THENC + SUBLET_CONV WORD_RED_CONV THENC + let_CONV THENC + SUBLET_CONV AESDEC_HELPER_CONV THENC + let_CONV THENC WORD_RED_CONV;; + +(* (REWRITE_CONV [iv_tweak; KEY2] THENC AES256_XTS_DECRYPT_ROUND_CONV) + `aes256_xts_decrypt_round iv_tweak iv_tweak KEY2`;; *) + +let XTSDEC_1BLOCK_HELPER_CONV = + REWR_CONV aes256_xts_decrypt_1block THENC + REWRITE_CONV [xts_init_tweak] THENC + SUBLET_CONV AESENC_HELPER_CONV THENC + let_CONV THENC + AES256_XTS_DECRYPT_ROUND_CONV;; + +(*162 seconds +time prove (`aes256_xts_decrypt_1block + (word 0x88c87a8644e587dc7e3057edf2a80cc3) + (word 0x0000000000000000000000123456789a) + KEY1 KEY2 = word 0x0f0e0d0c0b0a09080706050403020100`, + CONV_TAC(LAND_CONV XTSDEC_1BLOCK_HELPER_CONV) THEN REFL_TAC);; +*) + +let EL_16_8_CLAUSES = + let pat = `EL n [x0;x1;x2;x3;x4;x5;x6;x7;x8;x9;x10;x11;x12;x13;x14;x15]:byte` in + map (fun n -> EL_CONV(subst [mk_small_numeral n,`n:num`] pat)) (0--15);; + +let BYTES_TO_INT128_CONV = + REWRITE_CONV [bytes_to_int128] THENC + REWRITE_CONV EL_16_8_CLAUSES THENC + DEPTH_CONV WORD_RED_CONV;; + +(* (REWRITE_CONV [c0] THENC BYTES_TO_INT128_CONV) `bytes_to_int128 c0`;; *) + +let INT128_TO_BYTES_CONV = + REWRITE_CONV [int128_to_bytes] THENC + DEPTH_CONV WORD_RED_CONV;; + +(* INT128_TO_BYTES_CONV `int128_to_bytes (word 0x0102030405060708090a0b0c0d0e0f)`;; *) + +let GF_128_MULT_BY_PRIMITIVE_CONV = + REWRITE_CONV [GF_128_mult_by_primitive] THENC + REPEATC let_CONV THENC + DEPTH_CONV WORD_RED_CONV;; + +(* GF_128_MULT_BY_PRIMITIVE_CONV + `GF_128_mult_by_primitive (word 0xffffffffffffffffffffffffffffffff)`;; *) + +let rec CALCULATE_TWEAK_CONV tm = + let BASE_CONV = + ONCE_REWRITE_CONV [calculate_tweak] THENC + XTS_INIT_TWEAK_CONV in + let INDUCT_CONV = + RATOR_CONV(LAND_CONV num_CONV) THENC + ONCE_REWRITE_CONV [CONJUNCT2 calculate_tweak] THENC + RAND_CONV CALCULATE_TWEAK_CONV THENC + GF_128_MULT_BY_PRIMITIVE_CONV in + match tm with + | Comb + (Comb + (Comb + (Const ("calculate_tweak",_), n), + _), + _) -> + if dest_numeral n =/ num 0 + then BASE_CONV tm + else INDUCT_CONV tm + | _ -> failwith "CALCULATE_TWEAK_CONV: inapplicable";; + +(* +(REWRITE_CONV [iv_tweak;KEY2] THENC CALCULATE_TWEAK_CONV) `calculate_tweak 0 iv_tweak KEY2`;; + +(REWRITE_CONV [iv_tweak;KEY2] THENC CALCULATE_TWEAK_CONV) `calculate_tweak 1 iv_tweak KEY2`;; +*) + +let rec AES256_XTS_DECRYPT_REC_CONV tm = + let BASE_CONV = + REWR_CONV aes256_xts_decrypt_rec THENC + DEPTH_CONV NUM_RED_CONV in + let INDUCT_CONV = + REWR_CONV aes256_xts_decrypt_rec THENC + DEPTH_CONV NUM_RED_CONV THENC + ONCE_DEPTH_CONV SUB_LIST_CONV THENC + ONCE_DEPTH_CONV BYTES_TO_INT128_CONV THENC let_CONV THENC + SUBLET_CONV CALCULATE_TWEAK_CONV THENC let_CONV THENC + SUBLET_CONV (RAND_CONV AES256_XTS_DECRYPT_ROUND_CONV) THENC + SUBLET_CONV INT128_TO_BYTES_CONV THENC let_CONV THENC + SUBLET_CONV AES256_XTS_DECRYPT_REC_CONV THENC let_CONV THENC + REWRITE_CONV [APPEND] in + match tm with + | Comb + (Comb + (Comb + (Comb + (Comb + (Comb (Const ("aes256_xts_decrypt_rec", _), i), m), + _), + _), + _), + _) -> + if dest_numeral m failwith "AES256_XTS_DECRYPT_REC_CONV: inapplicable";; + +(* +(REWRITE_CONV [iv_tweak;KEY1;KEY2;c0] THENC AES256_XTS_DECRYPT_REC_CONV) + `aes256_xts_decrypt_rec 0 0 c0 iv_tweak KEY1 KEY2`;; +*) + +let CIPHER_STEALING_CONV = + REWRITE_CONV [cipher_stealing] THENC + SUBLET_CONV CALCULATE_TWEAK_CONV THENC let_CONV THENC + SUBLET_CONV GF_128_MULT_BY_PRIMITIVE_CONV THENC let_CONV THENC + SUBLET_CONV (ONCE_DEPTH_CONV BYTES_TO_INT128_CONV) THENC + SUBLET_CONV (RAND_CONV AES256_XTS_DECRYPT_ROUND_CONV) THENC + SUBLET_CONV INT128_TO_BYTES_CONV THENC let_CONV THENC + SUBLET_CONV SUB_LIST_CONV THENC let_CONV THENC + SUBLET_CONV (DEPTH_CONV NUM_RED_CONV) THENC (* For evaluating 16 - tail_len *) + SUBLET_CONV SUB_LIST_CONV THENC let_CONV THENC + SUBLET_CONV (ONCE_DEPTH_CONV (REWRITE_CONV [APPEND])) THENC + SUBLET_CONV BYTES_TO_INT128_CONV THENC let_CONV THENC + SUBLET_CONV (RAND_CONV AES256_XTS_DECRYPT_ROUND_CONV) THENC + SUBLET_CONV INT128_TO_BYTES_CONV THENC let_CONV;; + +(* +(REWRITE_CONV [c0;iv_tweak;KEY1;KEY2] THENC CIPHER_STEALING_CONV) + `cipher_stealing c0 [(word 0x0)] 1 iv_tweak 0 KEY1 KEY2`;; +*) + +let AES256_XTS_DECRYPT_TAIL_CONV tm = + let ONE_BLOCK_CONV = + REWR_CONV aes256_xts_decrypt_tail THENC + DEPTH_CONV NUM_RED_CONV THENC + SUBLET_CONV (RAND_CONV SUB_LIST_CONV) THENC + SUBLET_CONV BYTES_TO_INT128_CONV THENC let_CONV THENC + SUBLET_CONV CALCULATE_TWEAK_CONV THENC let_CONV THENC + RAND_CONV AES256_XTS_DECRYPT_ROUND_CONV THENC + INT128_TO_BYTES_CONV in + let ONE_BLOCK_AND_TAIL_CONV = + REWR_CONV aes256_xts_decrypt_tail THENC + DEPTH_CONV NUM_RED_CONV THENC + SUBLET_CONV SUB_LIST_CONV THENC let_CONV THENC + SUBLET_CONV SUB_LIST_CONV THENC let_CONV THENC + SUBLET_CONV CIPHER_STEALING_CONV THENC let_CONV THENC + REWRITE_CONV [FST;SND] THENC REWRITE_CONV [APPEND] in + match tm with + | Comb + (Comb + (Comb + (Comb + (Comb + (Comb + (Const ("aes256_xts_decrypt_tail", _), _), tail_len), + _), + _), + _), + _) -> + if dest_numeral tail_len =/ num 0 + then ONE_BLOCK_CONV tm + else ONE_BLOCK_AND_TAIL_CONV tm + | _ -> failwith "AES256_XTS_DECRYPT_TAIL_CONV: inapplicable";; + +(* +(REWRITE_CONV [c0;iv_tweak;KEY1;KEY2] THENC AES256_XTS_DECRYPT_TAIL_CONV) + `aes256_xts_decrypt_tail 0 0 c0 iv_tweak KEY1 KEY2`;; + +(REWRITE_CONV [c1;iv_tweak;KEY1;KEY2] THENC AES256_XTS_DECRYPT_TAIL_CONV) + `aes256_xts_decrypt_tail 0 6 c1 iv_tweak KEY1 KEY2`;; +*) + +let AES256_XTS_DECRYPT_CONV tm = + let ERROR_CONV = + REWR_CONV aes256_xts_decrypt THENC + DEPTH_CONV NUM_RED_CONV in + let MORE_THAN_2_CONV = + SUBLET_CONV AES256_XTS_DECRYPT_REC_CONV THENC let_CONV THENC + SUBLET_CONV AES256_XTS_DECRYPT_TAIL_CONV THENC let_CONV THENC + REWRITE_CONV [APPEND] in + let BODY_CONV = + REWR_CONV aes256_xts_decrypt THENC + DEPTH_CONV NUM_RED_CONV THENC let_CONV THENC + DEPTH_CONV NUM_RED_CONV THENC let_CONV THENC + DEPTH_CONV NUM_RED_CONV THENC + (AES256_XTS_DECRYPT_TAIL_CONV ORELSEC MORE_THAN_2_CONV) in + match tm with + | Comb + (Comb + (Comb + (Comb + (Comb + (Const ("aes256_xts_decrypt", _), _), len), + _), + _), + _) -> + if dest_numeral len failwith "AES256_XTS_DECRYPT_CONV: inapplicable";; + +(* +AES256_XTS_DECRYPT_CONV + `aes256_xts_decrypt c0 5 iv_tweak KEY1 KEY2`;; + +(REWRITE_CONV [c0;iv_tweak;KEY1;KEY2] THENC AES256_XTS_DECRYPT_CONV) + `aes256_xts_decrypt c0 16 iv_tweak KEY1 KEY2`;; + +time (REWRITE_CONV [iv_tweak;KEY1;KEY2] THENC AES256_XTS_DECRYPT_CONV) + `aes256_xts_decrypt [word 0xc3; word 0x0c; word 0xa8; word 0xf2 + ; word 0xed; word 0x57; word 0x30; word 0x7e + ; word 0xdc; word 0x87; word 0xe5; word 0x44 + ; word 0x86; word 0x7a; word 0xc8; word 0x88 + ; word 0xc3; word 0x0c; word 0xa8; word 0xf2 + ; word 0xed; word 0x57; word 0x30; word 0x7e + ; word 0xdc; word 0x87; word 0xe5; word 0x44 + ; word 0x86; word 0x7a; word 0xc8; word 0x88 + ; word 0x00] + 33 iv_tweak KEY1 KEY2`;; +*) + +(*******************************************) +(* Tests *) + +(* +(* 1 block : 81 second *) +time prove (`aes256_xts_decrypt c0 16 iv_tweak KEY1 KEY2 = p0`, + CONV_TAC(LAND_CONV (REWRITE_CONV [c0;iv_tweak;KEY1;KEY2] THENC AES256_XTS_DECRYPT_CONV)) THEN + REWRITE_TAC [p0] THEN REFL_TAC);; + +(* 1 block + 6 bytes : 121 seconds *) +time prove(`aes256_xts_decrypt c1 22 iv_tweak KEY1 KEY2 = p1`, + CONV_TAC(LAND_CONV (REWRITE_CONV [c1;iv_tweak;KEY1;KEY2;p1] THENC AES256_XTS_DECRYPT_CONV)) THEN + REWRITE_TAC [p1] THEN REFL_TAC);; + +(* 3 blocks + 3 bytes : 273 seconds *) +time prove(`aes256_xts_decrypt c2 51 iv_tweak KEY1 KEY2 = p2`, + CONV_TAC(LAND_CONV (REWRITE_CONV [c2;iv_tweak;KEY1;KEY2;p2] THENC AES256_XTS_DECRYPT_CONV)) THEN + REWRITE_TAC [p2] THEN REFL_TAC);; +*) \ No newline at end of file diff --git a/arm/proofs/utils/aes_xts_encrypt_spec.ml b/arm/proofs/utils/aes_xts_encrypt_spec.ml new file mode 100644 index 000000000..1c0379aae --- /dev/null +++ b/arm/proofs/utils/aes_xts_encrypt_spec.ml @@ -0,0 +1,615 @@ +(* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0 + *) + +needs "arm/proofs/utils/aes_xts_common_spec.ml";; + +(* +AES-256-XTS Encryption Algorithm for Any Input Length +Based on IEEE 1619-2007 Standard + +This specification implements the complete AES-XTS encryption algorithm +as described in IEEE 1619-2007, Section 5.3, supporting arbitrary input lengths. + +Key components: +- Key = Key1 (256-bit data key) || Key2 (256-bit tweak key) +- P is the plaintext of arbitrary length (>= 128 bits) +- i is the value of the 128-bit tweak +- C is the resulting ciphertext + +The algorithm processes data in 128-bit blocks with special handling for +the final partial block (if any) using ciphertext stealing. + +For each complete block j: + T_j := AES-enc(Key2, i) MUL alpha^j + PP_j := P_j XOR T_j + CC_j := AES-enc(Key1, PP_j) + C_j := CC_j XOR T_j + +Where alpha is the primitive element in GF(2^128) and MUL denotes multiplication +in the Galois field. + +For partial final blocks, ciphertext stealing is used as per Section 5.3.2. +*) + +(*****************************************) +(* AES-XTS encryption full *) + +(* AES-XTS encryption round function *) +let aes256_xts_encrypt_round = new_definition + `aes256_xts_encrypt_round (P:int128) (tk:int128) (key1:int128 list) = + let PP = word_xor P tk in + let CC = aes256_encrypt PP key1 in + word_xor CC tk`;; + +(* Single block AES-XTS encryption *) +let aes256_xts_encrypt_1block = new_definition + `aes256_xts_encrypt_1block (P:int128) (iv:int128) (key1:int128 list) (key2:int128 list) = + let tk = xts_init_tweak iv key2 in + aes256_xts_encrypt_round P tk key1`;; + +(* Recursive encryption function for multiple blocks *) +let eth = prove_general_recursive_function_exists + `?aes256_xts_encrypt_rec. + ! (i:num) (m:num) (P:byte list) (iv:int128) (key1:int128 list) (key2:int128 list). + aes256_xts_encrypt_rec i m P iv key1 key2 : (byte list) = + if m < i then [] + else + let current_block = bytes_to_int128 (SUB_LIST (i * 16, 16) P) in + let twk = calculate_tweak i iv key2 in + let curr = int128_to_bytes (aes256_xts_encrypt_round current_block twk key1) in + let res = aes256_xts_encrypt_rec (i + 1) m P iv key1 key2 in + APPEND curr res`;; + +let wfth = prove(hd(hyp eth), + EXISTS_TAC `MEASURE (\(i:num,m:num,P:byte list,iv:int128,key1:int128 list,key2:int128 list). (m + 1) - i)` THEN + REWRITE_TAC[WF_MEASURE; MEASURE] THEN ARITH_TAC);; + +let exists_lemma = PROVE_HYP wfth eth;; + +(* Note: results are stored in LSByte to MSByte *) +let aes256_xts_encrypt_rec = new_specification ["aes256_xts_encrypt_rec"] exists_lemma;; + +(* Cipher stealing for encryption (note: encryption cipher stealing is different from decryption) + Pm1 : last full block; P_{m-1} in the standard + Pm : tail; P_m +*) +let cipher_stealing_encrypt = new_definition + `cipher_stealing_encrypt (Pm1:byte list) (Pm:byte list) (tail_len:num) + (iv:int128) (i:num) (key1:int128 list) (key2:int128 list): (byte list)#(byte list) = + let twk = calculate_tweak i iv key2 in + let CC = int128_to_bytes (aes256_xts_encrypt_round (bytes_to_int128 Pm1) twk key1) in + let Cm = SUB_LIST (0, tail_len) CC in + let CP = SUB_LIST (tail_len, 16 - tail_len) CC in + let PP = bytes_to_int128 (APPEND Pm CP) in + let twk_last = GF_128_mult_by_primitive twk in + let Cm1 = int128_to_bytes (aes256_xts_encrypt_round PP twk_last key1) in + (Cm1, Cm)`;; + +(* Encryption tail handling - either single block or cipher stealing *) +let aes256_xts_encrypt_tail = new_definition + `aes256_xts_encrypt_tail (i:num) (tail_len:num) (P:byte list) (iv:int128) + (key1:int128 list) (key2:int128 list) : byte list = + if tail_len = 0 then + let Pm1 = bytes_to_int128 (SUB_LIST (i * 16, 16) P) in + let twk = calculate_tweak i iv key2 in + int128_to_bytes (aes256_xts_encrypt_round Pm1 twk key1) + else + let Pm1 = SUB_LIST (i * 16, 16) P in + let Pm = SUB_LIST ((i + 1) * 16, tail_len) P in + let res_cs = cipher_stealing_encrypt Pm1 Pm tail_len iv i key1 key2 in + APPEND (FST res_cs) (SND res_cs)`;; + +(* The main encryption function *) +(* Note: the specification does not handle the case of len < 16, which is + handled in the implementation. *) +(* AES256-XTS assumes there is at least one block in input *) +(* + P: Input plaintext represented as a byte list + len: Byte length of P + iv: Initialization vector (tweak) as an int128 + key1: Key schedule for AES-256 encryption + key2: Key schedule for AES-256 encryption for the tweak + return: Output ciphertext as a byte list + When input len < 16, the function returns []. +*) + +let aes256_xts_encrypt = new_definition + `aes256_xts_encrypt + (P:byte list) (len:num) (iv:int128) (key1:int128 list) (key2:int128 list) : byte list = + if len < 16 then + [] + else + let tail_len = len MOD 16 in + let m = (len - tail_len) DIV 16 in + if m < 2 then + aes256_xts_encrypt_tail 0 tail_len P iv key1 key2 + else + let res = aes256_xts_encrypt_rec 0 (m - 2) P iv key1 key2 in + let Ctail = aes256_xts_encrypt_tail (m - 1) tail_len P iv key1 key2 in + APPEND res Ctail`;; + +(***********************************************) +(* Conversions and test vectors *) +(* Test case: Basic XTS encryption *) +(* +Test Vector: +Plaintext: 000102030405060708090a0b0c0d0e0f +Data Key: 2718281828459045235360287471352662497757247093699959574966967627 +Tweak Key: 3141592653589793238462643383279502884197169399375105820974944592 +Tweak: FF000000000000000000000000000000 +Expected: 1C3B3A102F770386E4836C99E370CF9B + Plaintext (reversed): 0F0E0D0C0B0A09080706050403020100 + Ciphertext (reversed): 9BCF70E3996C83E48603772F103A3B1C + +The test vector values appear in reverse byte order to be little endian. +*) +(* Test vectors based on our Python implementation results *) +let data_key_schedule = new_definition `data_key_schedule:int128 list = + [ word 0x26357174286053234590452818281827 + ; word 0x27769666495759996993702457774962 + ; word 0x602147C9461436BD6E74659E2BE420B6 + ; word 0x80385664A74EC002EE19999B878AE9BF + ; word 0x206833EF40497426065D429B68292705 + ; word 0xF9A0259D799873F9DED6B3FB30CF2A60 + ; word 0x50CCC26C70A4F18330ED85A536B0C73E + ; word 0x3D6AEAAFC4CACF32BD52BCCB63840F30 + ; word 0x5F1273FB0FDEB1977F7A40144F97C5B1 + ; word 0xE8BF1969D5D5F3C6111F3CF4AC4D803F + ; word 0x99BA4F0DC6A83CF6C9768D61B60CCD75 + ; word 0x6ECCD2B38673CBDA53A6381C42B904E8 + ; word 0x4DF7787AD44D377712E50B81DB9386E0 + ; word 0x1AC8994774044BF4F277802EA1D1B832 + ; word 0xF06E2AC2BD9952B869D465CF7B316E4E + ]`;; + +let tweak_key_schedule = new_definition `tweak_key_schedule:int128 list = + [ word 0x95278333646284239397585326594131 + ; word 0x92459474098205513799931697418802 + ; word 0xD6C4705143E3F36227817741B4162F12 + ; word 0xCD03DBE05F464F9456C44AC5615DD9D3 + ; word 0xE70DA0DB31C9D08A722A23E855AB54A9 + ; word 0x310BE7DBFC083C3BA34E73AFF58A396A + ; word 0x48822C80AF8F8C5B9E465CD1EC6C7F39 + ; word 0xC9D4E0E8F8DF073304D73B08A79948A7 + ; word 0x0EFACBDA4678E75AE9F76B0177B137D0 + ; word 0x39688B23F0BC6BCB08636CF80CB457F0 + ; word 0xF0D6357CFE2CFEA6B85419FC51A372FD + ; word 0x41F54DF0789DC6D38821AD188042C1E0 + ; word 0x6B8E46189B58736465748DC2DD20943E + ; word 0x4E12BD760FE7F086777A3655FF5B9B4D + ; word 0x70ADE5BA1B23A3A2807BD0C6E50F5D04 + ]`;; + +(* + Two-block test vector (same key and tweak as single block) + Plaintext: 000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f + Data Key: 2718281828459045235360287471352662497757247093699959574966967627 + Tweak Key: 3141592653589793238462643383279502884197169399375105820974944592 + Tweak: FF000000000000000000000000000000 + Ciphertext: 1C3B3A102F770386E4836C99E370CF9B EA00803F5E482357A4AE12D414A3E63B + Plaintext (reversed): 0F0E0D0C0B0A09080706050403020100 1F1E1D1C1B1A19181716151413121110 + Ciphertext (reversed): 9BCF70E3996C83E48603772F103A3B1C 3BE6A314D412AEA45723485E3F8000EA +*) + +(* Convert reversed plaintext and ciphertext to byte lists using int128_to_bytes *) +let ptext = new_definition + `ptext = + int128_to_bytes (word 0x0F0E0D0C0B0A09080706050403020100 : int128)`;; + +let ctext = new_definition + `ctext = + int128_to_bytes (word 0x9BCF70E3996C83E48603772F103A3B1C : int128 )`;; + +let iv1 = new_definition + `iv1 = (word 0x000000000000000000000000000000FF) : int128`;; + +let ptext2 = new_definition + `ptext2 = + APPEND (int128_to_bytes (word 0x0F0E0D0C0B0A09080706050403020100)) + (int128_to_bytes (word 0x1F1E1D1C1B1A19181716151413121110))`;; + +(* +(REWR_CONV ptext2 THENC + RAND_CONV INT128_TO_BYTES_CONV THENC + RATOR_CONV(RAND_CONV INT128_TO_BYTES_CONV) THENC + REWRITE_CONV [APPEND]) `ptext2`;; +*) + (* loops indefinitely + (REWR_CONV ptext2 THENC + DEPTH_CONV INT128_TO_BYTES_CONV THENC + (*RATOR_CONV(RAND_CONV INT128_TO_BYTES_CONV) THENC*) + REWRITE_CONV [APPEND]) `ptext2`;; +*) + +(* Test values from aes_xts_decrypt_spec.ml *) + let iv_tweak = new_definition + `iv_tweak = (word 0x0000000000000000000000123456789a) : int128`;; + +(* p0 = pm1 = ptext *) +let pm1 = new_definition + `pm1 = [word 0x0; word 0x1; word 0x2; word 0x3; + word 0x4; word 0x5; word 0x6; word 0x7; + word 0x8; word 0x9; word 0xa; word 0xb; + word 0xc; word 0xd; word 0xe; word 0xf] : byte list`;; +let pm = new_definition + `pm = [word 0x10; word 0x11; word 0x12; word 0x13; + word 0x14; word 0x15] : byte list`;; + +let cm1 = new_definition + `cm1 = [word 0x75; word 0xe8; word 0x18; word 0x8b; word 0xcc; word 0xe5; + word 0x9a; word 0xda; word 0x93; word 0x9f; word 0x57; word 0xde; + word 0x2c; word 0xb9; word 0xa4; word 0x89] : byte list`;; +let cm = new_definition + `cm = [word 0xc3; word 0xc; word 0xa8; word 0xf2; word 0xed; word 0x57] : byte list`;; + +let c0 = new_definition + `c0 = [word 0xc3; word 0x0c; word 0xa8; word 0xf2 + ; word 0xed; word 0x57; word 0x30; word 0x7e + ; word 0xdc; word 0x87; word 0xe5; word 0x44 + ; word 0x86; word 0x7a; word 0xc8; word 0x88] : byte list`;; + +let p1 = new_definition + `p1 = [word 0x0; word 0x1; word 0x2; word 0x3; + word 0x4; word 0x5; word 0x6; word 0x7; + word 0x8; word 0x9; word 0xa; word 0xb; + word 0xc; word 0xd; word 0xe; word 0xf; + word 0x10; word 0x11; word 0x12; word 0x13; + word 0x14; word 0x15] : byte list`;; +let c1 = new_definition + `c1 = [ word 0x75; word 0xe8; word 0x18; word 0x8b; + word 0xcc; word 0xe5; word 0x9a; word 0xda; + word 0x93; word 0x9f; word 0x57; word 0xde; + word 0x2c; word 0xb9; word 0xa4; word 0x89; + word 0xc3; word 0x0c; word 0xa8; word 0xf2; + word 0xed; word 0x57 ] : byte list`;; + +let p2 = new_definition + `p2 = [word 0x0; word 0x1; word 0x2; word 0x3; + word 0x4; word 0x5; word 0x6; word 0x7; + word 0x8; word 0x9; word 0xa; word 0xb; + word 0xc; word 0xd; word 0xe; word 0xf; + word 0x10; word 0x11; word 0x12; word 0x13; + word 0x14; word 0x15; word 0x16; word 0x17; + word 0x18; word 0x19; word 0x1a; word 0x1b; + word 0x1c; word 0x1d; word 0x1e; word 0x1f; + word 0x20; word 0x21; word 0x22; word 0x23; + word 0x24; word 0x25; word 0x26; word 0x27; + word 0x28; word 0x29; word 0x2a; word 0x2b; + word 0x2c; word 0x2d; word 0x2e; word 0x2f; + word 0x30; word 0x31; word 0x32] : byte list`;; +let c2 = new_definition + `c2 = [ word 0xc3; word 0x0c; word 0xa8; word 0xf2; + word 0xed; word 0x57; word 0x30; word 0x7e; + word 0xdc; word 0x87; word 0xe5; word 0x44; + word 0x86; word 0x7a; word 0xc8; word 0x88; + word 0x34; word 0x8c; word 0x20; word 0x89; + word 0x28; word 0xd7; word 0x40; word 0x62; + word 0x69; word 0x95; word 0x45; word 0x51; + word 0xcb; word 0x62; word 0x7b; word 0x5b; + word 0xbe; word 0xa4; word 0x77; word 0x68; + word 0xaa; word 0x25; word 0x37; word 0x6e; + word 0x92; word 0x4c; word 0xce; word 0x6a; + word 0x10; word 0x2c; word 0xa2; word 0xe4; + word 0xe1; word 0xc2; word 0x41 ] : byte list`;; + +(* +(* This key schedule is from aes_xts_decrypt_spec.ml + It is used in EQINVCIPHER found in Sec 5.3.5 of + https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf + which is implemented in AWS-LC as the AES decryption algorithm. + It's different from the encryption key scheduling. *) +let key_1 = new_definition `key_1:int128 list = + [ word 0xc70a951e84370d1836bdd387607e94e5 + ; word 0x7ead95d6f74bf6b3103340cce21b473d + ; word 0x298c296cdf3241d53d0757ddbebda060 + ; word 0x89e66365e778b67ff22807f1cdc91c8f + ; word 0xf6be68b9e235160883baf7bd2340b902 + ; word 0x6e9ed51a1550b18e3fe11b7e185c513e + ; word 0x148b7eb1618fe1b5a0fa4ebf336ae76e + ; word 0x7bce64942ab1aaf027bd4a40982968cd + ; word 0x75049f04c175af0a9390a9d1d91a6526 + ; word 0x517fce640d0ce0b0bf94228de7e3085d + ; word 0xb471300e52e506db4a8accf7a81afe26 + ; word 0x5c732ed4b298c23d58772ad0be94ce31 + ; word 0xe69436d5186fca2ce29032d11463c620 + ; word 0xeeebece9eaefe8ede6e3e4e1e2e7e0e5 + ; word 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + ]`;; +*) +let key_1 = new_definition `key_1:int128 list = + [ word 0xF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF + ; word 0xE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF + ; word 0x11E1F899E1100A6A15E5FC9DED1C0666 + ; word 0x82F841EE6219A30D86FC45EA6E15AF01 + ; word 0x201B498931FAB110D0EABB7AC50F47E7 + ; word 0xBFA733AF3D5F72415F46D14CD9BA94A6 + ; word 0x7D0C58C35D17114A6CEDA05ABC071B20 + ; word 0xFBFA6E2A445D5D8579022FC42644FE88 + ; word 0x15FEDF6468F287A735E596ED590836B7 + ; word 0xB95A7CA042A0128A06FD4F0F7FFF60CB + ; word 0xF1B74699E44999FD8CBB1E5AB95E88B7 + ; word 0x23511B009A0B67A0D8AB752ADE563A25 + ; word 0x433D9806B28ADE9F56C34762DA785938 + ; word 0xA58075C086D16EC01CDA0960C4717C4A + ; word 0xC70A951E84370D1836BDD387607E94E5 + ]`;; + +let key_2 = new_definition `key_2:int128 list = + [ word 0xb0b1b2b3b4b5b6b7b8b9babbbcbdbebf + ; word 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf + ; word 0x0ae0323bba5180880ee4363fb65d8c84 + ; word 0x67e123e2c740814163e527e6cb4c8d4d + ; word 0x908df02c9a6dc217203c429f2ed874a0 + ; word 0x685584790fb4a79bc8f426daab11013c + ; word 0xb241f85f22cc0873b8a1ca64989d88fb + ; word 0x338745cb5bd2c1b2546666299c9240f3 + ; word 0xaf72a5d51d335d8a3fff55f9875e9f9d + ; word 0xd9e1a4a0ea66e16bb1b420d9e5d246f0 + ; word 0xead5ca6245a76fb75894323d676b67c4 + ; word 0xe0e257483903f3e8d365128362d1325a + ; word 0xc26c685728b9a2356d1ecd82358affbf + ; word 0x4d05c122ade7966a94e4658247817701 + ; word 0x21a29367e3cefb30cb775905a6699487 + ]`;; + + +(* +let AES_XTS_ENC_1BLK_HELPER_CONV = +(* PRINT_TERM_CONV THENC *) + REWR_CONV aes256_xts_encrypt_1block THENC + PRINT_TERM_CONV THENC + REWRITE_CONV [data_key_schedule; tweak_key_schedule] THENC + (* PRINT_TERM_CONV THENC *) + REWRITE_CONV [xts_init_tweak; aes256_xts_encrypt_round] THENC + REPEATC let_CONV THENC + DEPTH_CONV (WORD_RED_CONV ORELSEC NUM_RED_CONV) THENC + DEPTH_CONV AESENC_HELPER_CONV THENC + DEPTH_CONV (WORD_RED_CONV ORELSEC NUM_RED_CONV) + ;; +*) +let AES256_XTS_ENCRYPT_ROUND_CONV = + REWR_CONV aes256_xts_encrypt_round THENC + REPEATC let_CONV THENC + DEPTH_CONV (WORD_RED_CONV ORELSEC NUM_RED_CONV) THENC + DEPTH_CONV AESENC_HELPER_CONV THENC + DEPTH_CONV (WORD_RED_CONV ORELSEC NUM_RED_CONV);; +(* +(* 32 sec *) +time prove(`aes256_xts_encrypt_round + (word 0x0F0E0D0C0B0A09080706050403020100) + (word 0x8b2b4a71228e98aed6aa0ca97775261a) + data_key_schedule + = word 0x9BCF70E3996C83E48603772F103A3B1C`, + CONV_TAC(REWRITE_CONV[data_key_schedule] THENC LAND_CONV AES256_XTS_ENCRYPT_ROUND_CONV) THEN + REFL_TAC + );; +*) +(* +time prove(`aes256_xts_encrypt_round + (word 0x1F1E1D1C1B1A19181716151413121110) + (word 0x165694e2451d315dad541952eeea4cb3) + data_key_schedule + = word 0x3BE6A314D412AEA45723485E3F8000EA`, + CONV_TAC(REWRITE_CONV[data_key_schedule] THENC LAND_CONV AES256_XTS_ENCRYPT_ROUND_CONV) THEN + REFL_TAC + );; +*) + +let AES_XTS_ENC_1BLK_HELPER_CONV = + REWR_CONV aes256_xts_encrypt_1block THENC + REWRITE_CONV [xts_init_tweak] THENC + SUBLET_CONV AESENC_HELPER_CONV THENC + let_CONV THENC + AES256_XTS_ENCRYPT_ROUND_CONV;; + +(* +(* Proven in about 73 sec on M3 *) +time prove(`aes256_xts_encrypt_1block + (word 0x0F0E0D0C0B0A09080706050403020100) + (word 0x000000000000000000000000000000FF) + data_key_schedule + tweak_key_schedule + = word 0x9BCF70E3996C83E48603772F103A3B1C`, (* expected result in little endian *) + CONV_TAC(REWRITE_CONV [data_key_schedule; tweak_key_schedule] THENC LAND_CONV AES_XTS_ENC_1BLK_HELPER_CONV) + THEN REFL_TAC + );; +*) + +(* +let tmp_xts = AES_XTS_ENC_1BLK_HELPER_CONV + `aes256_xts_encrypt_1block + (word 0x0F0E0D0C0B0A09080706050403020100) + (word 0x000000000000000000000000000000FF) + data_key_schedule + tweak_key_schedule + `;; + +prove(list_mk_comb (`(=):((128)word->(128)word->bool)`, + [rand (concl tmp_xts);`(word 0x9BCF70E3996C83E48603772F103A3B1C):(128)word`]), + REFL_TAC);; +*) +(* + (* 67 sec on M3 *) +time prove(`aes256_xts_encrypt_1block + (word 0x0F0E0D0C0B0A09080706050403020100) + (word 0x0000000000000000000000123456789a) + key_1 + key_2 + = word 0x88c87a8644e587dc7e3057edf2a80cc3`, (* expected result in little endian *) + CONV_TAC(REWRITE_CONV [key_1; key_2] THENC LAND_CONV AES_XTS_ENC_1BLK_HELPER_CONV) + THEN REFL_TAC + );; +*) + + + +let rec AES256_XTS_ENCRYPT_REC_CONV tm = + let BASE_CONV = + REWR_CONV aes256_xts_encrypt_rec THENC + DEPTH_CONV NUM_RED_CONV in + let INDUCT_CONV = + REWR_CONV aes256_xts_encrypt_rec THENC + DEPTH_CONV NUM_RED_CONV THENC + ONCE_DEPTH_CONV SUB_LIST_CONV THENC + ONCE_DEPTH_CONV BYTES_TO_INT128_CONV THENC let_CONV THENC + SUBLET_CONV CALCULATE_TWEAK_CONV THENC let_CONV THENC + SUBLET_CONV (RAND_CONV AES256_XTS_ENCRYPT_ROUND_CONV) THENC + SUBLET_CONV INT128_TO_BYTES_CONV THENC let_CONV THENC + SUBLET_CONV AES256_XTS_ENCRYPT_REC_CONV THENC let_CONV THENC + REWRITE_CONV [APPEND] in + match tm with + | Comb + (Comb + (Comb + (Comb + (Comb + (Comb (Const ("aes256_xts_encrypt_rec", _), i), m), + _), + _), + _), + _) -> + if dest_numeral m failwith "AES256_XTS_ENCRYPT_REC_CONV: inapplicable";; + +(* +(REWRITE_CONV [iv1; data_key_schedule; tweak_key_schedule; ptext; int128_to_bytes] THENC + AES256_XTS_ENCRYPT_REC_CONV) + `aes256_xts_encrypt_rec 0 0 ptext iv1 data_key_schedule tweak_key_schedule`;; +*) (* +(REWRITE_CONV [iv_tweak; pm1; key_1; key_2] THENC + AES256_XTS_ENCRYPT_REC_CONV) + `aes256_xts_encrypt_rec 0 0 pm1 iv_tweak key_1 key_2`;; +*) +(* +(REWRITE_CONV [iv1; data_key_schedule; tweak_key_schedule; ptext2; int128_to_bytes; APPEND] THENC + AES256_XTS_ENCRYPT_REC_CONV) + `aes256_xts_encrypt_rec 0 1 ptext2 iv1 data_key_schedule tweak_key_schedule`;; +*) + +let CIPHER_STEALING_ENCRYPT_CONV = + REWR_CONV cipher_stealing_encrypt THENC + SUBLET_CONV CALCULATE_TWEAK_CONV THENC let_CONV THENC + SUBLET_CONV (ONCE_DEPTH_CONV BYTES_TO_INT128_CONV) THENC + SUBLET_CONV (RAND_CONV AES256_XTS_ENCRYPT_ROUND_CONV) THENC + SUBLET_CONV INT128_TO_BYTES_CONV THENC let_CONV THENC + SUBLET_CONV SUB_LIST_CONV THENC let_CONV THENC + SUBLET_CONV (DEPTH_CONV NUM_RED_CONV) THENC (* For evaluating 16 - tail_len *) + SUBLET_CONV SUB_LIST_CONV THENC let_CONV THENC + SUBLET_CONV (ONCE_DEPTH_CONV (REWRITE_CONV [APPEND])) THENC + SUBLET_CONV BYTES_TO_INT128_CONV THENC let_CONV THENC + SUBLET_CONV GF_128_MULT_BY_PRIMITIVE_CONV THENC let_CONV THENC + SUBLET_CONV (RAND_CONV AES256_XTS_ENCRYPT_ROUND_CONV) THENC + SUBLET_CONV INT128_TO_BYTES_CONV THENC let_CONV;; + +(* (REWRITE_CONV [ptext; int128_to_bytes; iv1; data_key_schedule; tweak_key_schedule] THENC CIPHER_STEALING_ENCRYPT_CONV) + `cipher_stealing_encrypt ptext [(word 0x0)] 1 iv1 0 data_key_schedule tweak_key_schedule`;;*) +(* +(REWRITE_CONV [pm1; pm; iv_tweak; key_1; key_2] THENC CIPHER_STEALING_ENCRYPT_CONV) + `cipher_stealing_encrypt pm1 pm 6 iv_tweak 0 key_1 key_2`;; +*) + +let AES256_XTS_ENCRYPT_TAIL_CONV tm = + let ONE_BLOCK_CONV = + REWR_CONV aes256_xts_encrypt_tail THENC + DEPTH_CONV NUM_RED_CONV THENC + SUBLET_CONV (RAND_CONV SUB_LIST_CONV) THENC + SUBLET_CONV BYTES_TO_INT128_CONV THENC let_CONV THENC + SUBLET_CONV CALCULATE_TWEAK_CONV THENC let_CONV THENC + RAND_CONV AES256_XTS_ENCRYPT_ROUND_CONV THENC + INT128_TO_BYTES_CONV in + let ONE_BLOCK_AND_TAIL_CONV = + REWR_CONV aes256_xts_encrypt_tail THENC + DEPTH_CONV NUM_RED_CONV THENC + SUBLET_CONV SUB_LIST_CONV THENC let_CONV THENC + SUBLET_CONV SUB_LIST_CONV THENC let_CONV THENC + SUBLET_CONV CIPHER_STEALING_ENCRYPT_CONV THENC let_CONV THENC + REWRITE_CONV [FST;SND] THENC REWRITE_CONV [APPEND] in + match tm with + | Comb + (Comb + (Comb + (Comb + (Comb + (Comb + (Const ("aes256_xts_encrypt_tail", _), _), tail_len), + _), + _), + _), + _) -> + if dest_numeral tail_len =/ num 0 + then ONE_BLOCK_CONV tm + else ONE_BLOCK_AND_TAIL_CONV tm + | _ -> failwith "AES256_XTS_ENCRYPT_TAIL_CONV: inapplicable";; +(* +(REWRITE_CONV [ptext; int128_to_bytes; iv1; data_key_schedule; tweak_key_schedule] THENC AES256_XTS_ENCRYPT_TAIL_CONV) + `aes256_xts_encrypt_tail 0 0 ptext iv1 data_key_schedule tweak_key_schedule`;; +*)(* +(REWRITE_CONV [p1;iv_tweak;key_1;key_2] THENC AES256_XTS_ENCRYPT_TAIL_CONV) + `aes256_xts_encrypt_tail 0 6 p1 iv_tweak key_1 key_2`;; +*)(* +(REWRITE_CONV [p0;iv_tweak;key_1;key_2] THENC AES256_XTS_ENCRYPT_TAIL_CONV) + `aes256_xts_encrypt_tail 0 0 p0 iv_tweak key_1 key_2`;; +*) + +let AES256_XTS_ENCRYPT_CONV tm = + let ERROR_CONV = + REWR_CONV aes256_xts_encrypt THENC + DEPTH_CONV NUM_RED_CONV in + let MORE_THAN_2_CONV = + SUBLET_CONV AES256_XTS_ENCRYPT_REC_CONV THENC let_CONV THENC + SUBLET_CONV AES256_XTS_ENCRYPT_TAIL_CONV THENC let_CONV THENC + REWRITE_CONV [APPEND] in + let BODY_CONV = + REWR_CONV aes256_xts_encrypt THENC + DEPTH_CONV NUM_RED_CONV THENC let_CONV THENC + DEPTH_CONV NUM_RED_CONV THENC let_CONV THENC + DEPTH_CONV NUM_RED_CONV THENC + (AES256_XTS_ENCRYPT_TAIL_CONV ORELSEC MORE_THAN_2_CONV) in + match tm with + | Comb + (Comb + (Comb + (Comb + (Comb + (Const ("aes256_xts_encrypt", _), _), len), + _), + _), + _) -> + if dest_numeral len failwith "AES256_XTS_ENCRYPT_CONV: inapplicable";; + +(* +(REWRITE_CONV [int128_to_bytes] THENC AES256_XTS_ENCRYPT_CONV) + `aes256_xts_encrypt p0 5 iv_tweak key_1 key_2`;; + +(*(REWRITE_CONV [ptext; int128_to_bytes; iv_tweak; key_1; key_2] THENC AES256_XTS_ENCRYPT_CONV) + `aes256_xts_encrypt ptext 16 iv_tweak key_1 key_2`;;*) + +(* 1 block : 70 sec on M3 *) +time prove (`aes256_xts_encrypt ptext 16 iv_tweak key_1 key_2 = c0`, + CONV_TAC(LAND_CONV (REWRITE_CONV [ptext; int128_to_bytes; iv_tweak; key_1; key_2] + THENC AES256_XTS_ENCRYPT_CONV)) THEN + REWRITE_TAC [c0] THEN REFL_TAC);; + +(* 1 block + 6 bytes : 104 sec on M3 *) +time prove (`aes256_xts_encrypt p1 22 iv_tweak key_1 key_2 = c1`, + CONV_TAC(LAND_CONV (REWRITE_CONV [p1; int128_to_bytes; iv_tweak; key_1; key_2] + THENC AES256_XTS_ENCRYPT_CONV)) THEN + REWRITE_TAC [c1] THEN REFL_TAC);; + +(* 3 blocks + 3 bytes : 243 sec on M3 *) +time prove (`aes256_xts_encrypt p2 51 iv_tweak key_1 key_2 = c2`, + CONV_TAC(LAND_CONV (REWRITE_CONV [p2; int128_to_bytes; iv_tweak; key_1; key_2] + THENC AES256_XTS_ENCRYPT_CONV)) THEN + REWRITE_TAC [c2] THEN REFL_TAC);; +*) +(*****************************************) + + + diff --git a/arm/tutorial/README.md b/arm/tutorial/README.md index 597454038..a96b4b776 100644 --- a/arm/tutorial/README.md +++ b/arm/tutorial/README.md @@ -14,6 +14,8 @@ To verify programs in x86, see `x86/tutorial`. 6. `bignum.ml`: Writing a specification of a program dealing with big numbers & proving it. 7. `rodata.ml`: Reading data from the read-only section. 8. `safety.ml`: Verify the safety property (constant-time and and memory-safe) +9. `aes_encrypt.ml`: Verifying a simple AES encryption program. +10. `aes_decrypt.ml`: Verifying a simple AES decryption program. ### Relational reasoning diff --git a/arm/tutorial/aes_decrypt.S b/arm/tutorial/aes_decrypt.S new file mode 100644 index 000000000..8feef9fa2 --- /dev/null +++ b/arm/tutorial/aes_decrypt.S @@ -0,0 +1,34 @@ +// x2: key schedule +// x1: input +// x0: output +#include "_internal_s2n_bignum.h" + + S2N_BN_SYM_VISIBILITY_DIRECTIVE(aes_decrypt) + S2N_BN_SYM_PRIVACY_DIRECTIVE(aes_decrypt) + .text + .balign 4 + .arch armv8-a+crypto + +aes_decrypt: + ldr w6,[x2,#240] + ld1 {v0.16b},[x2],#16 + ld1 {v1.16b},[x2],#16 + ld1 {v6.16b},[x1] + sub w6,w6,#2 + +Loop_dec: + aesd v6.16b,v0.16b + aesimc v6.16b,v6.16b + ld1 {v0.4s},[x2],#16 + subs w6,w6,#2 + aesd v6.16b,v1.16b + aesimc v6.16b,v6.16b + ld1 {v1.4s},[x2],#16 + b.gt Loop_dec + + aesd v6.16b,v0.16b + aesimc v6.16b,v6.16b + ld1 {v0.4s},[x2] + aesd v6.16b,v1.16b + eor v6.16b,v6.16b,v0.16b + st1 {v6.4s},[x0] diff --git a/arm/tutorial/aes_encrypt.S b/arm/tutorial/aes_encrypt.S new file mode 100644 index 000000000..c2d977b77 --- /dev/null +++ b/arm/tutorial/aes_encrypt.S @@ -0,0 +1,34 @@ +// x2: key schedule +// x1: input +// x0: output +#include "_internal_s2n_bignum.h" + + S2N_BN_SYM_VISIBILITY_DIRECTIVE(aes_encrypt) + S2N_BN_SYM_PRIVACY_DIRECTIVE(aes_encrypt) + .text + .balign 4 + .arch armv8-a+crypto + +aes_encrypt: + ldr w6,[x2,#240] + ld1 {v0.16b},[x2],#16 + ld1 {v1.16b},[x2],#16 + ld1 {v6.16b},[x1] + sub w6,w6,#2 + +Loop_enc: + aese v6.16b,v0.16b + aesmc v6.16b,v6.16b + ld1 {v0.4s},[x2],#16 + subs w6,w6,#2 + aese v6.16b,v1.16b + aesmc v6.16b,v6.16b + ld1 {v1.4s},[x2],#16 + b.gt Loop_enc + + aese v6.16b,v0.16b + aesmc v6.16b,v6.16b + ld1 {v0.4s},[x2] + aese v6.16b,v1.16b + eor v6.16b,v6.16b,v0.16b + st1 {v6.4s},[x0] diff --git a/arm/tutorial/aes_encrypt_decrypt.ml b/arm/tutorial/aes_encrypt_decrypt.ml new file mode 100644 index 000000000..c9bbc5174 --- /dev/null +++ b/arm/tutorial/aes_encrypt_decrypt.ml @@ -0,0 +1,261 @@ +(* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0 + *) + +(****************************************************************************** + AES-256 encryption proof. +******************************************************************************) + +needs "arm/proofs/base.ml";; +needs "arm/proofs/utils/aes_encrypt_spec.ml";; + +(* The following program performs an AES-256 encryption: + - input: 128-bit block stored in memory at address in x1 + - output: 128-bit block to be stored in memory at address in x0 + - round keys: 15 128-bit values stored starting at address in x2, k0 to k14. + After the round keys, the number of rounds is stored + at offset 240 of address in x2. This number is 14 for AES-256 (see below) + w6 is the round counter. + 2 round keys are loaded in v0 and v1 before the loop and then in the loop and + the counter is decremented by 2 in each iteration. + + The instructions AESE and AESMC form one AES encryption round: + AESE: AESSubBytes(AESShiftRows(operand1 XOR operand2), // XOR = AddRoundKey + AESMC: AESMixColumns(operand) + The last round doesn't use AESMC, only AESE and XOR. + The output is stored at the end. + + In the specs, the first round key is used in AddRoundKey in the initialization + then 13 regular rounds, each ending with AddRoundKey, + then a last round that doesn't have MixColumns and ends with AddRoundKey + In the implementation, there are 14 rounds that start with AddRoundKey in AESE + and one last round (with no MixColumns) ending with AddRoundKey. +*) + +let aes256_encrypt_mc = define_assert_from_elf "aes256_encrypt_mc" "arm/tutorial/aes_encrypt.o" [ + 0xb940f046; (* arm_LDR W6 X2 (Immediate_Offset (word 240)) *) + 0x4cdf7040; (* arm_LDR Q0 X2 (Postimmediate_Offset (word 16)) *) + 0x4cdf7041; (* arm_LDR Q1 X2 (Postimmediate_Offset (word 16)) *) + 0x4c407026; (* arm_LDR Q6 X1 No_Offset *) + 0x510008c6; (* arm_SUB W6 W6 (rvalue (word 2)) *) + 0x4e284806; (* arm_AESE Q6 Q0 *) + 0x4e2868c6; (* arm_AESMC Q6 Q6 *) + 0x4cdf7840; (* arm_LDR Q0 X2 (Postimmediate_Offset (word 16)) *) + 0x710008c6; (* arm_SUBS W6 W6 (rvalue (word 2)) *) + 0x4e284826; (* arm_AESE Q6 Q1 *) + 0x4e2868c6; (* arm_AESMC Q6 Q6 *) + 0x4cdf7841; (* arm_LDR Q1 X2 (Postimmediate_Offset (word 16)) *) + 0x54ffff2c; (* arm_BGT (word 2097124) *) + 0x4e284806; (* arm_AESE Q6 Q0 *) + 0x4e2868c6; (* arm_AESMC Q6 Q6 *) + 0x4c407840; (* arm_LDR Q0 X2 No_Offset *) + 0x4e284826; (* arm_AESE Q6 Q1 *) + 0x6e201cc6; (* arm_EOR_VEC Q6 Q6 Q0 128 *) + 0x4c007806 (* arm_STR Q6 X0 No_Offset *) +];; + +(* +You can get the above OCaml list data structure from +First generating the by running at the command line under arm directory: + $ make tutorial/ +`print_literal_from_elf "arm/tutorial/"` or +`save_literal_from_elf "" ""`. +*) + +(* ARM_MK_EXEC_RULE decodes the byte sequence into an OCaml array of + theorems describing the instruction decoded at each PC (only when + it is multiple of 4). *) +let AES256_ENCRYPT_EXEC = ARM_MK_EXEC_RULE aes256_encrypt_mc;; + +let AES256_ENCRYPT_CORRECT = prove( + `!ciphertext plaintext key pt_in k0 k1 k2 k3 k4 k5 k6 k7 k8 k9 k10 k11 k12 k13 k14 pc. + nonoverlapping (word pc,LENGTH aes256_encrypt_mc) (ciphertext,16) + ==> ensures arm + // precondition + (\s. aligned_bytes_loaded s (word pc) aes256_encrypt_mc /\ + read PC s = word pc /\ + // uses the C ABI which puts the arguments in their order in registers x0 to x7. + // Here only 3 arguments are passed in. + C_ARGUMENTS [ciphertext; plaintext; key] s /\ + read(memory :> bytes128 plaintext) s = pt_in /\ + read(memory :> bytes32 (word_add key (word 240))) s = word 14 /\ + read(memory :> bytes128 key) s = k0 /\ + read(memory :> bytes128 (word_add key (word 16))) s = k1 /\ + read(memory :> bytes128 (word_add key (word 32))) s = k2 /\ + read(memory :> bytes128 (word_add key (word 48))) s = k3 /\ + read(memory :> bytes128 (word_add key (word 64))) s = k4 /\ + read(memory :> bytes128 (word_add key (word 80))) s = k5 /\ + read(memory :> bytes128 (word_add key (word 96))) s = k6 /\ + read(memory :> bytes128 (word_add key (word 112))) s = k7 /\ + read(memory :> bytes128 (word_add key (word 128))) s = k8 /\ + read(memory :> bytes128 (word_add key (word 144))) s = k9 /\ + read(memory :> bytes128 (word_add key (word 160))) s = k10 /\ + read(memory :> bytes128 (word_add key (word 176))) s = k11 /\ + read(memory :> bytes128 (word_add key (word 192))) s = k12 /\ + read(memory :> bytes128 (word_add key (word 208))) s = k13 /\ + read(memory :> bytes128 (word_add key (word 224))) s = k14 + ) + // postcondition + (\s. read PC s = word (pc + LENGTH aes256_encrypt_mc) /\ + read(memory :> bytes128 ciphertext) s = + aes256_encrypt pt_in + [k0; k1; k2; k3; k4; k5; k6; k7; k8; k9; k10; k11; k12; k13; k14] + ) + // Registers (and memory locations) that may change after execution + (MAYCHANGE [PC;X2;X6],, MAYCHANGE [Q0;Q1;Q6],, MAYCHANGE [events],, + MAYCHANGE SOME_FLAGS,, MAYCHANGE [memory :> bytes128 ciphertext])`, + + (* Convert C_ARGUMENTS to reading registers x0, x1, x2 and expand SOME_FLAGS *) + REWRITE_TAC[C_ARGUMENTS; SOME_FLAGS] THEN + + (* Find the length of the program using a Conversion *) + REWRITE_TAC [(REWRITE_CONV [aes256_encrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_encrypt_mc`] THEN + + (* Strips the outermost universal quantifier from the conclusion of a goal *) + REPEAT STRIP_TAC THEN + (* Start symbolic execution with state 's0' *) + ENSURES_INIT_TAC "s0" THEN + (* Symbolic execution *) + ARM_STEPS_TAC AES256_ENCRYPT_EXEC (1--6) THEN + ARM_STEPS_TAC AES256_ENCRYPT_EXEC (7--59) THEN + (* Returned; Finalize symbolic execution. *) + ENSURES_FINAL_STATE_TAC THEN + + (* Use ASM_REWRITE_TAC[] to rewrite the goal using equalities in assumptions. *) + ASM_REWRITE_TAC[] THEN + (* Use the specs to expand defintions *) + REWRITE_TAC [aes256_encrypt] THEN + + (* Replace the elements selection, EL, with the selected element + from the key round list. *) + REWRITE_TAC EL_15_128_CLAUSES THEN + + (* Expand definitions and evaluate `let` terms. *) + REWRITE_TAC [aes256_encrypt_round; aese; aesmc] THEN + CONV_TAC (TOP_DEPTH_CONV let_CONV) THEN + + (* Evaluate the logical expression on both sides as a gate circuit between bits. *) + BITBLAST_TAC + (* Alternatively, use the XOR symmetry *) + (* GEN_REWRITE_TAC LAND_CONV [WORD_XOR_SYM] THEN + REFL_TAC *) +);; + +(****************************************************************************** + AES-256 decryption proof. +******************************************************************************) + +needs "arm/proofs/utils/aes_decrypt_spec.ml";; + +(* The following program performs an AES-256 decryption, + with the following differences from encryption (see tutorial/aes_encrypt.ml): + + procedure EQINVCIPHER(in, Nr, dw) is the one used from the standard in order + to be able to use the same round keys in the same order as with encrypt. + + The instructions AESD and AESIMC form one AES decryption round: + AESD: AESInvSubBytes(AESInvShiftRows(operand1 XOR operand2), // XOR = AddRoundKey + AESIMC: AESInvMixColumns(operand) + The last round doesn't use AESIMC, only AESD and XOR. +*) + +let aes256_decrypt_mc = define_assert_from_elf "aes256_decrypt_mc" "arm/tutorial/aes_decrypt.o" +[ + 0xb940f046; (* arm_LDR W6 X2 (Immediate_Offset (word 240)) *) + 0x4cdf7040; (* arm_LDR Q0 X2 (Postimmediate_Offset (word 16)) *) + 0x4cdf7041; (* arm_LDR Q1 X2 (Postimmediate_Offset (word 16)) *) + 0x4c407026; (* arm_LDR Q6 X1 No_Offset *) + 0x510008c6; (* arm_SUB W6 W6 (rvalue (word 2)) *) + 0x4e285806; (* arm_AESD Q6 Q0 *) + 0x4e2878c6; (* arm_AESIMC Q6 Q6 *) + 0x4cdf7840; (* arm_LDR Q0 X2 (Postimmediate_Offset (word 16)) *) + 0x710008c6; (* arm_SUBS W6 W6 (rvalue (word 2)) *) + 0x4e285826; (* arm_AESD Q6 Q1 *) + 0x4e2878c6; (* arm_AESIMC Q6 Q6 *) + 0x4cdf7841; (* arm_LDR Q1 X2 (Postimmediate_Offset (word 16)) *) + 0x54ffff2c; (* arm_BGT (word 2097124) *) + 0x4e285806; (* arm_AESD Q6 Q0 *) + 0x4e2878c6; (* arm_AESIMC Q6 Q6 *) + 0x4c407840; (* arm_LDR Q0 X2 No_Offset *) + 0x4e285826; (* arm_AESD Q6 Q1 *) + 0x6e201cc6; (* arm_EOR_VEC Q6 Q6 Q0 128 *) + 0x4c007806 (* arm_STR Q6 X0 No_Offset *) +];; + +let AES256_DECRYPT_EXEC = ARM_MK_EXEC_RULE aes256_decrypt_mc;; + +let AES256_DECRYPT_CORRECT = prove( + `!plaintext ciphertext key ib k0 k1 k2 k3 k4 k5 k6 k7 k8 k9 k10 k11 k12 k13 k14 pc. + nonoverlapping (word pc,LENGTH aes256_decrypt_mc) (plaintext,16) + ==> ensures arm + // precondition + (\s. aligned_bytes_loaded s (word pc) aes256_decrypt_mc /\ + read PC s = word pc /\ + // uses the C ABI which puts the arguments in their order in registers x0 to x7. + // Here only 3 arguments are passed in. + C_ARGUMENTS [plaintext; ciphertext; key] s /\ + read(memory :> bytes128 ciphertext) s = ib /\ + read(memory :> bytes32 (word_add key (word 240))) s = word 14 /\ + read(memory :> bytes128 key) s = k0 /\ + read(memory :> bytes128 (word_add key (word 16))) s = k1 /\ + read(memory :> bytes128 (word_add key (word 32))) s = k2 /\ + read(memory :> bytes128 (word_add key (word 48))) s = k3 /\ + read(memory :> bytes128 (word_add key (word 64))) s = k4 /\ + read(memory :> bytes128 (word_add key (word 80))) s = k5 /\ + read(memory :> bytes128 (word_add key (word 96))) s = k6 /\ + read(memory :> bytes128 (word_add key (word 112))) s = k7 /\ + read(memory :> bytes128 (word_add key (word 128))) s = k8 /\ + read(memory :> bytes128 (word_add key (word 144))) s = k9 /\ + read(memory :> bytes128 (word_add key (word 160))) s = k10 /\ + read(memory :> bytes128 (word_add key (word 176))) s = k11 /\ + read(memory :> bytes128 (word_add key (word 192))) s = k12 /\ + read(memory :> bytes128 (word_add key (word 208))) s = k13 /\ + read(memory :> bytes128 (word_add key (word 224))) s = k14) + // postcondition + (\s. read PC s = word (pc + LENGTH aes256_decrypt_mc) /\ + read (memory :> bytes128 plaintext) s = + aes256_decrypt ib [k0; k1; k2; k3; k4; k5; k6; k7; k8; k9; k10; k11; k12; k13; k14] + ) + // Registers (and memory locations) that may change after execution + (MAYCHANGE [PC;X6;X2] ,, MAYCHANGE [Q0; Q1; Q6],, + MAYCHANGE [memory :> bytes128 plaintext],, + MAYCHANGE SOME_FLAGS,, MAYCHANGE [events])`, + + MAP_EVERY X_GEN_TAC + [`plaintext:int64`; `ciphertext:int64`; `key:int64`; + `ib:int128`; `k0:int128`; `k1:int128`; `k2:int128`; + `k3:int128`; `k4:int128`; `k5:int128`; `k6:int128`; + `k7:int128`; `k8:int128`; `k9:int128`; `k10:int128`; + `k11:int128`; `k12:int128`; `k13:int128`; `k14:int128`; `pc:num`] THEN + + (* Convert C_ARGUMENTS to reading registers x0, x1, x2 and expand SOME_FLAGS *) + REWRITE_TAC[C_ARGUMENTS; SOME_FLAGS] THEN + + (* Find the length of the program using a Conversion *) + REWRITE_TAC [(REWRITE_CONV [aes256_decrypt_mc] THENC LENGTH_CONV) `LENGTH aes256_decrypt_mc`] THEN + DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN + + (* Start symbolic execution with state 's0' *) + ENSURES_INIT_TAC "s0" THEN + (* Symbolic execution of all instructions *) + ARM_ACCSTEPS_TAC AES256_DECRYPT_EXEC [] (1--59) THEN + (* Returned; Finalize symbolic execution. *) + ENSURES_FINAL_STATE_TAC THEN + (* Use ASM_REWRITE_TAC[] to rewrite the goal using equalities in assumptions. *) + ASM_REWRITE_TAC[] THEN + + (* Use the specs to expand defintions *) + REWRITE_TAC [aes256_decrypt] THEN + + (* Replace the elements selection, EL, with the selected element + from the key round list. *) + REWRITE_TAC EL_15_128_CLAUSES THEN + + (* Expand definitions and evaluate `let` terms *) + REWRITE_TAC [aes256_decrypt_round] THEN + CONV_TAC(TOP_DEPTH_CONV let_CONV) THEN + REWRITE_TAC [aesd;aesimc] THEN + GEN_REWRITE_TAC LAND_CONV [WORD_XOR_SYM] THEN + REFL_TAC +);; diff --git a/benchmarks/benchmark.c b/benchmarks/benchmark.c index ae83eb5ab..b7df4812c 100644 --- a/benchmarks/benchmark.c +++ b/benchmarks/benchmark.c @@ -49,6 +49,10 @@ static uint64_t bb[16][BUFFERSIZE]; static uint64_t bigbuff[100000]; +// AES keys for XTS mode testing +static s2n_bignum_AES_KEY aes_key1, aes_key2; +static uint8_t aes_iv[16]; + // Source of random 64-bit numbers with bit density // 0 = all zeros, 32 = "average", 64 = all ones // Then a generic one with the density itself randomized @@ -1118,6 +1122,20 @@ void call_sha3_keccak2_f1600_alt(void) {} void call_sha3_keccak4_f1600_alt(void) {} void call_sha3_keccak4_f1600_alt2(void) {} +void call_aes_xts_encrypt_16(void) {} +void call_aes_xts_encrypt_32(void) {} +void call_aes_xts_encrypt_64(void) {} +void call_aes_xts_encrypt_128(void) {} +void call_aes_xts_encrypt_256(void) {} +void call_aes_xts_encrypt_512(void) {} + +void call_aes_xts_decrypt_16(void) {} +void call_aes_xts_decrypt_32(void) {} +void call_aes_xts_decrypt_64(void) {} +void call_aes_xts_decrypt_128(void) {} +void call_aes_xts_decrypt_256(void) {} +void call_aes_xts_decrypt_512(void) {} + #else void call_mldsa_intt(void) {} @@ -1147,12 +1165,60 @@ void call_sha3_keccak4_f1600_alt2(void) repeat(sha3_keccak4_f1600_alt2(b0,b1)) void call_mlkem_frombytes(void) {} void call_mlkem_unpack(void) {} + +// Helper function for AES XTS encrypt with parameterized length +static void aes_xts_encrypt_helper(size_t len) +{ + int j; + for (j = 0; j < 30; ++j) { + aes_key1.rd_key[j] = b1[j % BUFFERSIZE]; + aes_key2.rd_key[j] = b2[j % BUFFERSIZE]; + } + aes_key1.rounds = 14; // AES-256 + aes_key2.rounds = 14; + for (j = 0; j < 16; ++j) aes_iv[j] = (uint8_t)(b3[j] & 0xFF); + + aes_xts_encrypt((uint8_t*)b0, (uint8_t*)b1, len, &aes_key1, &aes_key2, aes_iv); +} + +// AES XTS encrypt wrapper functions for different block sizes +void call_aes_xts_encrypt_16(void) { repeat(aes_xts_encrypt_helper(16)); } +void call_aes_xts_encrypt_32(void) { repeat(aes_xts_encrypt_helper(32)); } +void call_aes_xts_encrypt_64(void) { repeat(aes_xts_encrypt_helper(64)); } +void call_aes_xts_encrypt_128(void) { repeat(aes_xts_encrypt_helper(128)); } +void call_aes_xts_encrypt_256(void) { repeat(aes_xts_encrypt_helper(256)); } +void call_aes_xts_encrypt_512(void) { repeatfewer(10,aes_xts_encrypt_helper(512)); } + +// Helper function for AES XTS decrypt with parameterized length +static void aes_xts_decrypt_helper(size_t len) +{ + int j; + for (j = 0; j < 30; ++j) { + aes_key1.rd_key[j] = b1[j % BUFFERSIZE]; + aes_key2.rd_key[j] = b2[j % BUFFERSIZE]; + } + aes_key1.rounds = 14; // AES-256 + aes_key2.rounds = 14; + for (j = 0; j < 16; ++j) aes_iv[j] = (uint8_t)(b3[j] & 0xFF); + + aes_xts_decrypt((uint8_t*)b0, (uint8_t*)b1, len, &aes_key1, &aes_key2, aes_iv); +} + +// AES XTS decrypt wrapper functions for different block sizes +void call_aes_xts_decrypt_16(void) { repeat(aes_xts_decrypt_helper(16)); } +void call_aes_xts_decrypt_32(void) { repeat(aes_xts_decrypt_helper(32)); } +void call_aes_xts_decrypt_64(void) { repeat(aes_xts_decrypt_helper(64)); } +void call_aes_xts_decrypt_128(void) { repeat(aes_xts_decrypt_helper(128)); } +void call_aes_xts_decrypt_256(void) { repeat(aes_xts_decrypt_helper(256)); } +void call_aes_xts_decrypt_512(void) { repeatfewer(10,aes_xts_decrypt_helper(512)); } + #endif int main(int argc, char *argv[]) { int bmi = get_arch_name() == ARCH_AARCH64 || supports_bmi2_and_adx(); int sha3 = get_arch_name() == ARCH_AARCH64 && supports_arm_sha3(); + int aes = get_arch_name() == ARCH_AARCH64 && supports_arm_aes(); int all = 1; int arm = get_arch_name() == ARCH_AARCH64; char *argending; @@ -1607,6 +1673,18 @@ int main(int argc, char *argv[]) timingtest(all,"word_negmodinv",call_word_negmodinv); timingtest(all,"word_popcount",call_word_popcount); timingtest(all,"word_recip",call_word_recip); + timingtest(aes,"aes_xts_encrypt (16 bytes)",call_aes_xts_encrypt_16); + timingtest(aes,"aes_xts_encrypt (32 bytes)",call_aes_xts_encrypt_32); + timingtest(aes,"aes_xts_encrypt (64 bytes)",call_aes_xts_encrypt_64); + timingtest(aes,"aes_xts_encrypt (128 bytes)",call_aes_xts_encrypt_128); + timingtest(aes,"aes_xts_encrypt (256 bytes)",call_aes_xts_encrypt_256); + timingtest(aes,"aes_xts_encrypt (512 bytes)",call_aes_xts_encrypt_512); + timingtest(aes,"aes_xts_decrypt (16 bytes)",call_aes_xts_decrypt_16); + timingtest(aes,"aes_xts_decrypt (32 bytes)",call_aes_xts_decrypt_32); + timingtest(aes,"aes_xts_decrypt (64 bytes)",call_aes_xts_decrypt_64); + timingtest(aes,"aes_xts_decrypt (128 bytes)",call_aes_xts_decrypt_128); + timingtest(aes,"aes_xts_decrypt (256 bytes)",call_aes_xts_decrypt_256); + timingtest(aes,"aes_xts_decrypt (512 bytes)",call_aes_xts_decrypt_512); // Summarize performance in arithmetic and geometric means diff --git a/common/consttime.ml b/common/consttime.ml index e5a315658..fb856f19f 100644 --- a/common/consttime.ml +++ b/common/consttime.ml @@ -365,7 +365,7 @@ let DISCHARGE_MEMACCESS_INBOUNDS_TAC = FAIL_TAC ("DISCHARGE_MEMACCESS_INBOUNDS_TAC could not identify the pattern. " ^ "Please check whether the event list in assumption matches the event " ^ - "list in the conclusion")));; + "list in the conclusion. setting safety_print_log := true might give more clue.")));; let mk_freshvar = let n = ref 0 in @@ -979,10 +979,18 @@ let FULL_UNIFY_F_EVENTS_TAC:tactic = end end) (asl,w)) ORELSE CANONICALIZE_UNIFY_F_EVENTS_TAC;; -(* The input goal: 'exists e2. ....' *) -let DISCHARGE_SAFETY_PROPERTY_TAC = +(* The input goal: 'exists e2. ....' + If FULL_UNIFY_F_EVENTS_TAC raises a failure because unseen variable x is + inside the goal of `... x ... = f_events ...`, provide the assumption + `x = ...` that can be used to expand x. +*) +let DISCHARGE_SAFETY_PROPERTY_TAC + ?(abbrevs_unfold_before_f_events_tac=[]) = SAFE_META_EXISTS_TAC allowed_vars_e THEN CONJ_TAC THENL [ EXISTS_E2_TAC allowed_vars_e; ALL_TAC ] THEN - CONJ_TAC THENL [ FULL_UNIFY_F_EVENTS_TAC; ALL_TAC ] THEN + CONJ_TAC THENL [ + MAP_EVERY (fun t -> UNDISCH_THEN t (SUBST_ALL_TAC o GSYM)) + abbrevs_unfold_before_f_events_tac THEN + FULL_UNIFY_F_EVENTS_TAC; ALL_TAC ] THEN (* Prove memaccess_inbounds predicates *) DISCHARGE_MEMACCESS_INBOUNDS_TAC;; diff --git a/include/s2n-bignum-c89.h b/include/s2n-bignum-c89.h index 2ddf0aac3..25ff8e2e2 100644 --- a/include/s2n-bignum-c89.h +++ b/include/s2n-bignum-c89.h @@ -25,6 +25,22 @@ * ---------------------------------------------------------------------------- */ +struct s2n_bignum_aes_key_st { + uint64_t rd_key[30]; + int rounds; +}; +typedef struct s2n_bignum_aes_key_st s2n_bignum_AES_KEY; + +/* AES_XTS_DECRYPT (256-bit) */ +/* Inputs in[length], length, key1[244], key2[244], iv[16]; output out[length] */ +extern void aes_xts_decrypt(const uint8_t *in, uint8_t *out, size_t length, + const s2n_bignum_AES_KEY *key1, const s2n_bignum_AES_KEY *key2, const uint8_t iv[16]); + +/* AES_XTS_ENCRYPT (256-bit) */ +/* Inputs in[length], length, key1[244], key2[244], iv[16]; output out[length] */ +extern void aes_xts_encrypt(const uint8_t *in, uint8_t *out, size_t length, + const s2n_bignum_AES_KEY *key1, const s2n_bignum_AES_KEY *key2, const uint8_t iv[16]); + /* Add, z := x + y */ /* Inputs x[m], y[n]; outputs function return (carry-out) and z[p] */ extern uint64_t bignum_add (uint64_t p, uint64_t *z, uint64_t m, const uint64_t *x, uint64_t n, const uint64_t *y); diff --git a/include/s2n-bignum.h b/include/s2n-bignum.h index fb2f41818..a8ca592e3 100644 --- a/include/s2n-bignum.h +++ b/include/s2n-bignum.h @@ -30,6 +30,22 @@ #define S2N_BIGNUM_STATIC static #endif +struct s2n_bignum_aes_key_st { + uint64_t rd_key[30]; + int rounds; +}; +typedef struct s2n_bignum_aes_key_st s2n_bignum_AES_KEY; + +// AES_XTS_DECRYPT (256-bit) +// Inputs in[length], length, key1[244], key2[244], iv[16]; output out[length] +extern void aes_xts_decrypt(const uint8_t *in, uint8_t *out, size_t length, + const s2n_bignum_AES_KEY *key1, const s2n_bignum_AES_KEY *key2, const uint8_t iv[S2N_BIGNUM_STATIC 16]); + +// AES_XTS_ENCRYPT (256-bit) +// Inputs in[length], length, key1[244], key2[244], iv[16]; output out[length] +extern void aes_xts_encrypt(const uint8_t *in, uint8_t *out, size_t length, + const s2n_bignum_AES_KEY *key1, const s2n_bignum_AES_KEY *key2, const uint8_t iv[S2N_BIGNUM_STATIC 16]); + // Add, z := x + y // Inputs x[m], y[n]; outputs function return (carry-out) and z[p] extern uint64_t bignum_add (uint64_t p, uint64_t *z, uint64_t m, const uint64_t *x, uint64_t n, const uint64_t *y); diff --git a/tests/arch.h b/tests/arch.h index 18d772933..e97d13d70 100644 --- a/tests/arch.h +++ b/tests/arch.h @@ -27,6 +27,11 @@ int supports_arm_sha3(void) return 0; } +int supports_arm_aes(void) +{ // Not an ARM machine at all + return 0; +} + #else int supports_bmi2_and_adx(void) @@ -68,6 +73,43 @@ int supports_bmi2_and_adx(void) return 0; #endif } + +#endif + +#if __linux__ + #include + #include + int supports_arm_aes(void) + { + long hwcaps = getauxval(AT_HWCAP); + return (hwcaps & HWCAP_AES) != 0; + } + +#elif __FreeBSD__ || __OpenBSD__ + + #include + #include + int supports_arm_aes(void) + { + unsigned long hwcaps; + if (elf_aux_info(AT_HWCAP, &hwcaps, sizeof(hwcaps)) != 0) + { printf("Warning: Failed to read AT_HWCAP\n"); + return 0; + } + return (hwcaps & HWCAP_AES) != 0; + } + +#else + + int supports_arm_aes(void) + { + #if __ARM_FEATURE_AES + return 1; + #else + return 0; + #endif + } + #endif enum arch_name get_arch_name() diff --git a/tests/known_value_tests_xts_decrypt.h b/tests/known_value_tests_xts_decrypt.h new file mode 100644 index 000000000..0a5e01243 --- /dev/null +++ b/tests/known_value_tests_xts_decrypt.h @@ -0,0 +1,362 @@ +// key1 = fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0 +// key2 = bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a0 +// iv = 9a785634120000000000000000000000 +// roundkey1 = +// 0xfcfdfeff 0xf8f9fafb 0xf4f5f6f7 0xf0f1f2f3 +// 0xecedeeef 0xe8e9eaeb 0xe4e5e6e7 0xe0e1e2e3 +// 0xed1c0666 0x15e5fc9d 0xe1100a6a 0x11e1f899 +// 0x6e15af01 0x86fc45ea 0x6219a30d 0x82f841ee +// 0xc50f47e7 0xd0eabb7a 0x31fab110 0x201b4989 +// 0xd9ba94a6 0x5f46d14c 0x3d5f7241 0xbfa733af +// 0xbc071b20 0x6ceda05a 0x5d17114a 0x7d0c58c3 +// 0x2644fe88 0x79022fc4 0x445d5d85 0xfbfa6e2a +// 0x590836b7 0x35e596ed 0x68f287a7 0x15fedf64 +// 0x7fff60cb 0x6fd4f0f 0x42a0128a 0xb95a7ca0 +// 0xb95e88b7 0x8cbb1e5a 0xe44999fd 0xf1b74699 +// 0xde563a25 0xd8ab752a 0x9a0b67a0 0x23511b00 +// 0xda785938 0x56c34762 0xb28ade9f 0x433d9806 +// 0xc4717c4a 0x1cda0960 0x86d16ec0 0xa58075c0 +// 0x607e94e5 0x36bdd387 0x84370d18 0xc70a951e +// roundkey2 = +// 0xbcbdbebf 0xb8b9babb 0xb4b5b6b7 0xb0b1b2b3 +// 0xacadaeaf 0xa8a9aaab 0xa4a5a6a7 0xa0a1a2a3 +// 0xb65d8c84 0xee4363f 0xba518088 0xae0323b +// 0xcb4c8d4d 0x63e527e6 0xc7408141 0x67e123e2 +// 0x2ed874a0 0x203c429f 0x9a6dc217 0x908df02c +// 0xab11013c 0xc8f426da 0xfb4a79b 0x68558479 +// 0x989d88fb 0xb8a1ca64 0x22cc0873 0xb241f85f +// 0x9c9240f3 0x54666629 0x5bd2c1b2 0x338745cb +// 0x875e9f9d 0x3fff55f9 0x1d335d8a 0xaf72a5d5 +// 0xe5d246f0 0xb1b420d9 0xea66e16b 0xd9e1a4a0 +// 0x676b67c4 0x5894323d 0x45a76fb7 0xead5ca62 +// 0x62d1325a 0xd3651283 0x3903f3e8 0xe0e25748 +// 0x358affbf 0x6d1ecd82 0x28b9a235 0xc26c6857 +// 0x47817701 0x94e46582 0xade7966a 0x4d05c122 +// 0xa6699487 0xcb775905 0xe3cefb30 0x21a29367 +key1->rd_key[0]=0x36bdd387607e94e5; key1->rd_key[1]=0xc70a951e84370d18; +key1->rd_key[2]=0x103340cce21b473d; key1->rd_key[3]=0x7ead95d6f74bf6b3; +key1->rd_key[4]=0x3d0757ddbebda060; key1->rd_key[5]=0x298c296cdf3241d5; +key1->rd_key[6]=0xf22807f1cdc91c8f; key1->rd_key[7]=0x89e66365e778b67f; +key1->rd_key[8]=0x83baf7bd2340b902; key1->rd_key[9]=0xf6be68b9e2351608; +key1->rd_key[10]=0x3fe11b7e185c513e; key1->rd_key[11]=0x6e9ed51a1550b18e; +key1->rd_key[12]=0xa0fa4ebf336ae76e; key1->rd_key[13]=0x148b7eb1618fe1b5; +key1->rd_key[14]=0x27bd4a40982968cd; key1->rd_key[15]=0x7bce64942ab1aaf0; +key1->rd_key[16]=0x9390a9d1d91a6526; key1->rd_key[17]=0x75049f04c175af0a; +key1->rd_key[18]=0xbf94228de7e3085d; key1->rd_key[19]=0x517fce640d0ce0b0; +key1->rd_key[20]=0x4a8accf7a81afe26; key1->rd_key[21]=0xb471300e52e506db; +key1->rd_key[22]=0x58772ad0be94ce31; key1->rd_key[23]=0x5c732ed4b298c23d; +key1->rd_key[24]=0xe29032d11463c620; key1->rd_key[25]=0xe69436d5186fca2c; +key1->rd_key[26]=0xe6e3e4e1e2e7e0e5; key1->rd_key[27]=0xeeebece9eaefe8ed; +key1->rd_key[28]=0xf8f9fafbfcfdfeff; key1->rd_key[29]=0xf0f1f2f3f4f5f6f7; + +key2->rd_key[0]=0xb8b9babbbcbdbebf; key2->rd_key[1]=0xb0b1b2b3b4b5b6b7; +key2->rd_key[2]=0xa8a9aaabacadaeaf; key2->rd_key[3]=0xa0a1a2a3a4a5a6a7; +key2->rd_key[4]=0x0ee4363fb65d8c84; key2->rd_key[5]=0x0ae0323bba518088; +key2->rd_key[6]=0x63e527e6cb4c8d4d; key2->rd_key[7]=0x67e123e2c7408141; +key2->rd_key[8]=0x203c429f2ed874a0; key2->rd_key[9]=0x908df02c9a6dc217; +key2->rd_key[10]=0xc8f426daab11013c; key2->rd_key[11]=0x685584790fb4a79b; +key2->rd_key[12]=0xb8a1ca64989d88fb; key2->rd_key[13]=0xb241f85f22cc0873; +key2->rd_key[14]=0x546666299c9240f3; key2->rd_key[15]=0x338745cb5bd2c1b2; +key2->rd_key[16]=0x3fff55f9875e9f9d; key2->rd_key[17]=0xaf72a5d51d335d8a; +key2->rd_key[18]=0xb1b420d9e5d246f0; key2->rd_key[19]=0xd9e1a4a0ea66e16b; +key2->rd_key[20]=0x5894323d676b67c4; key2->rd_key[21]=0xead5ca6245a76fb7; +key2->rd_key[22]=0xd365128362d1325a; key2->rd_key[23]=0xe0e257483903f3e8; +key2->rd_key[24]=0x6d1ecd82358affbf; key2->rd_key[25]=0xc26c685728b9a235; +key2->rd_key[26]=0x94e4658247817701; key2->rd_key[27]=0x4d05c122ade7966a; +key2->rd_key[28]=0xcb775905a6699487; key2->rd_key[29]=0x21a29367e3cefb30; + +key1->rounds=13; +key2->rounds=13; + +iv[0]=0x9a;iv[1]=0x78;iv[2]=0x56;iv[3]=0x34; +iv[4]=0x12;iv[5]=0x00;iv[6]=0x00;iv[7]=0x00; +iv[8]=0x00;iv[9]=0x00;iv[10]=0x00;iv[11]=0x00; +iv[12]=0x00;iv[13]=0x00;iv[14]=0x00;iv[15]=0x00; + +// 1block +len = 16; +ASSIGNHEX(res, "000102030405060708090a0b0c0d0e0f", len); +ASSIGNHEX(in, "c30ca8f2ed57307edc87e544867ac888", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 1block + 1byte = 17 bytes +len = 17; +ASSIGNHEX(res, "000102030405060708090a0b0c0d0e0f10", len); +ASSIGNHEX(in, "7f117752cc598a8b0d81d88af9f9bec8c3", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 1block + 6byte = 22 bytes +len = 22; +ASSIGNHEX(res, "000102030405060708090a0b0c0d0e0f101112131415", len); +ASSIGNHEX(in, "75e8188bcce59ada939f57de2cb9a489c30ca8f2ed57", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 1bock + 15bytes = 31 bytes +len = 31; +ASSIGNHEX(res, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e", len); +ASSIGNHEX(in, "581ea1fee5516ad432ddebe75fd27c6fc30ca8f2ed57307edc87e544867ac8", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 3 blocks + 3 bytes +len = 51; +ASSIGNHEX(res, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132", len); +ASSIGNHEX(in, "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "bea47768aa25376e924cce6a102ca2e4e1c241", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 4 blocks +len = 64; +ASSIGNHEX(res, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", len); +ASSIGNHEX(in, "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 4blocks + 10 bytes = 74 bytes +len = 74; +ASSIGNHEX(res, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "40414243444546474849", len); +ASSIGNHEX(in, "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b0f451eb8847b98d48b1407f64a4f9ee3" + "474e1fd14311edb95219", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 5 blocks +len = 80; +ASSIGNHEX(res, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f", len); +ASSIGNHEX(in, "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 5blocks + 7bytes = 87 bytes +len = 87; +ASSIGNHEX(res, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f50515253545556", len); +ASSIGNHEX(in, "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "a436b967e79bb8e8e4c29d1099fe1bbf8917567652e9b4", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 6 blocks +len = 96; +ASSIGNHEX(res, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", len); +ASSIGNHEX(in, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 6blocks + 4bytes = 100 bytes +len = 100; +ASSIGNHEX(res, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "60616263", len); +ASSIGNHEX(in, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1aad32ff4d83b0af3f6a176025bd1321b" + "ffe2f16c", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 8 blocks +len = 128; +ASSIGNHEX(res, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f", len); +ASSIGNHEX(in, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 8blocks + 6 bytes = 134 bytes +len = 134; +ASSIGNHEX(res, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485", len); +ASSIGNHEX(in, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1be0ad32884698e15420e52c96b698bba1" + "ce3d9a8750b8", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 9 blocks = 144 bytes +len = 144; +ASSIGNHEX(res, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f", len); +ASSIGNHEX(in, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04" + "e11b6adce343e1f38c6a879463c080d7", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 9blocks + 14bytes = 158bytes +len = 158; +ASSIGNHEX(res, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d", len); +ASSIGNHEX(in, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04" + "a5da920d96beb388ade417027054dbd0e11b6adce343e1f38c6a879463c0", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 10blocks = 160bytes +len = 160; +ASSIGNHEX(res, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", len); +ASSIGNHEX(in, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04" + "e11b6adce343e1f38c6a879463c080d74a72a90b1e6fe46b7bc95a929f79947e", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 10blocks + 5bytes = 165bytes +len = 165; +ASSIGNHEX(res, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4", len); +ASSIGNHEX(in, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04" + "e11b6adce343e1f38c6a879463c080d7254c4d65cf40e04934108bcde6bda824" + "4a72a90b1e", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 11 blocks = 176 bytes +len = 176; +ASSIGNHEX(res, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", len); +ASSIGNHEX(in, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04" + "e11b6adce343e1f38c6a879463c080d74a72a90b1e6fe46b7bc95a929f79947e" + "ae8cc61cbb5f8cbd0c6f052e95ed6539", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 11 blocks + 9 bytes = 185bytes +len = 185; +ASSIGNHEX(res, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8", len); +ASSIGNHEX(in, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04" + "e11b6adce343e1f38c6a879463c080d74a72a90b1e6fe46b7bc95a929f79947e" + "3ed782ad26e98e07f14d47f3c2a8e92aae8cc61cbb5f8cbd0c", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 14 blocks +len = 224; +ASSIGNHEX(res, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf", len); +ASSIGNHEX(in, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04" + "e11b6adce343e1f38c6a879463c080d74a72a90b1e6fe46b7bc95a929f79947e" + "ae8cc61cbb5f8cbd0c6f052e95ed65399009f56148fc07d88c8e0113d7eafb1f" + "ea39991882130ee45e95a3c6bc508f09c990add0cd3f1ca3403c096f9277e785", len); +ASSIGNZERO(out, len); +aes_xts_decrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); diff --git a/tests/known_value_tests_xts_encrypt.h b/tests/known_value_tests_xts_encrypt.h new file mode 100644 index 000000000..d22f74ad7 --- /dev/null +++ b/tests/known_value_tests_xts_encrypt.h @@ -0,0 +1,362 @@ +// key1 = fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0 +// key2 = bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a0 +// iv = 9a785634120000000000000000000000 +// roundkey1 = +// 0xfcfdfeff 0xf8f9fafb 0xf4f5f6f7 0xf0f1f2f3 +// 0xecedeeef 0xe8e9eaeb 0xe4e5e6e7 0xe0e1e2e3 +// 0xed1c0666 0x15e5fc9d 0xe1100a6a 0x11e1f899 +// 0x6e15af01 0x86fc45ea 0x6219a30d 0x82f841ee +// 0xc50f47e7 0xd0eabb7a 0x31fab110 0x201b4989 +// 0xd9ba94a6 0x5f46d14c 0x3d5f7241 0xbfa733af +// 0xbc071b20 0x6ceda05a 0x5d17114a 0x7d0c58c3 +// 0x2644fe88 0x79022fc4 0x445d5d85 0xfbfa6e2a +// 0x590836b7 0x35e596ed 0x68f287a7 0x15fedf64 +// 0x7fff60cb 0x6fd4f0f 0x42a0128a 0xb95a7ca0 +// 0xb95e88b7 0x8cbb1e5a 0xe44999fd 0xf1b74699 +// 0xde563a25 0xd8ab752a 0x9a0b67a0 0x23511b00 +// 0xda785938 0x56c34762 0xb28ade9f 0x433d9806 +// 0xc4717c4a 0x1cda0960 0x86d16ec0 0xa58075c0 +// 0x607e94e5 0x36bdd387 0x84370d18 0xc70a951e +// roundkey2 = +// 0xbcbdbebf 0xb8b9babb 0xb4b5b6b7 0xb0b1b2b3 +// 0xacadaeaf 0xa8a9aaab 0xa4a5a6a7 0xa0a1a2a3 +// 0xb65d8c84 0xee4363f 0xba518088 0xae0323b +// 0xcb4c8d4d 0x63e527e6 0xc7408141 0x67e123e2 +// 0x2ed874a0 0x203c429f 0x9a6dc217 0x908df02c +// 0xab11013c 0xc8f426da 0xfb4a79b 0x68558479 +// 0x989d88fb 0xb8a1ca64 0x22cc0873 0xb241f85f +// 0x9c9240f3 0x54666629 0x5bd2c1b2 0x338745cb +// 0x875e9f9d 0x3fff55f9 0x1d335d8a 0xaf72a5d5 +// 0xe5d246f0 0xb1b420d9 0xea66e16b 0xd9e1a4a0 +// 0x676b67c4 0x5894323d 0x45a76fb7 0xead5ca62 +// 0x62d1325a 0xd3651283 0x3903f3e8 0xe0e25748 +// 0x358affbf 0x6d1ecd82 0x28b9a235 0xc26c6857 +// 0x47817701 0x94e46582 0xade7966a 0x4d05c122 +// 0xa6699487 0xcb775905 0xe3cefb30 0x21a29367 +key1->rd_key[0]=0xf8f9fafbfcfdfeff; key1->rd_key[1]=0xf0f1f2f3f4f5f6f7; +key1->rd_key[2]=0xe8e9eaebecedeeef; key1->rd_key[3]=0xe0e1e2e3e4e5e6e7; +key1->rd_key[4]=0x15e5fc9ded1c0666; key1->rd_key[5]=0x11e1f899e1100a6a; +key1->rd_key[6]=0x86fc45ea6e15af01; key1->rd_key[7]=0x82f841ee6219a30d; +key1->rd_key[8]=0xd0eabb7ac50f47e7; key1->rd_key[9]=0x201b498931fab110; +key1->rd_key[10]=0x5f46d14cd9ba94a6; key1->rd_key[11]=0xbfa733af3d5f7241; +key1->rd_key[12]=0x6ceda05abc071b20; key1->rd_key[13]=0x7d0c58c35d17114a; +key1->rd_key[14]=0x79022fc42644fe88; key1->rd_key[15]=0xfbfa6e2a445d5d85; +key1->rd_key[16]=0x35e596ed590836b7; key1->rd_key[17]=0x15fedf6468f287a7; +key1->rd_key[18]=0x06fd4f0f7fff60cb; key1->rd_key[19]=0xb95a7ca042a0128a; +key1->rd_key[20]=0x8cbb1e5ab95e88b7; key1->rd_key[21]=0xf1b74699e44999fd; +key1->rd_key[22]=0xd8ab752ade563a25; key1->rd_key[23]=0x23511b009a0b67a0; +key1->rd_key[24]=0x56c34762da785938; key1->rd_key[25]=0x433d9806b28ade9f; +key1->rd_key[26]=0x1cda0960c4717c4a; key1->rd_key[27]=0xa58075c086d16ec0; +key1->rd_key[28]=0x36bdd387607e94e5; key1->rd_key[29]=0xc70a951e84370d18; + +key2->rd_key[0]=0xb8b9babbbcbdbebf; key2->rd_key[1]=0xb0b1b2b3b4b5b6b7; +key2->rd_key[2]=0xa8a9aaabacadaeaf; key2->rd_key[3]=0xa0a1a2a3a4a5a6a7; +key2->rd_key[4]=0x0ee4363fb65d8c84; key2->rd_key[5]=0x0ae0323bba518088; +key2->rd_key[6]=0x63e527e6cb4c8d4d; key2->rd_key[7]=0x67e123e2c7408141; +key2->rd_key[8]=0x203c429f2ed874a0; key2->rd_key[9]=0x908df02c9a6dc217; +key2->rd_key[10]=0xc8f426daab11013c; key2->rd_key[11]=0x685584790fb4a79b; +key2->rd_key[12]=0xb8a1ca64989d88fb; key2->rd_key[13]=0xb241f85f22cc0873; +key2->rd_key[14]=0x546666299c9240f3; key2->rd_key[15]=0x338745cb5bd2c1b2; +key2->rd_key[16]=0x3fff55f9875e9f9d; key2->rd_key[17]=0xaf72a5d51d335d8a; +key2->rd_key[18]=0xb1b420d9e5d246f0; key2->rd_key[19]=0xd9e1a4a0ea66e16b; +key2->rd_key[20]=0x5894323d676b67c4; key2->rd_key[21]=0xead5ca6245a76fb7; +key2->rd_key[22]=0xd365128362d1325a; key2->rd_key[23]=0xe0e257483903f3e8; +key2->rd_key[24]=0x6d1ecd82358affbf; key2->rd_key[25]=0xc26c685728b9a235; +key2->rd_key[26]=0x94e4658247817701; key2->rd_key[27]=0x4d05c122ade7966a; +key2->rd_key[28]=0xcb775905a6699487; key2->rd_key[29]=0x21a29367e3cefb30; + +key1->rounds=13; +key2->rounds=13; + +iv[0]=0x9a;iv[1]=0x78;iv[2]=0x56;iv[3]=0x34; +iv[4]=0x12;iv[5]=0x00;iv[6]=0x00;iv[7]=0x00; +iv[8]=0x00;iv[9]=0x00;iv[10]=0x00;iv[11]=0x00; +iv[12]=0x00;iv[13]=0x00;iv[14]=0x00;iv[15]=0x00; + +// 1block +len = 16; +ASSIGNHEX(in, "000102030405060708090a0b0c0d0e0f", len); +ASSIGNHEX(res, "c30ca8f2ed57307edc87e544867ac888", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 1block + 1byte = 17 bytes +len = 17; +ASSIGNHEX(in, "000102030405060708090a0b0c0d0e0f10", len); +ASSIGNHEX(res, "7f117752cc598a8b0d81d88af9f9bec8c3", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 1block + 6byte = 22 bytes +len = 22; +ASSIGNHEX(in, "000102030405060708090a0b0c0d0e0f101112131415", len); +ASSIGNHEX(res, "75e8188bcce59ada939f57de2cb9a489c30ca8f2ed57", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 1bock + 15bytes = 31 bytes +len = 31; +ASSIGNHEX(in, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e", len); +ASSIGNHEX(res, "581ea1fee5516ad432ddebe75fd27c6fc30ca8f2ed57307edc87e544867ac8", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 3 blocks + 3 bytes +len = 51; +ASSIGNHEX(in, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132", len); +ASSIGNHEX(res, "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "bea47768aa25376e924cce6a102ca2e4e1c241", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 4 blocks +len = 64; +ASSIGNHEX(in, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", len); +ASSIGNHEX(res, "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 4blocks + 10 bytes = 74 bytes +len = 74; +ASSIGNHEX(in, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "40414243444546474849", len); +ASSIGNHEX(res, "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b0f451eb8847b98d48b1407f64a4f9ee3" + "474e1fd14311edb95219", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 5 blocks +len = 80; +ASSIGNHEX(in, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f", len); +ASSIGNHEX(res, "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 5blocks + 7bytes = 87 bytes +len = 87; +ASSIGNHEX(in, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f50515253545556", len); +ASSIGNHEX(res, "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "a436b967e79bb8e8e4c29d1099fe1bbf8917567652e9b4", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 6 blocks +len = 96; +ASSIGNHEX(in, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", len); +ASSIGNHEX(res, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 6blocks + 4bytes = 100 bytes +len = 100; +ASSIGNHEX(in, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "60616263", len); +ASSIGNHEX(res, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1aad32ff4d83b0af3f6a176025bd1321b" + "ffe2f16c", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 8 blocks +len = 128; +ASSIGNHEX(in, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f", len); +ASSIGNHEX(res, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 8blocks + 6 bytes = 134 bytes +len = 134; +ASSIGNHEX(in, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485", len); +ASSIGNHEX(res, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1be0ad32884698e15420e52c96b698bba1" + "ce3d9a8750b8", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 9 blocks = 144 bytes +len = 144; +ASSIGNHEX(in, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f", len); +ASSIGNHEX(res, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04" + "e11b6adce343e1f38c6a879463c080d7", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 9blocks + 14bytes = 158bytes +len = 158; +ASSIGNHEX(in, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d", len); +ASSIGNHEX(res, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04" + "a5da920d96beb388ade417027054dbd0e11b6adce343e1f38c6a879463c0", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 10blocks = 160bytes +len = 160; +ASSIGNHEX(in, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", len); +ASSIGNHEX(res, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04" + "e11b6adce343e1f38c6a879463c080d74a72a90b1e6fe46b7bc95a929f79947e", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 10blocks + 5bytes = 165bytes +len = 165; +ASSIGNHEX(in, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4", len); +ASSIGNHEX(res, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04" + "e11b6adce343e1f38c6a879463c080d7254c4d65cf40e04934108bcde6bda824" + "4a72a90b1e", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 11 blocks = 176 bytes +len = 176; +ASSIGNHEX(in, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", len); +ASSIGNHEX(res, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04" + "e11b6adce343e1f38c6a879463c080d74a72a90b1e6fe46b7bc95a929f79947e" + "ae8cc61cbb5f8cbd0c6f052e95ed6539", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 11 blocks + 9 bytes = 185bytes +len = 185; +ASSIGNHEX(in, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8", len); +ASSIGNHEX(res, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04" + "e11b6adce343e1f38c6a879463c080d74a72a90b1e6fe46b7bc95a929f79947e" + "3ed782ad26e98e07f14d47f3c2a8e92aae8cc61cbb5f8cbd0c", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); + +// 14 blocks +len = 224; +ASSIGNHEX(in, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf", len); +ASSIGNHEX(res, + "c30ca8f2ed57307edc87e544867ac888348c208928d7406269954551cb627b5b" + "e1c241d0ff691de6b47ad81eac2b925b474e1fd14311edb95219ce64677f497b" + "8917567652e9b4ef3838baf35e400fe1ffe2f16cfa1900d7ae2b67f0e6f43b71" + "769d1b0e0c0b99ea11de58fcd3b72e1bce3d9a8750b87e945d77f4dc39d73b04" + "e11b6adce343e1f38c6a879463c080d74a72a90b1e6fe46b7bc95a929f79947e" + "ae8cc61cbb5f8cbd0c6f052e95ed65399009f56148fc07d88c8e0113d7eafb1f" + "ea39991882130ee45e95a3c6bc508f09c990add0cd3f1ca3403c096f9277e785", len); +ASSIGNZERO(out, len); +aes_xts_encrypt(in,out,len,key1,key2,iv); +CHECKHEX(out,res,0,len); diff --git a/tests/test.c b/tests/test.c index a7fbf298a..eb26a06b8 100644 --- a/tests/test.c +++ b/tests/test.c @@ -15065,9 +15065,9 @@ int test_word_recip(void) if (x[0] != UINT64_C(n)) \ { printf("Failed known value test\n"); ++failures; } else { ++successes; } -int test_known_values(void) +int test_known_values_p384(void) { int failures = 0, successes = 0; - printf("Testing known value cases\n"); + printf("Testing known value cases for p384\n"); #include "known_value_tests_p384.h" @@ -15081,6 +15081,95 @@ int test_known_values(void) } } +// Helpers for writing XTS tests +void assign_bytearray_from_hexstring(uint8_t *bytearr, const char *hexstr, int len) +{ + for (int i = 0; i < len; i++) { + sscanf(&hexstr[i * 2], "%2hhx", &bytearr[i]); + } +} + +void assign_bytearray_zero(uint8_t *bytearr, int len) +{ + for(int i = 0; i < len; i++){ + bytearr[i] = 0x00; + } +} + +#define ASSIGNHEX(bytearr, hexstr, len) assign_bytearray_from_hexstring(bytearr, hexstr, len) +#define ASSIGNZERO(bytearr, len) assign_bytearray_zero(bytearr, len) + +int check_bytearr(const uint8_t *out, const uint8_t *res, int diff, int len) +{ + for(int i = 0; i < len; i++){ + if (out[i]!=res[i]){diff = 1;break;}; + } + return diff; +} + +#define CHECKHEX(out, res, diff, len) \ + if (check_bytearr(out, res, diff, len)) \ + { printf("Failed known value test\n"); ++failures; } else { ++successes; } + + +int test_known_values_xts_encrypt(void) +{ +#ifdef __x86_64__ + return 1; +#else + int failures = 0, successes = 0; + printf("Testing known value cases for aes-xts encrypt\n"); + + s2n_bignum_AES_KEY *key1 = (s2n_bignum_AES_KEY *)malloc(sizeof(s2n_bignum_AES_KEY)); + s2n_bignum_AES_KEY *key2 = (s2n_bignum_AES_KEY *)malloc(sizeof(s2n_bignum_AES_KEY)); + size_t len; + uint8_t iv[16]; + uint8_t in[224]; + uint8_t out[224]; + uint8_t res[224]; + +#include "known_value_tests_xts_encrypt.h" + + if (failures != 0) + { printf ("Failed %d known value tests, passed %d\n",failures,successes); + return failures; + } + else + { printf("Successfully passed %d known value tests\n",successes); + return 0; + } +#endif +} + +int test_known_values_xts_decrypt(void) +{ +#ifdef __x86_64__ + return 1; +#else + int failures = 0, successes = 0; + printf("Testing known value cases for aes-xts decrypt\n"); + + s2n_bignum_AES_KEY *key1 = (s2n_bignum_AES_KEY *)malloc(sizeof(s2n_bignum_AES_KEY)); + s2n_bignum_AES_KEY *key2 = (s2n_bignum_AES_KEY *)malloc(sizeof(s2n_bignum_AES_KEY)); + size_t len; + uint8_t iv[16]; + uint8_t in[224]; + uint8_t out[224]; + uint8_t res[224]; + +#include "known_value_tests_xts_decrypt.h" + + if (failures != 0) + { printf ("Failed %d known value tests, passed %d\n",failures,successes); + return failures; + } + else + { printf("Successfully passed %d known value tests\n",successes); + return 0; + } +#endif +} + // **************************************************************************** // Analogous testing of relevant functions against TweetNaCl as reference // @@ -15611,6 +15700,7 @@ void functionaltest(int enabled,char *name,int (*f)(void)) int main(int argc, char *argv[]) { int bmi = get_arch_name() == ARCH_AARCH64 || supports_bmi2_and_adx(); int sha3 = get_arch_name() == ARCH_AARCH64 && supports_arm_sha3(); + int aes = get_arch_name() == ARCH_AARCH64 && supports_arm_aes(); int arm = get_arch_name() == ARCH_AARCH64; int all = 1; int extrastrigger = 1; @@ -15997,12 +16087,13 @@ int main(int argc, char *argv[]) functionaltest(sha3,"sha3_keccak2_f1600_alt",test_sha3_keccak2_f1600_alt); functionaltest(sha3,"sha3_keccak4_f1600_alt",test_sha3_keccak4_f1600_alt); functionaltest(sha3,"sha3_keccak4_f1600_alt2",test_sha3_keccak4_f1600_alt2); - + functionaltest(aes,"known value tests for aes-xts encrypt",test_known_values_xts_encrypt); + functionaltest(aes,"known value tests for aes-xts decrypt",test_known_values_xts_decrypt); } if (extrastrigger) function_to_test = "_"; - functionaltest(bmi,"known value tests",test_known_values); + functionaltest(bmi,"known value tests",test_known_values_p384); functionaltest(bmi,"curve25519_x25519 (TweetNaCl)",test_curve25519_x25519_tweetnacl); functionaltest(all,"curve25519_x25519_alt (TweetNaCl)",test_curve25519_x25519_alt_tweetnacl); diff --git a/tools/collect-signatures.py b/tools/collect-signatures.py index 05fdbf6e5..02254ac8b 100644 --- a/tools/collect-signatures.py +++ b/tools/collect-signatures.py @@ -48,7 +48,6 @@ def __eq__(self, io2): return self.meminputs == io2.meminputs and self.memoutputs == io2.memoutputs and \ self.temporaries == decl2.temporaries - def parseFnDecl(s:str, filename:str) -> FnDecl: assert s.startswith("extern"), s original_lines = s @@ -291,6 +290,8 @@ def stripPrefixes(s, prefixes): # A list of functions that are either only in arm or x86 onlyInArm = [ + "aes_xts_decrypt", + "aes_xts_encrypt", "bignum_copy_row_from_table_8n", "bignum_copy_row_from_table_16", "bignum_copy_row_from_table_32", @@ -395,6 +396,7 @@ def checkOnlyInArch(fnname, onlyIn): # Before printing input and output buffers, collect elem bytesize of buffers arg_elem_bytesizes = dict() + isPtr = lambda fullty, elemty: fullty.startswith(elemty + "*") isPtrOrArray = lambda fullty, elemty: fullty.startswith(elemty + "[") or fullty.startswith(elemty + "*") for argname, argtype, _ in fnsig.args: if isPtrOrArray(argtype, "int64_t") or isPtrOrArray(argtype, "uint64_t"): @@ -405,6 +407,8 @@ def checkOnlyInArch(fnname, onlyIn): arg_elem_bytesizes[argname] = 2 elif isPtrOrArray(argtype, "int8_t") or isPtrOrArray(argtype, "uint8_t"): arg_elem_bytesizes[argname] = 1 + elif isPtr(argtype, "s2n_bignum_AES_KEY"): + arg_elem_bytesizes[argname] = 1 elif "[" not in argtype and "*" not in argtype: continue else: diff --git a/x86/proofs/aes.ml b/x86/proofs/aes.ml index 9c3fc94d3..5af731137 100644 --- a/x86/proofs/aes.ml +++ b/x86/proofs/aes.ml @@ -127,7 +127,9 @@ let AESKEYGENASSIST_REDUCE_CONV tm = (** TESTS **) (************************************************) (* From White Paper: - Intel Advanced Encryption Standard (AES) New Instructions Set *) + Intel Advanced Encryption Standard (AES) New Instructions Set + https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf + Fig 11. AESENC Example to Fig 14 AESDECLAST Example *) prove(`aesenc (word 0x7b5b54657374566563746f725d53475d) (word 0x48692853686179295b477565726f6e5d) =