1 import Base 2 import bend-osdev-bytes@0.1.0.0/bytes.bend as B 3 import bend-osdev-bytes@0.1.0.0/LAWS.bend as BL 4 import bend-osdev-bytes@0.1.0.0/PROOF.bend as BP 5 import bend-osdev-word64@0.1.0.0/word64.bend as W 6 import ./cipher_modes.bend as M 7 import ./aes.bend as X 8 import ./pkcs7.bend as P 9 import ./cbc.bend as C 10 import ./xts.bend as T 11 import ./ccm.bend as CC 12 import ./cmac.bend as CM 13 import ./aes_modes.bend as D 14 import ./LAWS.bend as Laws 15 16 # How the proofs go. The modes work on blocks; the byte layer splits a byte 17 # string into blocks and joins blocks back. The lemmas below show: 18 # * XOR with the same block twice is the identity (bit by bit); 19 # * a word split into bytes and joined back is the word, and the bytes of a 20 # joined word are the (masked) bytes (bit slicing, every bit symbolic); 21 # * splitting joined blocks gives the blocks back, and joining a split 22 # byte string gives it back (induction, 16 bytes at a time); 23 # * every to_list of an Octets is masked (the bytes interface laws 24 # octets_of_to and octets_to_of), so the bytes a mode reads back are the 25 # bytes it wrote. 26 # Nothing here looks inside Octets: only the bytes laws and its list layer. 27 28 # XOR 29 30 def bx.bool(a: Bool, b: Bool) -> {Bool.xor(a, Bool.xor(a, b)) == b : Bool}: 31 match a b: 32 case False{} False{}: 33 {==} 34 case False{} True{}: 35 {==} 36 case True{} False{}: 37 {==} 38 case True{} True{}: 39 {==} 40 41 def bx.word(n: Nat, a: Word(n), b: Word(n)) -> {Word.xor(n, a, Word.xor(n, a, b)) == b : Word(n)}: 42 match n: 43 case 0n: 44 match b: 45 case WNil{}: 46 {==} 47 case 1n+p: 48 match a b: 49 case WCon{ah, at} WCon{bh, bt}: 50 %bx.bool(ah, bh) : {WCon{Bool.xor(ah, Bool.xor(ah, bh)), Word.xor(p, at, Word.xor(p, at, bt))} == WCon{_, bt} : Word(1n+p)} 51 %bx.word(p, at, bt) : {WCon{Bool.xor(ah, Bool.xor(ah, bh)), Word.xor(p, at, Word.xor(p, at, bt))} == WCon{Bool.xor(ah, Bool.xor(ah, bh)), _} : Word(1n+p)} 52 {==} 53 54 def bx.u32(a: U32, b: U32) -> {U32.xor(a, U32.xor(a, b)) == b : U32}: 55 match a b: 56 case U32{x} U32{y}: 57 %bx.word(32n, x, y) : {U32{Word.xor(32n, x, Word.xor(32n, x, y))} == U32{_} : U32} 58 {==} 59 60 # xor(a, xor(a, b)) == b on blocks 61 def bx.block(+a: M.CmBlock, +b: M.CmBlock) -> {M.CmBlock.xor(a, M.CmBlock.xor(a, b)) == b : M.CmBlock}: 62 match a b: 63 case M.CmBlock{a0, a1, a2, a3} M.CmBlock{b0, b1, b2, b3}: 64 %bx.u32(a0, b0) : {M.CmBlock.xor(M.CmBlock{a0, a1, a2, a3}, M.CmBlock.xor(M.CmBlock{a0, a1, a2, a3}, M.CmBlock{b0, b1, b2, b3})) == M.CmBlock{_, b1, b2, b3} : M.CmBlock} 65 %bx.u32(a1, b1) : {M.CmBlock.xor(M.CmBlock{a0, a1, a2, a3}, M.CmBlock.xor(M.CmBlock{a0, a1, a2, a3}, M.CmBlock{b0, b1, b2, b3})) == M.CmBlock{U32.xor(a0, U32.xor(a0, b0)), _, b2, b3} : M.CmBlock} 66 %bx.u32(a2, b2) : {M.CmBlock.xor(M.CmBlock{a0, a1, a2, a3}, M.CmBlock.xor(M.CmBlock{a0, a1, a2, a3}, M.CmBlock{b0, b1, b2, b3})) == M.CmBlock{U32.xor(a0, U32.xor(a0, b0)), U32.xor(a1, U32.xor(a1, b1)), _, b3} : M.CmBlock} 67 %bx.u32(a3, b3) : {M.CmBlock.xor(M.CmBlock{a0, a1, a2, a3}, M.CmBlock.xor(M.CmBlock{a0, a1, a2, a3}, M.CmBlock{b0, b1, b2, b3})) == M.CmBlock{U32.xor(a0, U32.xor(a0, b0)), U32.xor(a1, U32.xor(a1, b1)), U32.xor(a2, U32.xor(a2, b2)), _} : M.CmBlock} 68 {==} 69 70 # Bits: each lemma splits its words into their 32 bits, so the slicing 71 # computes 72 73 def bits.word_bytes(w: U32) -> {M.cm.word(M.cm.b0(w), M.cm.b1(w), M.cm.b2(w), M.cm.b3(w)) == w : U32}: 74 match w: 75 case U32{WCon{w0, WCon{w1, WCon{w2, WCon{w3, WCon{w4, WCon{w5, WCon{w6, WCon{w7, WCon{w8, WCon{w9, WCon{w10, WCon{w11, WCon{w12, WCon{w13, WCon{w14, WCon{w15, WCon{w16, WCon{w17, WCon{w18, WCon{w19, WCon{w20, WCon{w21, WCon{w22, WCon{w23, WCon{w24, WCon{w25, WCon{w26, WCon{w27, WCon{w28, WCon{w29, WCon{w30, WCon{w31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}: 76 {==} 77 78 def bits.byte0_word(a: U32, b: U32, c: U32, d: U32) -> {M.cm.b0(M.cm.word(a, b, c, d)) == B.byte(a) : U32}: 79 match a b c d: 80 case U32{WCon{a0, WCon{a1, WCon{a2, WCon{a3, WCon{a4, WCon{a5, WCon{a6, WCon{a7, WCon{a8, WCon{a9, WCon{a10, WCon{a11, WCon{a12, WCon{a13, WCon{a14, WCon{a15, WCon{a16, WCon{a17, WCon{a18, WCon{a19, WCon{a20, WCon{a21, WCon{a22, WCon{a23, WCon{a24, WCon{a25, WCon{a26, WCon{a27, WCon{a28, WCon{a29, WCon{a30, WCon{a31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{b0, WCon{b1, WCon{b2, WCon{b3, WCon{b4, WCon{b5, WCon{b6, WCon{b7, WCon{b8, WCon{b9, WCon{b10, WCon{b11, WCon{b12, WCon{b13, WCon{b14, WCon{b15, WCon{b16, WCon{b17, WCon{b18, WCon{b19, WCon{b20, WCon{b21, WCon{b22, WCon{b23, WCon{b24, WCon{b25, WCon{b26, WCon{b27, WCon{b28, WCon{b29, WCon{b30, WCon{b31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{c0, WCon{c1, WCon{c2, WCon{c3, WCon{c4, WCon{c5, WCon{c6, WCon{c7, WCon{c8, WCon{c9, WCon{c10, WCon{c11, WCon{c12, WCon{c13, WCon{c14, WCon{c15, WCon{c16, WCon{c17, WCon{c18, WCon{c19, WCon{c20, WCon{c21, WCon{c22, WCon{c23, WCon{c24, WCon{c25, WCon{c26, WCon{c27, WCon{c28, WCon{c29, WCon{c30, WCon{c31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{d0, WCon{d1, WCon{d2, WCon{d3, WCon{d4, WCon{d5, WCon{d6, WCon{d7, WCon{d8, WCon{d9, WCon{d10, WCon{d11, WCon{d12, WCon{d13, WCon{d14, WCon{d15, WCon{d16, WCon{d17, WCon{d18, WCon{d19, WCon{d20, WCon{d21, WCon{d22, WCon{d23, WCon{d24, WCon{d25, WCon{d26, WCon{d27, WCon{d28, WCon{d29, WCon{d30, WCon{d31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}: 81 {==} 82 83 def bits.byte1_word(a: U32, b: U32, c: U32, d: U32) -> {M.cm.b1(M.cm.word(a, b, c, d)) == B.byte(b) : U32}: 84 match a b c d: 85 case U32{WCon{a0, WCon{a1, WCon{a2, WCon{a3, WCon{a4, WCon{a5, WCon{a6, WCon{a7, WCon{a8, WCon{a9, WCon{a10, WCon{a11, WCon{a12, WCon{a13, WCon{a14, WCon{a15, WCon{a16, WCon{a17, WCon{a18, WCon{a19, WCon{a20, WCon{a21, WCon{a22, WCon{a23, WCon{a24, WCon{a25, WCon{a26, WCon{a27, WCon{a28, WCon{a29, WCon{a30, WCon{a31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{b0, WCon{b1, WCon{b2, WCon{b3, WCon{b4, WCon{b5, WCon{b6, WCon{b7, WCon{b8, WCon{b9, WCon{b10, WCon{b11, WCon{b12, WCon{b13, WCon{b14, WCon{b15, WCon{b16, WCon{b17, WCon{b18, WCon{b19, WCon{b20, WCon{b21, WCon{b22, WCon{b23, WCon{b24, WCon{b25, WCon{b26, WCon{b27, WCon{b28, WCon{b29, WCon{b30, WCon{b31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{c0, WCon{c1, WCon{c2, WCon{c3, WCon{c4, WCon{c5, WCon{c6, WCon{c7, WCon{c8, WCon{c9, WCon{c10, WCon{c11, WCon{c12, WCon{c13, WCon{c14, WCon{c15, WCon{c16, WCon{c17, WCon{c18, WCon{c19, WCon{c20, WCon{c21, WCon{c22, WCon{c23, WCon{c24, WCon{c25, WCon{c26, WCon{c27, WCon{c28, WCon{c29, WCon{c30, WCon{c31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{d0, WCon{d1, WCon{d2, WCon{d3, WCon{d4, WCon{d5, WCon{d6, WCon{d7, WCon{d8, WCon{d9, WCon{d10, WCon{d11, WCon{d12, WCon{d13, WCon{d14, WCon{d15, WCon{d16, WCon{d17, WCon{d18, WCon{d19, WCon{d20, WCon{d21, WCon{d22, WCon{d23, WCon{d24, WCon{d25, WCon{d26, WCon{d27, WCon{d28, WCon{d29, WCon{d30, WCon{d31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}: 86 {==} 87 88 def bits.byte2_word(a: U32, b: U32, c: U32, d: U32) -> {M.cm.b2(M.cm.word(a, b, c, d)) == B.byte(c) : U32}: 89 match a b c d: 90 case U32{WCon{a0, WCon{a1, WCon{a2, WCon{a3, WCon{a4, WCon{a5, WCon{a6, WCon{a7, WCon{a8, WCon{a9, WCon{a10, WCon{a11, WCon{a12, WCon{a13, WCon{a14, WCon{a15, WCon{a16, WCon{a17, WCon{a18, WCon{a19, WCon{a20, WCon{a21, WCon{a22, WCon{a23, WCon{a24, WCon{a25, WCon{a26, WCon{a27, WCon{a28, WCon{a29, WCon{a30, WCon{a31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{b0, WCon{b1, WCon{b2, WCon{b3, WCon{b4, WCon{b5, WCon{b6, WCon{b7, WCon{b8, WCon{b9, WCon{b10, WCon{b11, WCon{b12, WCon{b13, WCon{b14, WCon{b15, WCon{b16, WCon{b17, WCon{b18, WCon{b19, WCon{b20, WCon{b21, WCon{b22, WCon{b23, WCon{b24, WCon{b25, WCon{b26, WCon{b27, WCon{b28, WCon{b29, WCon{b30, WCon{b31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{c0, WCon{c1, WCon{c2, WCon{c3, WCon{c4, WCon{c5, WCon{c6, WCon{c7, WCon{c8, WCon{c9, WCon{c10, WCon{c11, WCon{c12, WCon{c13, WCon{c14, WCon{c15, WCon{c16, WCon{c17, WCon{c18, WCon{c19, WCon{c20, WCon{c21, WCon{c22, WCon{c23, WCon{c24, WCon{c25, WCon{c26, WCon{c27, WCon{c28, WCon{c29, WCon{c30, WCon{c31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{d0, WCon{d1, WCon{d2, WCon{d3, WCon{d4, WCon{d5, WCon{d6, WCon{d7, WCon{d8, WCon{d9, WCon{d10, WCon{d11, WCon{d12, WCon{d13, WCon{d14, WCon{d15, WCon{d16, WCon{d17, WCon{d18, WCon{d19, WCon{d20, WCon{d21, WCon{d22, WCon{d23, WCon{d24, WCon{d25, WCon{d26, WCon{d27, WCon{d28, WCon{d29, WCon{d30, WCon{d31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}: 91 {==} 92 93 def bits.byte3_word(a: U32, b: U32, c: U32, d: U32) -> {M.cm.b3(M.cm.word(a, b, c, d)) == B.byte(d) : U32}: 94 match a b c d: 95 case U32{WCon{a0, WCon{a1, WCon{a2, WCon{a3, WCon{a4, WCon{a5, WCon{a6, WCon{a7, WCon{a8, WCon{a9, WCon{a10, WCon{a11, WCon{a12, WCon{a13, WCon{a14, WCon{a15, WCon{a16, WCon{a17, WCon{a18, WCon{a19, WCon{a20, WCon{a21, WCon{a22, WCon{a23, WCon{a24, WCon{a25, WCon{a26, WCon{a27, WCon{a28, WCon{a29, WCon{a30, WCon{a31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{b0, WCon{b1, WCon{b2, WCon{b3, WCon{b4, WCon{b5, WCon{b6, WCon{b7, WCon{b8, WCon{b9, WCon{b10, WCon{b11, WCon{b12, WCon{b13, WCon{b14, WCon{b15, WCon{b16, WCon{b17, WCon{b18, WCon{b19, WCon{b20, WCon{b21, WCon{b22, WCon{b23, WCon{b24, WCon{b25, WCon{b26, WCon{b27, WCon{b28, WCon{b29, WCon{b30, WCon{b31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{c0, WCon{c1, WCon{c2, WCon{c3, WCon{c4, WCon{c5, WCon{c6, WCon{c7, WCon{c8, WCon{c9, WCon{c10, WCon{c11, WCon{c12, WCon{c13, WCon{c14, WCon{c15, WCon{c16, WCon{c17, WCon{c18, WCon{c19, WCon{c20, WCon{c21, WCon{c22, WCon{c23, WCon{c24, WCon{c25, WCon{c26, WCon{c27, WCon{c28, WCon{c29, WCon{c30, WCon{c31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{d0, WCon{d1, WCon{d2, WCon{d3, WCon{d4, WCon{d5, WCon{d6, WCon{d7, WCon{d8, WCon{d9, WCon{d10, WCon{d11, WCon{d12, WCon{d13, WCon{d14, WCon{d15, WCon{d16, WCon{d17, WCon{d18, WCon{d19, WCon{d20, WCon{d21, WCon{d22, WCon{d23, WCon{d24, WCon{d25, WCon{d26, WCon{d27, WCon{d28, WCon{d29, WCon{d30, WCon{d31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}: 96 {==} 97 98 def bits.byte_b0(w: U32) -> {B.byte(M.cm.b0(w)) == M.cm.b0(w) : U32}: 99 match w: 100 case U32{WCon{w0, WCon{w1, WCon{w2, WCon{w3, WCon{w4, WCon{w5, WCon{w6, WCon{w7, WCon{w8, WCon{w9, WCon{w10, WCon{w11, WCon{w12, WCon{w13, WCon{w14, WCon{w15, WCon{w16, WCon{w17, WCon{w18, WCon{w19, WCon{w20, WCon{w21, WCon{w22, WCon{w23, WCon{w24, WCon{w25, WCon{w26, WCon{w27, WCon{w28, WCon{w29, WCon{w30, WCon{w31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}: 101 {==} 102 103 def bits.byte_b1(w: U32) -> {B.byte(M.cm.b1(w)) == M.cm.b1(w) : U32}: 104 match w: 105 case U32{WCon{w0, WCon{w1, WCon{w2, WCon{w3, WCon{w4, WCon{w5, WCon{w6, WCon{w7, WCon{w8, WCon{w9, WCon{w10, WCon{w11, WCon{w12, WCon{w13, WCon{w14, WCon{w15, WCon{w16, WCon{w17, WCon{w18, WCon{w19, WCon{w20, WCon{w21, WCon{w22, WCon{w23, WCon{w24, WCon{w25, WCon{w26, WCon{w27, WCon{w28, WCon{w29, WCon{w30, WCon{w31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}: 106 {==} 107 108 def bits.byte_b2(w: U32) -> {B.byte(M.cm.b2(w)) == M.cm.b2(w) : U32}: 109 match w: 110 case U32{WCon{w0, WCon{w1, WCon{w2, WCon{w3, WCon{w4, WCon{w5, WCon{w6, WCon{w7, WCon{w8, WCon{w9, WCon{w10, WCon{w11, WCon{w12, WCon{w13, WCon{w14, WCon{w15, WCon{w16, WCon{w17, WCon{w18, WCon{w19, WCon{w20, WCon{w21, WCon{w22, WCon{w23, WCon{w24, WCon{w25, WCon{w26, WCon{w27, WCon{w28, WCon{w29, WCon{w30, WCon{w31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}: 111 {==} 112 113 def bits.byte_b3(w: U32) -> {B.byte(M.cm.b3(w)) == M.cm.b3(w) : U32}: 114 match w: 115 case U32{WCon{w0, WCon{w1, WCon{w2, WCon{w3, WCon{w4, WCon{w5, WCon{w6, WCon{w7, WCon{w8, WCon{w9, WCon{w10, WCon{w11, WCon{w12, WCon{w13, WCon{w14, WCon{w15, WCon{w16, WCon{w17, WCon{w18, WCon{w19, WCon{w20, WCon{w21, WCon{w22, WCon{w23, WCon{w24, WCon{w25, WCon{w26, WCon{w27, WCon{w28, WCon{w29, WCon{w30, WCon{w31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}: 116 {==} 117 118 def bits.byte_byte(y: U32) -> {B.byte(B.byte(y)) == B.byte(y) : U32}: 119 match y: 120 case U32{WCon{y0, WCon{y1, WCon{y2, WCon{y3, WCon{y4, WCon{y5, WCon{y6, WCon{y7, WCon{y8, WCon{y9, WCon{y10, WCon{y11, WCon{y12, WCon{y13, WCon{y14, WCon{y15, WCon{y16, WCon{y17, WCon{y18, WCon{y19, WCon{y20, WCon{y21, WCon{y22, WCon{y23, WCon{y24, WCon{y25, WCon{y26, WCon{y27, WCon{y28, WCon{y29, WCon{y30, WCon{y31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}: 121 {==} 122 # Splits 123 124 def sp.cons_blocks(b: M.CmBlock, s: M.CmSplit) -> {M.cm.split.blocks(M.cm.split.cons(b, s)) == Con{b, M.cm.split.blocks(s)} : List<&2, M.CmBlock>}: 125 match s: 126 case M.CmSplit{bs, t}: 127 {==} 128 129 def sp.cons_tail(b: M.CmBlock, s: M.CmSplit) -> {M.cm.split.tail(M.cm.split.cons(b, s)) == M.cm.split.tail(s) : List<&2, U32>}: 130 match s: 131 case M.CmSplit{bs, t}: 132 {==} 133 134 def sp.eta(s: M.CmSplit) -> {M.CmSplit{M.cm.split.blocks(s), M.cm.split.tail(s)} == s : M.CmSplit}: 135 match s: 136 case M.CmSplit{bs, t}: 137 {==} 138 139 # Arithmetic: n + 16 and n leave the same remainder mod 16 140 141 def sp.disc(n: Nat) -> Type: 142 match n: 143 case 0n: 144 Empty 145 case 1n+p: 146 Unit 147 148 def sp.absurd(p: Nat, h: {1n+p == 0n : Nat}) -> Empty: 149 %h : sp.disc(_) 150 Unit{} 151 152 def sp.absurd_tail(p: Nat, xs: List<&2, U32>, h: {1n+p == 0n : Nat}) -> {M.cm.split.tail(M.cm.split(B.mask(xs))) == Nil{} : List<&2, U32>}: 153 Empty.absurd({M.cm.split.tail(M.cm.split(B.mask(xs))) == Nil{} : List<&2, U32>}, sp.absurd(p, h)) 154 155 def sp.snd_go(n: Nat, m: Nat, d1: Nat, d2: Nat, r: Nat) -> {Pair.snd(Nat, Nat, Nat.divmod.go(n, m, d1, r)) == Pair.snd(Nat, Nat, Nat.divmod.go(n, m, d2, r)) : Nat}: 156 match n: 157 case 0n: 158 {==} 159 case 1n+np: 160 match m: 161 case 0n: 162 sp.snd_go(np, r, 1n+d1, 1n+d2, 0n) 163 case 1n+mp: 164 sp.snd_go(np, mp, d1, d2, 1n+r) 165 166 def sp.mod16(n: Nat) -> {Nat.mod(Nat.add(16n, n), 16n) == Nat.mod(n, 16n) : Nat}: 167 sp.snd_go(n, 15n, 1n, 0n, 0n) 168 169 170 # Booleans: False is not True 171 172 def bo.disc(b: Bool) -> Type: 173 match b: 174 case False{}: 175 Unit 176 case True{}: 177 Empty 178 179 def bo.empty(h: {False{} == True{} : Bool}) -> Empty: 180 %h : bo.disc(_) 181 Unit{} 182 183 def bo.absurd(-A: Type, h: {False{} == True{} : Bool}) -> A: 184 Empty.absurd(A, bo.empty(h)) 185 186 # Lists of bytes (the bytes list layer) 187 188 def li.mask_mask(zs: List<&2, U32>) -> {B.mask(B.mask(zs)) == B.mask(zs) : List<&2, U32>}: 189 match zs: 190 case Nil{}: 191 {==} 192 case Con{+z, +t}: 193 %bits.byte_byte(z) : {Con{B.byte(B.byte(z)), B.mask(B.mask(t))} == Con{_, B.mask(t)} : List<&2, U32>} 194 %li.mask_mask(t) : {Con{B.byte(B.byte(z)), B.mask(B.mask(t))} == Con{B.byte(B.byte(z)), _} : List<&2, U32>} 195 {==} 196 197 def li.take_append(+a: List<&2, U32>, +b: List<&2, U32>) -> {B.take(B.len(a), B.append(a, b)) == a : List<&2, U32>}: 198 match a: 199 case Nil{}: 200 {==} 201 case Con{+h, +t}: 202 %Equal.sym(List<&2, U32>, B.take(B.len(t), B.append(t, b)), t, li.take_append(t, b)) : {Con{h, _} == Con{h, t} : List<&2, U32>} 203 {==} 204 205 def li.drop_append(+a: List<&2, U32>, +b: List<&2, U32>) -> {B.drop(B.len(a), B.append(a, b)) == b : List<&2, U32>}: 206 match a: 207 case Nil{}: 208 {==} 209 case Con{+h, +t}: 210 li.drop_append(t, b) 211 212 def li.mask_append(+a: List<&2, U32>, +b: List<&2, U32>) -> {B.mask(B.append(a, b)) == B.append(B.mask(a), B.mask(b)) : List<&2, U32>}: 213 match a: 214 case Nil{}: 215 {==} 216 case Con{+h, +t}: 217 %li.mask_append(t, b) : {Con{B.byte(h), B.mask(B.append(t, b))} == Con{B.byte(h), _} : List<&2, U32>} 218 {==} 219 220 def li.mask_drop(+n: Nat, +xs: List<&2, U32>) -> {B.mask(B.drop(n, xs)) == B.drop(n, B.mask(xs)) : List<&2, U32>}: 221 match n: 222 case 0n: 223 {==} 224 case 1n+p: 225 match xs: 226 case Nil{}: 227 {==} 228 case Con{+h, +t}: 229 li.mask_drop(p, t) 230 231 def li.mask_take(+n: Nat, +xs: List<&2, U32>) -> {B.mask(B.take(n, xs)) == B.take(n, B.mask(xs)) : List<&2, U32>}: 232 match n: 233 case 0n: 234 {==} 235 case 1n+p: 236 match xs: 237 case Nil{}: 238 {==} 239 case Con{+h, +t}: 240 %li.mask_take(p, t) : {Con{B.byte(h), B.mask(B.take(p, t))} == Con{B.byte(h), _} : List<&2, U32>} 241 {==} 242 243 def li.len_append(+a: List<&2, U32>, +b: List<&2, U32>) -> {B.len(B.append(a, b)) == Nat.add(B.len(a), B.len(b)) : Nat}: 244 match a: 245 case Nil{}: 246 {==} 247 case Con{+h, +t}: 248 %li.len_append(t, b) : {1n+B.len(B.append(t, b)) == 1n+_ : Nat} 249 {==} 250 251 def li.len_drop(+n: Nat, +xs: List<&2, U32>) -> {B.len(B.drop(n, xs)) == Nat.sub(B.len(xs), n) : Nat}: 252 match n: 253 case 0n: 254 match xs: 255 case Nil{}: 256 {==} 257 case Con{+h, +t}: 258 {==} 259 case 1n+p: 260 match xs: 261 case Nil{}: 262 {==} 263 case Con{+h, +t}: 264 li.len_drop(p, t) 265 266 def li.len_take(+n: Nat, +xs: List<&2, U32>) -> {Nat.is_le(n, B.len(xs)) == True{} : Bool} -> {B.len(B.take(n, xs)) == n : Nat}: 267 match n: 268 case 0n: 269 h => {==} 270 case 1n+p: 271 match xs: 272 case Nil{}: 273 h => bo.absurd({B.len(B.take(1n+p, Nil{})) == 1n+p : Nat}, h) 274 case Con{+x, +t}: 275 h => %li.len_take(p, t)(h) : {1n+B.len(B.take(p, t)) == 1n+_ : Nat} 276 {==} 277 278 # Naturals 279 280 def na.add_sub(+a: Nat, +b: Nat) -> {Nat.is_le(a, b) == True{} : Bool} -> {Nat.add(a, Nat.sub(b, a)) == b : Nat}: 281 match a b: 282 case 0n 0n: 283 h => {==} 284 case 0n 1n+bp: 285 h => {==} 286 case 1n+ap 0n: 287 h => bo.absurd({Nat.add(1n+ap, Nat.sub(0n, 1n+ap)) == 0n : Nat}, h) 288 case 1n+ap 1n+bp: 289 h => %na.add_sub(ap, bp)(h) : {1n+Nat.add(ap, Nat.sub(bp, ap)) == 1n+_ : Nat} 290 {==} 291 292 def na.lt_le(+a: Nat, +b: Nat) -> {Nat.is_lt(a, b) == True{} : Bool} -> {Nat.is_le(a, b) == True{} : Bool}: 293 match a b: 294 case 0n 0n: 295 h => bo.absurd({Nat.is_le(0n, 0n) == True{} : Bool}, h) 296 case 0n 1n+bp: 297 h => {==} 298 case 1n+ap 0n: 299 h => bo.absurd({Nat.is_le(1n+ap, 0n) == True{} : Bool}, h) 300 case 1n+ap 1n+bp: 301 h => na.lt_le(ap, bp)(h) 302 303 # Blocks in lists 304 305 def sp.hd(bs: List<&2, M.CmBlock>) -> M.CmBlock: 306 match bs: 307 case Nil{}: 308 M.CmBlock.zero() 309 case Con{b, t}: 310 b 311 312 def sp.tl(bs: List<&2, M.CmBlock>) -> List<&2, M.CmBlock>: 313 match bs: 314 case Nil{}: 315 Nil{} 316 case Con{b, t}: 317 t 318 319 # splitting the bytes of a block gives the block back 320 def sp.blk(b: M.CmBlock, rest: List<&2, U32>) -> {M.cm.split(M.cm.bytes_onto(b, rest)) == M.cm.split.cons(b, M.cm.split(rest)) : M.CmSplit}: 321 match b: 322 case M.CmBlock{U32{WCon{p0, WCon{p1, WCon{p2, WCon{p3, WCon{p4, WCon{p5, WCon{p6, WCon{p7, WCon{p8, WCon{p9, WCon{p10, WCon{p11, WCon{p12, WCon{p13, WCon{p14, WCon{p15, WCon{p16, WCon{p17, WCon{p18, WCon{p19, WCon{p20, WCon{p21, WCon{p22, WCon{p23, WCon{p24, WCon{p25, WCon{p26, WCon{p27, WCon{p28, WCon{p29, WCon{p30, WCon{p31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, U32{WCon{q0, WCon{q1, WCon{q2, WCon{q3, WCon{q4, WCon{q5, WCon{q6, WCon{q7, WCon{q8, WCon{q9, WCon{q10, WCon{q11, WCon{q12, WCon{q13, WCon{q14, WCon{q15, WCon{q16, WCon{q17, WCon{q18, WCon{q19, WCon{q20, WCon{q21, WCon{q22, WCon{q23, WCon{q24, WCon{q25, WCon{q26, WCon{q27, WCon{q28, WCon{q29, WCon{q30, WCon{q31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, U32{WCon{r0, WCon{r1, WCon{r2, WCon{r3, WCon{r4, WCon{r5, WCon{r6, WCon{r7, WCon{r8, WCon{r9, WCon{r10, WCon{r11, WCon{r12, WCon{r13, WCon{r14, WCon{r15, WCon{r16, WCon{r17, WCon{r18, WCon{r19, WCon{r20, WCon{r21, WCon{r22, WCon{r23, WCon{r24, WCon{r25, WCon{r26, WCon{r27, WCon{r28, WCon{r29, WCon{r30, WCon{r31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, U32{WCon{s0, WCon{s1, WCon{s2, WCon{s3, WCon{s4, WCon{s5, WCon{s6, WCon{s7, WCon{s8, WCon{s9, WCon{s10, WCon{s11, WCon{s12, WCon{s13, WCon{s14, WCon{s15, WCon{s16, WCon{s17, WCon{s18, WCon{s19, WCon{s20, WCon{s21, WCon{s22, WCon{s23, WCon{s24, WCon{s25, WCon{s26, WCon{s27, WCon{s28, WCon{s29, WCon{s30, WCon{s31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}: 323 {==} 324 325 # the bytes of a block are bytes: masking changes nothing 326 def sp.mask_blk(b: M.CmBlock, rest: List<&2, U32>) -> {B.mask(M.cm.bytes_onto(b, rest)) == M.cm.bytes_onto(b, B.mask(rest)) : List<&2, U32>}: 327 match b: 328 case M.CmBlock{U32{WCon{p0, WCon{p1, WCon{p2, WCon{p3, WCon{p4, WCon{p5, WCon{p6, WCon{p7, WCon{p8, WCon{p9, WCon{p10, WCon{p11, WCon{p12, WCon{p13, WCon{p14, WCon{p15, WCon{p16, WCon{p17, WCon{p18, WCon{p19, WCon{p20, WCon{p21, WCon{p22, WCon{p23, WCon{p24, WCon{p25, WCon{p26, WCon{p27, WCon{p28, WCon{p29, WCon{p30, WCon{p31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, U32{WCon{q0, WCon{q1, WCon{q2, WCon{q3, WCon{q4, WCon{q5, WCon{q6, WCon{q7, WCon{q8, WCon{q9, WCon{q10, WCon{q11, WCon{q12, WCon{q13, WCon{q14, WCon{q15, WCon{q16, WCon{q17, WCon{q18, WCon{q19, WCon{q20, WCon{q21, WCon{q22, WCon{q23, WCon{q24, WCon{q25, WCon{q26, WCon{q27, WCon{q28, WCon{q29, WCon{q30, WCon{q31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, U32{WCon{r0, WCon{r1, WCon{r2, WCon{r3, WCon{r4, WCon{r5, WCon{r6, WCon{r7, WCon{r8, WCon{r9, WCon{r10, WCon{r11, WCon{r12, WCon{r13, WCon{r14, WCon{r15, WCon{r16, WCon{r17, WCon{r18, WCon{r19, WCon{r20, WCon{r21, WCon{r22, WCon{r23, WCon{r24, WCon{r25, WCon{r26, WCon{r27, WCon{r28, WCon{r29, WCon{r30, WCon{r31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, U32{WCon{s0, WCon{s1, WCon{s2, WCon{s3, WCon{s4, WCon{s5, WCon{s6, WCon{s7, WCon{s8, WCon{s9, WCon{s10, WCon{s11, WCon{s12, WCon{s13, WCon{s14, WCon{s15, WCon{s16, WCon{s17, WCon{s18, WCon{s19, WCon{s20, WCon{s21, WCon{s22, WCon{s23, WCon{s24, WCon{s25, WCon{s26, WCon{s27, WCon{s28, WCon{s29, WCon{s30, WCon{s31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}: 329 {==} 330 331 # the block of 16 bytes, as bytes again 332 def sp.blk16(y0: U32, y1: U32, y2: U32, y3: U32, y4: U32, y5: U32, y6: U32, y7: U32, y8: U32, y9: U32, y10: U32, y11: U32, y12: U32, y13: U32, y14: U32, y15: U32, rest: List<&2, U32>) -> {M.cm.bytes_onto(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), rest) == Con{B.byte(y0), Con{B.byte(y1), Con{B.byte(y2), Con{B.byte(y3), Con{B.byte(y4), Con{B.byte(y5), Con{B.byte(y6), Con{B.byte(y7), Con{B.byte(y8), Con{B.byte(y9), Con{B.byte(y10), Con{B.byte(y11), Con{B.byte(y12), Con{B.byte(y13), Con{B.byte(y14), Con{B.byte(y15), rest}}}}}}}}}}}}}}}} : List<&2, U32>}: 333 match y0 y1 y2 y3 y4 y5 y6 y7 y8 y9 y10 y11 y12 y13 y14 y15: 334 case U32{WCon{y00, WCon{y01, WCon{y02, WCon{y03, WCon{y04, WCon{y05, WCon{y06, WCon{y07, WCon{y08, WCon{y09, WCon{y010, WCon{y011, WCon{y012, WCon{y013, WCon{y014, WCon{y015, WCon{y016, WCon{y017, WCon{y018, WCon{y019, WCon{y020, WCon{y021, WCon{y022, WCon{y023, WCon{y024, WCon{y025, WCon{y026, WCon{y027, WCon{y028, WCon{y029, WCon{y030, WCon{y031, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{y10, WCon{y11, WCon{y12, WCon{y13, WCon{y14, WCon{y15, WCon{y16, WCon{y17, WCon{y18, WCon{y19, WCon{y110, WCon{y111, WCon{y112, WCon{y113, WCon{y114, WCon{y115, WCon{y116, WCon{y117, WCon{y118, WCon{y119, WCon{y120, WCon{y121, WCon{y122, WCon{y123, WCon{y124, WCon{y125, WCon{y126, WCon{y127, WCon{y128, WCon{y129, WCon{y130, WCon{y131, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{y20, WCon{y21, WCon{y22, WCon{y23, WCon{y24, WCon{y25, WCon{y26, WCon{y27, WCon{y28, WCon{y29, WCon{y210, WCon{y211, WCon{y212, WCon{y213, WCon{y214, WCon{y215, WCon{y216, WCon{y217, WCon{y218, WCon{y219, WCon{y220, WCon{y221, WCon{y222, WCon{y223, WCon{y224, WCon{y225, WCon{y226, WCon{y227, WCon{y228, WCon{y229, WCon{y230, WCon{y231, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{y30, WCon{y31, WCon{y32, WCon{y33, WCon{y34, WCon{y35, WCon{y36, WCon{y37, WCon{y38, WCon{y39, WCon{y310, WCon{y311, WCon{y312, WCon{y313, WCon{y314, WCon{y315, WCon{y316, WCon{y317, WCon{y318, WCon{y319, WCon{y320, WCon{y321, WCon{y322, WCon{y323, WCon{y324, WCon{y325, WCon{y326, WCon{y327, WCon{y328, WCon{y329, WCon{y330, WCon{y331, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{y40, WCon{y41, WCon{y42, WCon{y43, WCon{y44, WCon{y45, WCon{y46, WCon{y47, WCon{y48, WCon{y49, WCon{y410, WCon{y411, WCon{y412, WCon{y413, WCon{y414, WCon{y415, WCon{y416, WCon{y417, WCon{y418, WCon{y419, WCon{y420, WCon{y421, WCon{y422, WCon{y423, WCon{y424, WCon{y425, WCon{y426, WCon{y427, WCon{y428, WCon{y429, WCon{y430, WCon{y431, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{y50, WCon{y51, WCon{y52, WCon{y53, WCon{y54, WCon{y5 335 {==} 336 337 # a masked list is its blocks and its tail joined back 338 def sp.join_split(ys: List<&2, U32>) -> {M.cm.join_onto(M.cm.split.blocks(M.cm.split(B.mask(ys))), M.cm.split.tail(M.cm.split(B.mask(ys)))) == B.mask(ys) : List<&2, U32>}: 339 match ys: 340 case Nil{}: 341 {==} 342 case Con{+y0, +r0}: 343 match r0: 344 case Nil{}: 345 {==} 346 case Con{+y1, +r1}: 347 match r1: 348 case Nil{}: 349 {==} 350 case Con{+y2, +r2}: 351 match r2: 352 case Nil{}: 353 {==} 354 case Con{+y3, +r3}: 355 match r3: 356 case Nil{}: 357 {==} 358 case Con{+y4, +r4}: 359 match r4: 360 case Nil{}: 361 {==} 362 case Con{+y5, +r5}: 363 match r5: 364 case Nil{}: 365 {==} 366 case Con{+y6, +r6}: 367 match r6: 368 case Nil{}: 369 {==} 370 case Con{+y7, +r7}: 371 match r7: 372 case Nil{}: 373 {==} 374 case Con{+y8, +r8}: 375 match r8: 376 case Nil{}: 377 {==} 378 case Con{+y9, +r9}: 379 match r9: 380 case Nil{}: 381 {==} 382 case Con{+y10, +r10}: 383 match r10: 384 case Nil{}: 385 {==} 386 case Con{+y11, +r11}: 387 match r11: 388 case Nil{}: 389 {==} 390 case Con{+y12, +r12}: 391 match r12: 392 case Nil{}: 393 {==} 394 case Con{+y13, +r13}: 395 match r13: 396 case Nil{}: 397 {==} 398 case Con{+y14, +r14}: 399 match r14: 400 case Nil{}: 401 {==} 402 case Con{+y15, +t}: 403 %Equal.sym(List<&2, M.CmBlock>, M.cm.split.blocks(M.cm.split.cons(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split(B.mask(t)))), Con{M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split.blocks(M.cm.split(B.mask(t)))}, sp.cons_blocks(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split(B.mask(t)))) : {M.cm.join_onto(_, M.cm.split.tail(M.cm.split.cons(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split(B.mask(t))))) == Con{B.byte(y0), Con{B.byte(y1), Con{B.byte(y2), Con{B.byte(y3), Con{B.byte(y4), Con{B.byte(y5), Con{B.byte(y6), Con{B.byte(y7), Con{B.byte(y8), Con{B.byte(y9), Con{B.byte(y10), Con{B.byte(y11), Con{B.byte(y12), Con{B.byte(y13), Con{B.byte(y14), Con{B.byte(y15), B.mask(t)}}}}}}}}}}}}}}}} : List<&2, U32>} 404 %Equal.sym(List<&2, U32>, M.cm.split.tail(M.cm.split.cons(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split(B.mask(t)))), M.cm.split.tail(M.cm.split(B.mask(t))), sp.cons_tail(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split(B.mask(t)))) : {M.cm.join_onto(Con{M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split.blocks(M.cm.split(B.mask(t)))}, _) == Con{B.byte(y0), Con{B.byte(y1), Con{B.byte(y2), Con{B.byte(y3), Con{B.byte(y4), Con{B.byte(y5), Con{B.byte(y6), Con{B.byte(y7), Con{B.byte(y8), Con{B.byte(y9), Con{B.byte(y10), Con{B.byte(y11), Con{B.byte(y12), Con{B.byte(y13), Con{B.byte(y14), Con{B.byte(y15), B.mask(t)}}}}}}}}}}}}}}}} : List<&2, U32>} 405 %Equal.sym(List<&2, U32>, M.cm.join_onto(M.cm.split.blocks(M.cm.split(B.mask(t))), M.cm.split.tail(M.cm.split(B.mask(t)))), B.mask(t), sp.join_split(t)) : {M.cm.bytes_onto(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), _) == Con{B.byte(y0), Con{B.byte(y1), Con{B.byte(y2), Con{B.byte(y3), Con{B.byte(y4), Con{B.byte(y5), Con{B.byte(y6), Con{B.byte(y7), Con{B.byte(y8), Con{B.byte(y9), Con{B.byte(y10), Con{B.byte(y11), Con{B.byte(y12), Con{B.byte(y13), Con{B.byte(y14), Con{B.byte(y15), B.mask(t)}}}}}}}}}}}}}}}} : List<&2, U32>} 406 sp.blk16(y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15, B.mask(t)) 407 408 # a list of whole blocks splits with no tail 409 def sp.mod_tail(ys: List<&2, U32>) -> {Nat.mod(B.len(ys), 16n) == 0n : Nat} -> {M.cm.split.tail(M.cm.split(B.mask(ys))) == Nil{} : List<&2, U32>}: 410 match ys: 411 case Nil{}: 412 h => {==} 413 case Con{+y0, +r0}: 414 match r0: 415 case Nil{}: 416 h => sp.absurd_tail(0n, Con{y0, Nil{}}, h) 417 case Con{+y1, +r1}: 418 match r1: 419 case Nil{}: 420 h => sp.absurd_tail(1n, Con{y0, Con{y1, Nil{}}}, h) 421 case Con{+y2, +r2}: 422 match r2: 423 case Nil{}: 424 h => sp.absurd_tail(2n, Con{y0, Con{y1, Con{y2, Nil{}}}}, h) 425 case Con{+y3, +r3}: 426 match r3: 427 case Nil{}: 428 h => sp.absurd_tail(3n, Con{y0, Con{y1, Con{y2, Con{y3, Nil{}}}}}, h) 429 case Con{+y4, +r4}: 430 match r4: 431 case Nil{}: 432 h => sp.absurd_tail(4n, Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Nil{}}}}}}, h) 433 case Con{+y5, +r5}: 434 match r5: 435 case Nil{}: 436 h => sp.absurd_tail(5n, Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Nil{}}}}}}}, h) 437 case Con{+y6, +r6}: 438 match r6: 439 case Nil{}: 440 h => sp.absurd_tail(6n, Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Nil{}}}}}}}}, h) 441 case Con{+y7, +r7}: 442 match r7: 443 case Nil{}: 444 h => sp.absurd_tail(7n, Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Nil{}}}}}}}}}, h) 445 case Con{+y8, +r8}: 446 match r8: 447 case Nil{}: 448 h => sp.absurd_tail(8n, Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Nil{}}}}}}}}}}, h) 449 case Con{+y9, +r9}: 450 match r9: 451 case Nil{}: 452 h => sp.absurd_tail(9n, Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Nil{}}}}}}}}}}}, h) 453 case Con{+y10, +r10}: 454 match r10: 455 case Nil{}: 456 h => sp.absurd_tail(10n, Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Nil{}}}}}}}}}}}}, h) 457 case Con{+y11, +r11}: 458 match r11: 459 case Nil{}: 460 h => sp.absurd_tail(11n, Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Nil{}}}}}}}}}}}}}, h) 461 case Con{+y12, +r12}: 462 match r12: 463 case Nil{}: 464 h => sp.absurd_tail(12n, Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Nil{}}}}}}}}}}}}}}, h) 465 case Con{+y13, +r13}: 466 match r13: 467 case Nil{}: 468 h => sp.absurd_tail(13n, Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Nil{}}}}}}}}}}}}}}}, h) 469 case Con{+y14, +r14}: 470 match r14: 471 case Nil{}: 472 h => sp.absurd_tail(14n, Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Con{y14, Nil{}}}}}}}}}}}}}}}}, h) 473 case Con{+y15, +t}: 474 h => %Equal.sym(List<&2, U32>, M.cm.split.tail(M.cm.split.cons(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split(B.mask(t)))), M.cm.split.tail(M.cm.split(B.mask(t))), sp.cons_tail(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split(B.mask(t)))) : {_ == Nil{} : List<&2, U32>} 475 sp.mod_tail(t)(Equal.trans(Nat, Nat.mod(B.len(t), 16n), Nat.mod(Nat.add(16n, B.len(t)), 16n), 0n, Equal.sym(Nat, Nat.mod(Nat.add(16n, B.len(t)), 16n), Nat.mod(B.len(t), 16n), sp.mod16(B.len(t))), h)) 476 477 # the bytes of the block of any 16 values are those values, masked 478 def sp.blk16g(z0: U32, z1: U32, z2: U32, z3: U32, z4: U32, z5: U32, z6: U32, z7: U32, z8: U32, z9: U32, z10: U32, z11: U32, z12: U32, z13: U32, z14: U32, z15: U32, rest: List<&2, U32>) -> {M.cm.bytes_onto(M.cm.block16(z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15), rest) == Con{B.byte(z0), Con{B.byte(z1), Con{B.byte(z2), Con{B.byte(z3), Con{B.byte(z4), Con{B.byte(z5), Con{B.byte(z6), Con{B.byte(z7), Con{B.byte(z8), Con{B.byte(z9), Con{B.byte(z10), Con{B.byte(z11), Con{B.byte(z12), Con{B.byte(z13), Con{B.byte(z14), Con{B.byte(z15), rest}}}}}}}}}}}}}}}} : List<&2, U32>}: 479 match z0 z1 z2 z3 z4 z5 z6 z7 z8 z9 z10 z11 z12 z13 z14 z15: 480 case U32{WCon{z00, WCon{z01, WCon{z02, WCon{z03, WCon{z04, WCon{z05, WCon{z06, WCon{z07, WCon{z08, WCon{z09, WCon{z010, WCon{z011, WCon{z012, WCon{z013, WCon{z014, WCon{z015, WCon{z016, WCon{z017, WCon{z018, WCon{z019, WCon{z020, WCon{z021, WCon{z022, WCon{z023, WCon{z024, WCon{z025, WCon{z026, WCon{z027, WCon{z028, WCon{z029, WCon{z030, WCon{z031, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{z10, WCon{z11, WCon{z12, WCon{z13, WCon{z14, WCon{z15, WCon{z16, WCon{z17, WCon{z18, WCon{z19, WCon{z110, WCon{z111, WCon{z112, WCon{z113, WCon{z114, WCon{z115, WCon{z116, WCon{z117, WCon{z118, WCon{z119, WCon{z120, WCon{z121, WCon{z122, WCon{z123, WCon{z124, WCon{z125, WCon{z126, WCon{z127, WCon{z128, WCon{z129, WCon{z130, WCon{z131, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{z20, WCon{z21, WCon{z22, WCon{z23, WCon{z24, WCon{z25, WCon{z26, WCon{z27, WCon{z28, WCon{z29, WCon{z210, WCon{z211, WCon{z212, WCon{z213, WCon{z214, WCon{z215, WCon{z216, WCon{z217, WCon{z218, WCon{z219, WCon{z220, WCon{z221, WCon{z222, WCon{z223, WCon{z224, WCon{z225, WCon{z226, WCon{z227, WCon{z228, WCon{z229, WCon{z230, WCon{z231, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{z30, WCon{z31, WCon{z32, WCon{z33, WCon{z34, WCon{z35, WCon{z36, WCon{z37, WCon{z38, WCon{z39, WCon{z310, WCon{z311, WCon{z312, WCon{z313, WCon{z314, WCon{z315, WCon{z316, WCon{z317, WCon{z318, WCon{z319, WCon{z320, WCon{z321, WCon{z322, WCon{z323, WCon{z324, WCon{z325, WCon{z326, WCon{z327, WCon{z328, WCon{z329, WCon{z330, WCon{z331, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{z40, WCon{z41, WCon{z42, WCon{z43, WCon{z44, WCon{z45, WCon{z46, WCon{z47, WCon{z48, WCon{z49, WCon{z410, WCon{z411, WCon{z412, WCon{z413, WCon{z414, WCon{z415, WCon{z416, WCon{z417, WCon{z418, WCon{z419, WCon{z420, WCon{z421, WCon{z422, WCon{z423, WCon{z424, WCon{z425, WCon{z426, WCon{z427, WCon{z428, WCon{z429, WCon{z430, WCon{z431, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{z50, WCon{z51, WCon{z52, WCon{z53, WCon{z54, WCon{z5 481 {==} 482 483 # the tail of a split has fewer than 16 bytes 484 def sp.tail_short(ys: List<&2, U32>) -> {Nat.is_lt(B.len(M.cm.split.tail(M.cm.split(B.mask(ys)))), 16n) == True{} : Bool}: 485 match ys: 486 case Nil{}: 487 {==} 488 case Con{+y0, +r0}: 489 match r0: 490 case Nil{}: 491 {==} 492 case Con{+y1, +r1}: 493 match r1: 494 case Nil{}: 495 {==} 496 case Con{+y2, +r2}: 497 match r2: 498 case Nil{}: 499 {==} 500 case Con{+y3, +r3}: 501 match r3: 502 case Nil{}: 503 {==} 504 case Con{+y4, +r4}: 505 match r4: 506 case Nil{}: 507 {==} 508 case Con{+y5, +r5}: 509 match r5: 510 case Nil{}: 511 {==} 512 case Con{+y6, +r6}: 513 match r6: 514 case Nil{}: 515 {==} 516 case Con{+y7, +r7}: 517 match r7: 518 case Nil{}: 519 {==} 520 case Con{+y8, +r8}: 521 match r8: 522 case Nil{}: 523 {==} 524 case Con{+y9, +r9}: 525 match r9: 526 case Nil{}: 527 {==} 528 case Con{+y10, +r10}: 529 match r10: 530 case Nil{}: 531 {==} 532 case Con{+y11, +r11}: 533 match r11: 534 case Nil{}: 535 {==} 536 case Con{+y12, +r12}: 537 match r12: 538 case Nil{}: 539 {==} 540 case Con{+y13, +r13}: 541 match r13: 542 case Nil{}: 543 {==} 544 case Con{+y14, +r14}: 545 match r14: 546 case Nil{}: 547 {==} 548 case Con{+y15, +t}: 549 %Equal.sym(List<&2, U32>, M.cm.split.tail(M.cm.split.cons(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split(B.mask(t)))), M.cm.split.tail(M.cm.split(B.mask(t))), sp.cons_tail(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split(B.mask(t)))) : {Nat.is_lt(B.len(_), 16n) == True{} : Bool} 550 sp.tail_short(t) 551 552 # the tail of a masked split is masked 553 def sp.tail_masked(ys: List<&2, U32>) -> {B.mask(M.cm.split.tail(M.cm.split(B.mask(ys)))) == M.cm.split.tail(M.cm.split(B.mask(ys))) : List<&2, U32>}: 554 match ys: 555 case Nil{}: 556 li.mask_mask(Nil{}) 557 case Con{+y0, +r0}: 558 match r0: 559 case Nil{}: 560 li.mask_mask(Con{y0, Nil{}}) 561 case Con{+y1, +r1}: 562 match r1: 563 case Nil{}: 564 li.mask_mask(Con{y0, Con{y1, Nil{}}}) 565 case Con{+y2, +r2}: 566 match r2: 567 case Nil{}: 568 li.mask_mask(Con{y0, Con{y1, Con{y2, Nil{}}}}) 569 case Con{+y3, +r3}: 570 match r3: 571 case Nil{}: 572 li.mask_mask(Con{y0, Con{y1, Con{y2, Con{y3, Nil{}}}}}) 573 case Con{+y4, +r4}: 574 match r4: 575 case Nil{}: 576 li.mask_mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Nil{}}}}}}) 577 case Con{+y5, +r5}: 578 match r5: 579 case Nil{}: 580 li.mask_mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Nil{}}}}}}}) 581 case Con{+y6, +r6}: 582 match r6: 583 case Nil{}: 584 li.mask_mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Nil{}}}}}}}}) 585 case Con{+y7, +r7}: 586 match r7: 587 case Nil{}: 588 li.mask_mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Nil{}}}}}}}}}) 589 case Con{+y8, +r8}: 590 match r8: 591 case Nil{}: 592 li.mask_mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Nil{}}}}}}}}}}) 593 case Con{+y9, +r9}: 594 match r9: 595 case Nil{}: 596 li.mask_mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Nil{}}}}}}}}}}}) 597 case Con{+y10, +r10}: 598 match r10: 599 case Nil{}: 600 li.mask_mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Nil{}}}}}}}}}}}}) 601 case Con{+y11, +r11}: 602 match r11: 603 case Nil{}: 604 li.mask_mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Nil{}}}}}}}}}}}}}) 605 case Con{+y12, +r12}: 606 match r12: 607 case Nil{}: 608 li.mask_mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Nil{}}}}}}}}}}}}}}) 609 case Con{+y13, +r13}: 610 match r13: 611 case Nil{}: 612 li.mask_mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Nil{}}}}}}}}}}}}}}}) 613 case Con{+y14, +r14}: 614 match r14: 615 case Nil{}: 616 li.mask_mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Con{y14, Nil{}}}}}}}}}}}}}}}}) 617 case Con{+y15, +t}: 618 %Equal.sym(List<&2, U32>, M.cm.split.tail(M.cm.split.cons(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split(B.mask(t)))), M.cm.split.tail(M.cm.split(B.mask(t))), sp.cons_tail(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split(B.mask(t)))) : {B.mask(_) == _ : List<&2, U32>} 619 sp.tail_masked(t) 620 621 # a byte string of at least 16 bytes has a first block 622 def sp.nonempty(ys: List<&2, U32>) -> {Nat.is_le(16n, B.len(ys)) == True{} : Bool} -> {Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(ys)))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(ys))))} == M.cm.split.blocks(M.cm.split(B.mask(ys))) : List<&2, M.CmBlock>}: 623 match ys: 624 case Nil{}: 625 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Nil{})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Nil{}))))} == M.cm.split.blocks(M.cm.split(B.mask(Nil{}))) : List<&2, M.CmBlock>}, h) 626 case Con{+y0, +r0}: 627 match r0: 628 case Nil{}: 629 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Nil{}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Nil{}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Nil{}}))) : List<&2, M.CmBlock>}, h) 630 case Con{+y1, +r1}: 631 match r1: 632 case Nil{}: 633 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Nil{}}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Nil{}}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Nil{}}}))) : List<&2, M.CmBlock>}, h) 634 case Con{+y2, +r2}: 635 match r2: 636 case Nil{}: 637 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Nil{}}}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Nil{}}}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Nil{}}}}))) : List<&2, M.CmBlock>}, h) 638 case Con{+y3, +r3}: 639 match r3: 640 case Nil{}: 641 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Nil{}}}}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Nil{}}}}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Nil{}}}}}))) : List<&2, M.CmBlock>}, h) 642 case Con{+y4, +r4}: 643 match r4: 644 case Nil{}: 645 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Nil{}}}}}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Nil{}}}}}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Nil{}}}}}}))) : List<&2, M.CmBlock>}, h) 646 case Con{+y5, +r5}: 647 match r5: 648 case Nil{}: 649 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Nil{}}}}}}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Nil{}}}}}}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Nil{}}}}}}}))) : List<&2, M.CmBlock>}, h) 650 case Con{+y6, +r6}: 651 match r6: 652 case Nil{}: 653 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Nil{}}}}}}}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Nil{}}}}}}}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Nil{}}}}}}}}))) : List<&2, M.CmBlock>}, h) 654 case Con{+y7, +r7}: 655 match r7: 656 case Nil{}: 657 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Nil{}}}}}}}}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Nil{}}}}}}}}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Nil{}}}}}}}}}))) : List<&2, M.CmBlock>}, h) 658 case Con{+y8, +r8}: 659 match r8: 660 case Nil{}: 661 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Nil{}}}}}}}}}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Nil{}}}}}}}}}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Nil{}}}}}}}}}}))) : List<&2, M.CmBlock>}, h) 662 case Con{+y9, +r9}: 663 match r9: 664 case Nil{}: 665 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Nil{}}}}}}}}}}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Nil{}}}}}}}}}}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Nil{}}}}}}}}}}}))) : List<&2, M.CmBlock>}, h) 666 case Con{+y10, +r10}: 667 match r10: 668 case Nil{}: 669 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Nil{}}}}}}}}}}}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Nil{}}}}}}}}}}}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Nil{}}}}}}}}}}}}))) : List<&2, M.CmBlock>}, h) 670 case Con{+y11, +r11}: 671 match r11: 672 case Nil{}: 673 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Nil{}}}}}}}}}}}}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Nil{}}}}}}}}}}}}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Nil{}}}}}}}}}}}}}))) : List<&2, M.CmBlock>}, h) 674 case Con{+y12, +r12}: 675 match r12: 676 case Nil{}: 677 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Nil{}}}}}}}}}}}}}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Nil{}}}}}}}}}}}}}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Nil{}}}}}}}}}}}}}}))) : List<&2, M.CmBlock>}, h) 678 case Con{+y13, +r13}: 679 match r13: 680 case Nil{}: 681 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Nil{}}}}}}}}}}}}}}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Nil{}}}}}}}}}}}}}}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Nil{}}}}}}}}}}}}}}}))) : List<&2, M.CmBlock>}, h) 682 case Con{+y14, +r14}: 683 match r14: 684 case Nil{}: 685 h => bo.absurd({Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Con{y14, Nil{}}}}}}}}}}}}}}}})))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Con{y14, Nil{}}}}}}}}}}}}}}}}))))} == M.cm.split.blocks(M.cm.split(B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Con{y14, Nil{}}}}}}}}}}}}}}}}))) : List<&2, M.CmBlock>}, h) 686 case Con{+y15, +t}: 687 h => %Equal.sym(List<&2, M.CmBlock>, M.cm.split.blocks(M.cm.split.cons(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split(B.mask(t)))), Con{M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split.blocks(M.cm.split(B.mask(t)))}, sp.cons_blocks(M.cm.block16(B.byte(y0), B.byte(y1), B.byte(y2), B.byte(y3), B.byte(y4), B.byte(y5), B.byte(y6), B.byte(y7), B.byte(y8), B.byte(y9), B.byte(y10), B.byte(y11), B.byte(y12), B.byte(y13), B.byte(y14), B.byte(y15)), M.cm.split(B.mask(t)))) : {Con{sp.hd(_), sp.tl(_)} == _ : List<&2, M.CmBlock>} 688 {==} 689 690 # fewer than 16 bytes are all tail 691 def sp.short_split(ys: List<&2, U32>) -> {Nat.is_lt(B.len(ys), 16n) == True{} : Bool} -> {M.cm.split(ys) == M.CmSplit{Nil{}, ys} : M.CmSplit}: 692 match ys: 693 case Nil{}: 694 h => {==} 695 case Con{+y0, +r0}: 696 match r0: 697 case Nil{}: 698 h => {==} 699 case Con{+y1, +r1}: 700 match r1: 701 case Nil{}: 702 h => {==} 703 case Con{+y2, +r2}: 704 match r2: 705 case Nil{}: 706 h => {==} 707 case Con{+y3, +r3}: 708 match r3: 709 case Nil{}: 710 h => {==} 711 case Con{+y4, +r4}: 712 match r4: 713 case Nil{}: 714 h => {==} 715 case Con{+y5, +r5}: 716 match r5: 717 case Nil{}: 718 h => {==} 719 case Con{+y6, +r6}: 720 match r6: 721 case Nil{}: 722 h => {==} 723 case Con{+y7, +r7}: 724 match r7: 725 case Nil{}: 726 h => {==} 727 case Con{+y8, +r8}: 728 match r8: 729 case Nil{}: 730 h => {==} 731 case Con{+y9, +r9}: 732 match r9: 733 case Nil{}: 734 h => {==} 735 case Con{+y10, +r10}: 736 match r10: 737 case Nil{}: 738 h => {==} 739 case Con{+y11, +r11}: 740 match r11: 741 case Nil{}: 742 h => {==} 743 case Con{+y12, +r12}: 744 match r12: 745 case Nil{}: 746 h => {==} 747 case Con{+y13, +r13}: 748 match r13: 749 case Nil{}: 750 h => {==} 751 case Con{+y14, +r14}: 752 match r14: 753 case Nil{}: 754 h => {==} 755 case Con{+y15, +t}: 756 match t: 757 case Nil{}: 758 h => bo.absurd({M.cm.split(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Con{y14, Con{y15, Nil{}}}}}}}}}}}}}}}}}) == M.CmSplit{Nil{}, Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Con{y14, Con{y15, Nil{}}}}}}}}}}}}}}}}}} : M.CmSplit}, h) 759 case Con{+z, +zs}: 760 h => bo.absurd({M.cm.split(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Con{y14, Con{y15, Con{z, zs}}}}}}}}}}}}}}}}}) == M.CmSplit{Nil{}, Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Con{y14, Con{y15, Con{z, zs}}}}}}}}}}}}}}}}}} : M.CmSplit}, h) 761 762 # a block of exactly 16 bytes gives them back, masked 763 def sp.bb16(ys: List<&2, U32>) -> {Nat.is_eq(B.len(ys), 16n) == True{} : Bool} -> {M.cm.bytes_of(M.cm.block_of(ys)) == B.mask(ys) : List<&2, U32>}: 764 match ys: 765 case Nil{}: 766 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Nil{})) == B.mask(Nil{}) : List<&2, U32>}, h) 767 case Con{+y0, +r0}: 768 match r0: 769 case Nil{}: 770 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Nil{}})) == B.mask(Con{y0, Nil{}}) : List<&2, U32>}, h) 771 case Con{+y1, +r1}: 772 match r1: 773 case Nil{}: 774 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Nil{}}})) == B.mask(Con{y0, Con{y1, Nil{}}}) : List<&2, U32>}, h) 775 case Con{+y2, +r2}: 776 match r2: 777 case Nil{}: 778 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Con{y2, Nil{}}}})) == B.mask(Con{y0, Con{y1, Con{y2, Nil{}}}}) : List<&2, U32>}, h) 779 case Con{+y3, +r3}: 780 match r3: 781 case Nil{}: 782 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Con{y2, Con{y3, Nil{}}}}})) == B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Nil{}}}}}) : List<&2, U32>}, h) 783 case Con{+y4, +r4}: 784 match r4: 785 case Nil{}: 786 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Nil{}}}}}})) == B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Nil{}}}}}}) : List<&2, U32>}, h) 787 case Con{+y5, +r5}: 788 match r5: 789 case Nil{}: 790 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Nil{}}}}}}})) == B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Nil{}}}}}}}) : List<&2, U32>}, h) 791 case Con{+y6, +r6}: 792 match r6: 793 case Nil{}: 794 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Nil{}}}}}}}})) == B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Nil{}}}}}}}}) : List<&2, U32>}, h) 795 case Con{+y7, +r7}: 796 match r7: 797 case Nil{}: 798 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Nil{}}}}}}}}})) == B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Nil{}}}}}}}}}) : List<&2, U32>}, h) 799 case Con{+y8, +r8}: 800 match r8: 801 case Nil{}: 802 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Nil{}}}}}}}}}})) == B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Nil{}}}}}}}}}}) : List<&2, U32>}, h) 803 case Con{+y9, +r9}: 804 match r9: 805 case Nil{}: 806 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Nil{}}}}}}}}}}})) == B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Nil{}}}}}}}}}}}) : List<&2, U32>}, h) 807 case Con{+y10, +r10}: 808 match r10: 809 case Nil{}: 810 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Nil{}}}}}}}}}}}})) == B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Nil{}}}}}}}}}}}}) : List<&2, U32>}, h) 811 case Con{+y11, +r11}: 812 match r11: 813 case Nil{}: 814 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Nil{}}}}}}}}}}}}})) == B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Nil{}}}}}}}}}}}}}) : List<&2, U32>}, h) 815 case Con{+y12, +r12}: 816 match r12: 817 case Nil{}: 818 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Nil{}}}}}}}}}}}}}})) == B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Nil{}}}}}}}}}}}}}}) : List<&2, U32>}, h) 819 case Con{+y13, +r13}: 820 match r13: 821 case Nil{}: 822 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Nil{}}}}}}}}}}}}}}})) == B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Nil{}}}}}}}}}}}}}}}) : List<&2, U32>}, h) 823 case Con{+y14, +r14}: 824 match r14: 825 case Nil{}: 826 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Con{y14, Nil{}}}}}}}}}}}}}}}})) == B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Con{y14, Nil{}}}}}}}}}}}}}}}}) : List<&2, U32>}, h) 827 case Con{+y15, +t}: 828 match t: 829 case Nil{}: 830 h => sp.blk16g(y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15, Nil{}) 831 case Con{+z, +zs}: 832 h => bo.absurd({M.cm.bytes_of(M.cm.block_of(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Con{y14, Con{y15, Con{z, zs}}}}}}}}}}}}}}}}})) == B.mask(Con{y0, Con{y1, Con{y2, Con{y3, Con{y4, Con{y5, Con{y6, Con{y7, Con{y8, Con{y9, Con{y10, Con{y11, Con{y12, Con{y13, Con{y14, Con{y15, Con{z, zs}}}}}}}}}}}}}}}}}) : List<&2, U32>}, h) 833 834 # the block of a block's bytes is the block 835 def sp.block_bytes(b: M.CmBlock) -> {M.cm.block_of(M.cm.bytes_of(b)) == b : M.CmBlock}: 836 match b: 837 case M.CmBlock{U32{WCon{p0, WCon{p1, WCon{p2, WCon{p3, WCon{p4, WCon{p5, WCon{p6, WCon{p7, WCon{p8, WCon{p9, WCon{p10, WCon{p11, WCon{p12, WCon{p13, WCon{p14, WCon{p15, WCon{p16, WCon{p17, WCon{p18, WCon{p19, WCon{p20, WCon{p21, WCon{p22, WCon{p23, WCon{p24, WCon{p25, WCon{p26, WCon{p27, WCon{p28, WCon{p29, WCon{p30, WCon{p31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, U32{WCon{q0, WCon{q1, WCon{q2, WCon{q3, WCon{q4, WCon{q5, WCon{q6, WCon{q7, WCon{q8, WCon{q9, WCon{q10, WCon{q11, WCon{q12, WCon{q13, WCon{q14, WCon{q15, WCon{q16, WCon{q17, WCon{q18, WCon{q19, WCon{q20, WCon{q21, WCon{q22, WCon{q23, WCon{q24, WCon{q25, WCon{q26, WCon{q27, WCon{q28, WCon{q29, WCon{q30, WCon{q31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, U32{WCon{r0, WCon{r1, WCon{r2, WCon{r3, WCon{r4, WCon{r5, WCon{r6, WCon{r7, WCon{r8, WCon{r9, WCon{r10, WCon{r11, WCon{r12, WCon{r13, WCon{r14, WCon{r15, WCon{r16, WCon{r17, WCon{r18, WCon{r19, WCon{r20, WCon{r21, WCon{r22, WCon{r23, WCon{r24, WCon{r25, WCon{r26, WCon{r27, WCon{r28, WCon{r29, WCon{r30, WCon{r31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, U32{WCon{s0, WCon{s1, WCon{s2, WCon{s3, WCon{s4, WCon{s5, WCon{s6, WCon{s7, WCon{s8, WCon{s9, WCon{s10, WCon{s11, WCon{s12, WCon{s13, WCon{s14, WCon{s15, WCon{s16, WCon{s17, WCon{s18, WCon{s19, WCon{s20, WCon{s21, WCon{s22, WCon{s23, WCon{s24, WCon{s25, WCon{s26, WCon{s27, WCon{s28, WCon{s29, WCon{s30, WCon{s31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}: 838 {==} 839 840 # Joining and splitting 841 842 def sp.split_join(bs: List<&2, M.CmBlock>) -> {M.cm.split(M.cm.join_onto(bs, Nil{})) == M.CmSplit{bs, Nil{}} : M.CmSplit}: 843 match bs: 844 case Nil{}: 845 {==} 846 case Con{+b, +t}: 847 %Equal.sym(M.CmSplit, M.cm.split(M.cm.bytes_onto(b, M.cm.join_onto(t, Nil{}))), M.cm.split.cons(b, M.cm.split(M.cm.join_onto(t, Nil{}))), sp.blk(b, M.cm.join_onto(t, Nil{}))) : {_ == M.CmSplit{Con{b, t}, Nil{}} : M.CmSplit} 848 %Equal.sym(M.CmSplit, M.cm.split(M.cm.join_onto(t, Nil{})), M.CmSplit{t, Nil{}}, sp.split_join(t)) : {M.cm.split.cons(b, _) == M.CmSplit{Con{b, t}, Nil{}} : M.CmSplit} 849 {==} 850 851 def sp.mask_join(bs: List<&2, M.CmBlock>) -> {B.mask(M.cm.join_onto(bs, Nil{})) == M.cm.join_onto(bs, Nil{}) : List<&2, U32>}: 852 match bs: 853 case Nil{}: 854 {==} 855 case Con{+b, +t}: 856 %Equal.sym(List<&2, U32>, B.mask(M.cm.bytes_onto(b, M.cm.join_onto(t, Nil{}))), M.cm.bytes_onto(b, B.mask(M.cm.join_onto(t, Nil{}))), sp.mask_blk(b, M.cm.join_onto(t, Nil{}))) : {_ == M.cm.bytes_onto(b, M.cm.join_onto(t, Nil{})) : List<&2, U32>} 857 %Equal.sym(List<&2, U32>, B.mask(M.cm.join_onto(t, Nil{})), M.cm.join_onto(t, Nil{}), sp.mask_join(t)) : {M.cm.bytes_onto(b, _) == M.cm.bytes_onto(b, M.cm.join_onto(t, Nil{})) : List<&2, U32>} 858 {==} 859 860 # Every Octets is masked: to_list(o) = to_list(of_list(to_list(o))) = mask(to_list(o)) 861 def oc.masked(+o: B.Octets) -> {B.mask(B.Octets.to_list(o)) == B.Octets.to_list(o) : List<&2, U32>}: 862 Equal.trans(List<&2, U32>, B.mask(B.Octets.to_list(o)), B.Octets.to_list(B.Octets.of_list(B.Octets.to_list(o))), B.Octets.to_list(o), Equal.sym(List<&2, U32>, B.Octets.to_list(B.Octets.of_list(B.Octets.to_list(o))), B.mask(B.Octets.to_list(o)), BL.octets_to_of(B.Octets.to_list(o))), Equal.cong(B.Octets, List<&2, U32>, x => B.Octets.to_list(x), B.Octets.of_list(B.Octets.to_list(o)), o, BL.octets_of_to(o))) 863 864 def oc.len(+o: B.Octets, +n: Nat, h: {B.Octets.len(o) == n : Nat}) -> {B.len(B.Octets.to_list(o)) == n : Nat}: 865 Equal.trans(Nat, B.len(B.Octets.to_list(o)), B.Octets.len(o), n, Equal.sym(Nat, B.Octets.len(o), B.len(B.Octets.to_list(o)), BL.octets_len_list(o)), h) 866 867 def oc.mod(+o: B.Octets, h: {Nat.mod(B.Octets.len(o), 16n) == 0n : Nat}) -> {Nat.mod(B.len(B.Octets.to_list(o)), 16n) == 0n : Nat}: 868 Equal.trans(Nat, Nat.mod(B.len(B.Octets.to_list(o)), 16n), Nat.mod(B.Octets.len(o), 16n), 0n, Equal.sym(Nat, Nat.mod(B.Octets.len(o), 16n), Nat.mod(B.len(B.Octets.to_list(o)), 16n), Equal.cong(Nat, Nat, n => Nat.mod(n, 16n), B.Octets.len(o), B.len(B.Octets.to_list(o)), BL.octets_len_list(o))), h) 869 870 # a 16-byte IV is the block of its bytes 871 def cbcp.iv(+iv: B.Octets, h: {B.Octets.len(iv) == 16n : Nat}) -> {C.cbc.iv(iv) == Done{M.cm.block_of(B.Octets.to_list(iv))} : Result<&2, &2, M.CmError, M.CmBlock>}: 872 %Equal.sym(Nat, B.len(B.Octets.to_list(iv)), 16n, oc.len(iv, 16n, h)) : {M.cm.need_block.pick(Nat.is_eq(_, 16n), B.Octets.to_list(iv), M.CmBadIvLength{B.len(B.Octets.to_list(iv))}) == Done{M.cm.block_of(B.Octets.to_list(iv))} : Result<&2, &2, M.CmError, M.CmBlock>} 873 {==} 874 875 876 # The tail-recursive forms the modes run are the structural ones, for every 877 # input: each loop with an accumulator is its structural form reversed onto 878 # the accumulator, and reversing twice gives the order back. Then the byte 879 # layers built from them are the structural byte layers, and so are the 880 # public defs (Cbc.encrypt == Cbc.encrypt.ref, ...). 881 882 def tr.add_succ(+a: Nat, +n: Nat) -> {Nat.add(a, 1n+n) == 1n+Nat.add(a, n) : Nat}: 883 match a: 884 case 0n: 885 {==} 886 case 1n+q: 887 Equal.cong(Nat, Nat, x => 1n+x, Nat.add(q, 1n+n), 1n+Nat.add(q, n), tr.add_succ(q, n)) 888 889 def tr.add_zero(+a: Nat) -> {Nat.add(a, 0n) == a : Nat}: 890 match a: 891 case 0n: 892 {==} 893 case 1n+q: 894 Equal.cong(Nat, Nat, x => 1n+x, Nat.add(q, 0n), q, tr.add_zero(q)) 895 896 def tr.rr(xs: List<&2, M.CmBlock>, acc: List<&2, M.CmBlock>, b: List<&2, M.CmBlock>) -> {M.cm.blocks.rev_onto(M.cm.blocks.rev_onto(xs, acc), b) == M.cm.blocks.rev_onto(acc, List.append(&2, M.CmBlock, xs, b)) : List<&2, M.CmBlock>}: 897 match xs: 898 case Nil{}: 899 {==} 900 case Con{h, t}: 901 tr.rr(t, Con{h, acc}, b) 902 903 def tr.append_eq(+xs: List<&2, M.CmBlock>, +ys: List<&2, M.CmBlock>) -> {List.append(&2, M.CmBlock, xs, ys) == M.cm.blocks.append(xs, ys) : List<&2, M.CmBlock>}: 904 Equal.sym(List<&2, M.CmBlock>, M.cm.blocks.append(xs, ys), List.append(&2, M.CmBlock, xs, ys), tr.rr(xs, Nil{}, ys)) 905 906 def tr.len_go(+bs: List<&2, M.CmBlock>, +n: Nat) -> {M.cm.blocks.len.go(bs, n) == Nat.add(List.length(&2, M.CmBlock, bs), n) : Nat}: 907 match bs: 908 case Nil{}: 909 {==} 910 case Con{h, t}: 911 Equal.trans(Nat, M.cm.blocks.len.go(t, 1n+n), Nat.add(List.length(&2, M.CmBlock, t), 1n+n), 1n+Nat.add(List.length(&2, M.CmBlock, t), n), tr.len_go(t, 1n+n), tr.add_succ(List.length(&2, M.CmBlock, t), n)) 912 913 def tr.len_eq(+bs: List<&2, M.CmBlock>) -> {List.length(&2, M.CmBlock, bs) == M.cm.blocks.len(bs) : Nat}: 914 Equal.sym(Nat, M.cm.blocks.len(bs), List.length(&2, M.CmBlock, bs), Equal.trans(Nat, M.cm.blocks.len.go(bs, 0n), Nat.add(List.length(&2, M.CmBlock, bs), 0n), List.length(&2, M.CmBlock, bs), tr.len_go(bs, 0n), tr.add_zero(List.length(&2, M.CmBlock, bs)))) 915 916 # Splitting: the blocks so far, reversed in acc, go in front of the 917 # structural split's blocks 918 919 def tr.split_fin(acc: List<&2, M.CmBlock>, s: M.CmSplit) -> M.CmSplit: 920 match s: 921 case M.CmSplit{bs, t}: 922 M.CmSplit{M.cm.blocks.rev_onto(acc, bs), t} 923 924 def tr.split_fin_cons(+b: M.CmBlock, +acc: List<&2, M.CmBlock>, +s: M.CmSplit) -> {tr.split_fin(Con{b, acc}, s) == tr.split_fin(acc, M.cm.split.cons(b, s)) : M.CmSplit}: 925 match s: 926 case M.CmSplit{bs, t}: 927 {==} 928 929 def tr.split_fin_nil(+s: M.CmSplit) -> {tr.split_fin(Nil{}, s) == s : M.CmSplit}: 930 match s: 931 case M.CmSplit{bs, t}: 932 {==} 933 934 def tr.split_go(+xs: List<&2, U32>, +acc: List<&2, M.CmBlock>) -> {M.cm.split.go(xs, acc) == tr.split_fin(acc, M.cm.split(xs)) : M.CmSplit}: 935 match xs: 936 case Nil{}: 937 {==} 938 case Con{+y0, +r0}: 939 match r0: 940 case Nil{}: 941 {==} 942 case Con{+y1, +r1}: 943 match r1: 944 case Nil{}: 945 {==} 946 case Con{+y2, +r2}: 947 match r2: 948 case Nil{}: 949 {==} 950 case Con{+y3, +r3}: 951 match r3: 952 case Nil{}: 953 {==} 954 case Con{+y4, +r4}: 955 match r4: 956 case Nil{}: 957 {==} 958 case Con{+y5, +r5}: 959 match r5: 960 case Nil{}: 961 {==} 962 case Con{+y6, +r6}: 963 match r6: 964 case Nil{}: 965 {==} 966 case Con{+y7, +r7}: 967 match r7: 968 case Nil{}: 969 {==} 970 case Con{+y8, +r8}: 971 match r8: 972 case Nil{}: 973 {==} 974 case Con{+y9, +r9}: 975 match r9: 976 case Nil{}: 977 {==} 978 case Con{+y10, +r10}: 979 match r10: 980 case Nil{}: 981 {==} 982 case Con{+y11, +r11}: 983 match r11: 984 case Nil{}: 985 {==} 986 case Con{+y12, +r12}: 987 match r12: 988 case Nil{}: 989 {==} 990 case Con{+y13, +r13}: 991 match r13: 992 case Nil{}: 993 {==} 994 case Con{+y14, +r14}: 995 match r14: 996 case Nil{}: 997 {==} 998 case Con{+y15, +t}: 999 Equal.trans(M.CmSplit, M.cm.split.go(t, Con{M.cm.block16(y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15), acc}), tr.split_fin(Con{M.cm.block16(y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15), acc}, M.cm.split(t)), tr.split_fin(acc, M.cm.split.cons(M.cm.block16(y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15), M.cm.split(t))), tr.split_go(t, Con{M.cm.block16(y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15), acc}), tr.split_fin_cons(M.cm.block16(y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15), acc, M.cm.split(t))) 1000 1001 def tr.split_eq(+xs: List<&2, U32>) -> {M.cm.split(xs) == M.cm.split.fast(xs) : M.CmSplit}: 1002 Equal.sym(M.CmSplit, M.cm.split.fast(xs), M.cm.split(xs), Equal.trans(M.CmSplit, M.cm.split.go(xs, Nil{}), tr.split_fin(Nil{}, M.cm.split(xs)), M.cm.split(xs), tr.split_go(xs, Nil{}), tr.split_fin_nil(M.cm.split(xs)))) 1003 1004 # Joining 1005 1006 def tr.join_go(xs: List<&2, M.CmBlock>, rs: List<&2, M.CmBlock>, +rest: List<&2, U32>) -> {M.cm.join.go(M.cm.blocks.rev_onto(xs, rs), rest) == M.cm.join.go(rs, M.cm.join_onto(xs, rest)) : List<&2, U32>}: 1007 match xs: 1008 case Nil{}: 1009 {==} 1010 case Con{x, t}: 1011 tr.join_go(t, Con{x, rs}, rest) 1012 1013 def tr.join_eq(+bs: List<&2, M.CmBlock>, +rest: List<&2, U32>) -> {M.cm.join_onto(bs, rest) == M.cm.join_onto.fast(bs, rest) : List<&2, U32>}: 1014 Equal.sym(List<&2, U32>, M.cm.join_onto.fast(bs, rest), M.cm.join_onto(bs, rest), tr.join_go(bs, Nil{}, rest)) 1015 1016 # The modes on blocks 1017 1018 def tr.cbc_enc_go(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, bs: List<&2, M.CmBlock>, +iv: M.CmBlock, +acc: List<&2, M.CmBlock>) -> {C.cbc.enc.go(~K, ~enc, k, bs, iv, acc) == M.cm.blocks.rev_onto(acc, C.cbc.enc(~K, ~enc, k, bs, iv)) : List<&2, M.CmBlock>}: 1019 match bs: 1020 case Nil{}: 1021 {==} 1022 case Con{+p, +t}: 1023 tr.cbc_enc_go(~K, ~enc, k, t, enc(k, M.CmBlock.xor(iv, p)), Con{enc(k, M.CmBlock.xor(iv, p)), acc}) 1024 1025 def tr.cbc_enc_eq(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +bs: List<&2, M.CmBlock>, +iv: M.CmBlock) -> {C.cbc.enc(~K, ~enc, k, bs, iv) == C.cbc.enc.fast(~K, ~enc, k, bs, iv) : List<&2, M.CmBlock>}: 1026 Equal.sym(List<&2, M.CmBlock>, C.cbc.enc.fast(~K, ~enc, k, bs, iv), C.cbc.enc(~K, ~enc, k, bs, iv), tr.cbc_enc_go(~K, ~enc, k, bs, iv, Nil{})) 1027 1028 def tr.cbc_dec_go(~K: Data, ~dec: K -> M.CmBlock -> M.CmBlock, +k: K, bs: List<&2, M.CmBlock>, +iv: M.CmBlock, +acc: List<&2, M.CmBlock>) -> {C.cbc.dec.go(~K, ~dec, k, bs, iv, acc) == M.cm.blocks.rev_onto(acc, C.cbc.dec(~K, ~dec, k, bs, iv)) : List<&2, M.CmBlock>}: 1029 match bs: 1030 case Nil{}: 1031 {==} 1032 case Con{+c, +t}: 1033 tr.cbc_dec_go(~K, ~dec, k, t, c, Con{M.CmBlock.xor(iv, dec(k, c)), acc}) 1034 1035 def tr.cbc_dec_eq(~K: Data, ~dec: K -> M.CmBlock -> M.CmBlock, +k: K, +bs: List<&2, M.CmBlock>, +iv: M.CmBlock) -> {C.cbc.dec(~K, ~dec, k, bs, iv) == C.cbc.dec.fast(~K, ~dec, k, bs, iv) : List<&2, M.CmBlock>}: 1036 Equal.sym(List<&2, M.CmBlock>, C.cbc.dec.fast(~K, ~dec, k, bs, iv), C.cbc.dec(~K, ~dec, k, bs, iv), tr.cbc_dec_go(~K, ~dec, k, bs, iv, Nil{})) 1037 1038 def tr.xts_enc_go(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, bs: List<&2, M.CmBlock>, +t: M.CmBlock, +acc: List<&2, M.CmBlock>) -> {T.xts.enc.go(~K, ~enc, k, bs, t, acc) == M.cm.blocks.rev_onto(acc, T.xts.enc(~K, ~enc, k, bs, t)) : List<&2, M.CmBlock>}: 1039 match bs: 1040 case Nil{}: 1041 {==} 1042 case Con{+p, +rest}: 1043 tr.xts_enc_go(~K, ~enc, k, rest, T.Xts.mul_alpha(t), Con{T.xts.benc(~K, ~enc, k, p, t), acc}) 1044 1045 def tr.xts_enc_eq(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +bs: List<&2, M.CmBlock>, +t: M.CmBlock) -> {T.xts.enc(~K, ~enc, k, bs, t) == T.xts.enc.fast(~K, ~enc, k, bs, t) : List<&2, M.CmBlock>}: 1046 Equal.sym(List<&2, M.CmBlock>, T.xts.enc.fast(~K, ~enc, k, bs, t), T.xts.enc(~K, ~enc, k, bs, t), tr.xts_enc_go(~K, ~enc, k, bs, t, Nil{})) 1047 1048 def tr.xts_dec_go(~K: Data, ~dec: K -> M.CmBlock -> M.CmBlock, +k: K, bs: List<&2, M.CmBlock>, +t: M.CmBlock, +acc: List<&2, M.CmBlock>) -> {T.xts.dec.go(~K, ~dec, k, bs, t, acc) == M.cm.blocks.rev_onto(acc, T.xts.dec(~K, ~dec, k, bs, t)) : List<&2, M.CmBlock>}: 1049 match bs: 1050 case Nil{}: 1051 {==} 1052 case Con{+c, +rest}: 1053 tr.xts_dec_go(~K, ~dec, k, rest, T.Xts.mul_alpha(t), Con{T.xts.bdec(~K, ~dec, k, c, t), acc}) 1054 1055 def tr.xts_dec_eq(~K: Data, ~dec: K -> M.CmBlock -> M.CmBlock, +k: K, +bs: List<&2, M.CmBlock>, +t: M.CmBlock) -> {T.xts.dec(~K, ~dec, k, bs, t) == T.xts.dec.fast(~K, ~dec, k, bs, t) : List<&2, M.CmBlock>}: 1056 Equal.sym(List<&2, M.CmBlock>, T.xts.dec.fast(~K, ~dec, k, bs, t), T.xts.dec(~K, ~dec, k, bs, t), tr.xts_dec_go(~K, ~dec, k, bs, t, Nil{})) 1057 1058 def tr.init_go(rest: List<&2, M.CmBlock>, +p: M.CmBlock, +acc: List<&2, M.CmBlock>) -> {T.xts.init.go(rest, p, acc) == M.cm.blocks.rev_onto(acc, T.xts.init(rest, p)) : List<&2, M.CmBlock>}: 1059 match rest: 1060 case Nil{}: 1061 {==} 1062 case Con{+q, +r}: 1063 tr.init_go(r, q, Con{p, acc}) 1064 1065 def tr.init_eq(+rest: List<&2, M.CmBlock>, +p: M.CmBlock) -> {T.xts.init(rest, p) == T.xts.init.fast(rest, p) : List<&2, M.CmBlock>}: 1066 Equal.sym(List<&2, M.CmBlock>, T.xts.init.fast(rest, p), T.xts.init(rest, p), tr.init_go(rest, p, Nil{})) 1067 1068 # The byte layers 1069 1070 def tr.cbc_e2(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +v: M.CmBlock, s: M.CmSplit, +n: Nat) -> {C.cbc.e2(~K, ~enc, k, v, s, n) == C.cbc.e2.fast(~K, ~enc, k, v, s, n) : Result<&2, &2, M.CmError, B.Octets>}: 1071 match s: 1072 case M.CmSplit{+bs, tail}: 1073 match tail: 1074 case Nil{}: 1075 %tr.cbc_enc_eq(~K, ~enc, k, bs, v) : {Done{B.Octets.of_list(M.cm.join_onto(C.cbc.enc(~K, ~enc, k, bs, v), Nil{}))} == Done{B.Octets.of_list(M.cm.join_onto.fast(_, Nil{}))} : Result<&2, &2, M.CmError, B.Octets>} 1076 %tr.join_eq(C.cbc.enc(~K, ~enc, k, bs, v), Nil{}) : {Done{B.Octets.of_list(M.cm.join_onto(C.cbc.enc(~K, ~enc, k, bs, v), Nil{}))} == Done{B.Octets.of_list(_)} : Result<&2, &2, M.CmError, B.Octets>} 1077 {==} 1078 case Con{h, t}: 1079 {==} 1080 1081 def tr.cbc_e1(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, r: Result<&2, &2, M.CmError, M.CmBlock>, +xs: List<&2, U32>) -> {C.cbc.e1(~K, ~enc, k, r, xs) == C.cbc.e1.fast(~K, ~enc, k, r, xs) : Result<&2, &2, M.CmError, B.Octets>}: 1082 match r: 1083 case Fail{e}: 1084 {==} 1085 case Done{+v}: 1086 %tr.split_eq(xs) : {C.cbc.e2(~K, ~enc, k, v, M.cm.split(xs), B.len(xs)) == C.cbc.e2.fast(~K, ~enc, k, v, _, B.len.fast(xs)) : Result<&2, &2, M.CmError, B.Octets>} 1087 %BL.len_fast(xs) : {C.cbc.e2(~K, ~enc, k, v, M.cm.split(xs), B.len(xs)) == C.cbc.e2.fast(~K, ~enc, k, v, M.cm.split(xs), _) : Result<&2, &2, M.CmError, B.Octets>} 1088 tr.cbc_e2(~K, ~enc, k, v, M.cm.split(xs), B.len(xs)) 1089 1090 def tr.cbc_d2(~K: Data, ~dec: K -> M.CmBlock -> M.CmBlock, +k: K, +v: M.CmBlock, s: M.CmSplit, +n: Nat) -> {C.cbc.d2(~K, ~dec, k, v, s, n) == C.cbc.d2.fast(~K, ~dec, k, v, s, n) : Result<&2, &2, M.CmError, B.Octets>}: 1091 match s: 1092 case M.CmSplit{+bs, tail}: 1093 match tail: 1094 case Nil{}: 1095 %tr.cbc_dec_eq(~K, ~dec, k, bs, v) : {Done{B.Octets.of_list(M.cm.join_onto(C.cbc.dec(~K, ~dec, k, bs, v), Nil{}))} == Done{B.Octets.of_list(M.cm.join_onto.fast(_, Nil{}))} : Result<&2, &2, M.CmError, B.Octets>} 1096 %tr.join_eq(C.cbc.dec(~K, ~dec, k, bs, v), Nil{}) : {Done{B.Octets.of_list(M.cm.join_onto(C.cbc.dec(~K, ~dec, k, bs, v), Nil{}))} == Done{B.Octets.of_list(_)} : Result<&2, &2, M.CmError, B.Octets>} 1097 {==} 1098 case Con{h, t}: 1099 {==} 1100 1101 def tr.cbc_d1(~K: Data, ~dec: K -> M.CmBlock -> M.CmBlock, +k: K, r: Result<&2, &2, M.CmError, M.CmBlock>, +xs: List<&2, U32>) -> {C.cbc.d1(~K, ~dec, k, r, xs) == C.cbc.d1.fast(~K, ~dec, k, r, xs) : Result<&2, &2, M.CmError, B.Octets>}: 1102 match r: 1103 case Fail{e}: 1104 {==} 1105 case Done{+v}: 1106 %tr.split_eq(xs) : {C.cbc.d2(~K, ~dec, k, v, M.cm.split(xs), B.len(xs)) == C.cbc.d2.fast(~K, ~dec, k, v, _, B.len.fast(xs)) : Result<&2, &2, M.CmError, B.Octets>} 1107 %BL.len_fast(xs) : {C.cbc.d2(~K, ~dec, k, v, M.cm.split(xs), B.len(xs)) == C.cbc.d2.fast(~K, ~dec, k, v, M.cm.split(xs), _) : Result<&2, &2, M.CmError, B.Octets>} 1108 tr.cbc_d2(~K, ~dec, k, v, M.cm.split(xs), B.len(xs)) 1109 1110 def tr.cbc_encrypt(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +iv: B.Octets, +m: B.Octets) -> {C.Cbc.encrypt.ref(~K, ~enc, k, iv, m) == C.Cbc.encrypt(~K, ~enc, k, iv, m) : Result<&2, &2, M.CmError, B.Octets>}: 1111 tr.cbc_e1(~K, ~enc, k, C.cbc.iv(iv), B.Octets.to_list(m)) 1112 1113 def tr.cbc_decrypt(~K: Data, ~dec: K -> M.CmBlock -> M.CmBlock, +k: K, +iv: B.Octets, +c: B.Octets) -> {C.Cbc.decrypt.ref(~K, ~dec, k, iv, c) == C.Cbc.decrypt(~K, ~dec, k, iv, c) : Result<&2, &2, M.CmError, B.Octets>}: 1114 tr.cbc_d1(~K, ~dec, k, C.cbc.iv(iv), B.Octets.to_list(c)) 1115 1116 def tr.xts_eout(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +t: M.CmBlock, +init: List<&2, M.CmBlock>, +last: M.CmBlock, +tail: List<&2, U32>) -> {T.xts.eout(~K, ~enc, k, t, init, last, tail) == T.xts.eout.fast(~K, ~enc, k, t, init, last, tail) : List<&2, U32>}: 1117 %tr.len_eq(init) : {T.xts.eout(~K, ~enc, k, t, init, last, tail) == M.cm.join_onto.fast(M.cm.blocks.append(T.xts.enc.fast(~K, ~enc, k, init, t), Con{T.xts.steal_c(~K, ~enc, k, last, tail, T.xts.alpha_n(_, t)), Nil{}}), T.xts.steal_t(~K, ~enc, k, last, tail, T.xts.alpha_n(_, t))) : List<&2, U32>} 1118 %tr.xts_enc_eq(~K, ~enc, k, init, t) : {T.xts.eout(~K, ~enc, k, t, init, last, tail) == M.cm.join_onto.fast(M.cm.blocks.append(_, Con{T.xts.steal_c(~K, ~enc, k, last, tail, T.xts.alpha_n(List.length(&2, M.CmBlock, init), t)), Nil{}}), T.xts.steal_t(~K, ~enc, k, last, tail, T.xts.alpha_n(List.length(&2, M.CmBlock, init), t))) : List<&2, U32>} 1119 %tr.append_eq(T.xts.enc(~K, ~enc, k, init, t), Con{T.xts.steal_c(~K, ~enc, k, last, tail, T.xts.alpha_n(List.length(&2, M.CmBlock, init), t)), Nil{}}) : {T.xts.eout(~K, ~enc, k, t, init, last, tail) == M.cm.join_onto.fast(_, T.xts.steal_t(~K, ~enc, k, last, tail, T.xts.alpha_n(List.length(&2, M.CmBlock, init), t))) : List<&2, U32>} 1120 %tr.join_eq(List.append(&2, M.CmBlock, T.xts.enc(~K, ~enc, k, init, t), Con{T.xts.steal_c(~K, ~enc, k, last, tail, T.xts.alpha_n(List.length(&2, M.CmBlock, init), t)), Nil{}}), T.xts.steal_t(~K, ~enc, k, last, tail, T.xts.alpha_n(List.length(&2, M.CmBlock, init), t))) : {T.xts.eout(~K, ~enc, k, t, init, last, tail) == _ : List<&2, U32>} 1121 {==} 1122 1123 def tr.xts_dout(~K: Data, ~dec: K -> M.CmBlock -> M.CmBlock, +k: K, +t: M.CmBlock, +init: List<&2, M.CmBlock>, +last: M.CmBlock, +tail: List<&2, U32>) -> {T.xts.dout(~K, ~dec, k, t, init, last, tail) == T.xts.dout.fast(~K, ~dec, k, t, init, last, tail) : List<&2, U32>}: 1124 %tr.len_eq(init) : {T.xts.dout(~K, ~dec, k, t, init, last, tail) == M.cm.join_onto.fast(T.xts.dec.fast(~K, ~dec, k, init, t), T.xts.dsteal(~K, ~dec, k, last, tail, T.xts.alpha_n(_, t))) : List<&2, U32>} 1125 %tr.xts_dec_eq(~K, ~dec, k, init, t) : {T.xts.dout(~K, ~dec, k, t, init, last, tail) == M.cm.join_onto.fast(_, T.xts.dsteal(~K, ~dec, k, last, tail, T.xts.alpha_n(List.length(&2, M.CmBlock, init), t))) : List<&2, U32>} 1126 %tr.join_eq(T.xts.dec(~K, ~dec, k, init, t), T.xts.dsteal(~K, ~dec, k, last, tail, T.xts.alpha_n(List.length(&2, M.CmBlock, init), t))) : {T.xts.dout(~K, ~dec, k, t, init, last, tail) == _ : List<&2, U32>} 1127 {==} 1128 1129 def tr.xts_e2(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +t: M.CmBlock, s: M.CmSplit, +n: Nat) -> {T.xts.e2(~K, ~enc, k, t, s, n) == T.xts.e2.fast(~K, ~enc, k, t, s, n) : Result<&2, &2, M.CmError, B.Octets>}: 1130 match s: 1131 case M.CmSplit{bs, +tail}: 1132 match bs: 1133 case Nil{}: 1134 {==} 1135 case Con{+p, +rest}: 1136 %tr.init_eq(rest, p) : {Done{B.Octets.of_list(T.xts.eout(~K, ~enc, k, t, T.xts.init(rest, p), T.xts.last(rest, p), tail))} == Done{B.Octets.of_list(T.xts.eout.fast(~K, ~enc, k, t, _, T.xts.last(rest, p), tail))} : Result<&2, &2, M.CmError, B.Octets>} 1137 %tr.xts_eout(~K, ~enc, k, t, T.xts.init(rest, p), T.xts.last(rest, p), tail) : {Done{B.Octets.of_list(T.xts.eout(~K, ~enc, k, t, T.xts.init(rest, p), T.xts.last(rest, p), tail))} == Done{B.Octets.of_list(_)} : Result<&2, &2, M.CmError, B.Octets>} 1138 {==} 1139 1140 def tr.xts_d2(~K: Data, ~dec: K -> M.CmBlock -> M.CmBlock, +k: K, +t: M.CmBlock, s: M.CmSplit, +n: Nat) -> {T.xts.d2(~K, ~dec, k, t, s, n) == T.xts.d2.fast(~K, ~dec, k, t, s, n) : Result<&2, &2, M.CmError, B.Octets>}: 1141 match s: 1142 case M.CmSplit{bs, +tail}: 1143 match bs: 1144 case Nil{}: 1145 {==} 1146 case Con{+c, +rest}: 1147 %tr.init_eq(rest, c) : {Done{B.Octets.of_list(T.xts.dout(~K, ~dec, k, t, T.xts.init(rest, c), T.xts.last(rest, c), tail))} == Done{B.Octets.of_list(T.xts.dout.fast(~K, ~dec, k, t, _, T.xts.last(rest, c), tail))} : Result<&2, &2, M.CmError, B.Octets>} 1148 %tr.xts_dout(~K, ~dec, k, t, T.xts.init(rest, c), T.xts.last(rest, c), tail) : {Done{B.Octets.of_list(T.xts.dout(~K, ~dec, k, t, T.xts.init(rest, c), T.xts.last(rest, c), tail))} == Done{B.Octets.of_list(_)} : Result<&2, &2, M.CmError, B.Octets>} 1149 {==} 1150 1151 def tr.xts_e1(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, r: Result<&2, &2, M.CmError, M.CmBlock>, +xs: List<&2, U32>) -> {T.xts.e1(~K, ~enc, k, r, xs) == T.xts.e1.fast(~K, ~enc, k, r, xs) : Result<&2, &2, M.CmError, B.Octets>}: 1152 match r: 1153 case Fail{e}: 1154 {==} 1155 case Done{+t}: 1156 %tr.split_eq(xs) : {T.xts.e2(~K, ~enc, k, t, M.cm.split(xs), B.len(xs)) == T.xts.e2.fast(~K, ~enc, k, t, _, B.len.fast(xs)) : Result<&2, &2, M.CmError, B.Octets>} 1157 %BL.len_fast(xs) : {T.xts.e2(~K, ~enc, k, t, M.cm.split(xs), B.len(xs)) == T.xts.e2.fast(~K, ~enc, k, t, M.cm.split(xs), _) : Result<&2, &2, M.CmError, B.Octets>} 1158 tr.xts_e2(~K, ~enc, k, t, M.cm.split(xs), B.len(xs)) 1159 1160 def tr.xts_d1(~K: Data, ~dec: K -> M.CmBlock -> M.CmBlock, +k: K, r: Result<&2, &2, M.CmError, M.CmBlock>, +xs: List<&2, U32>) -> {T.xts.d1(~K, ~dec, k, r, xs) == T.xts.d1.fast(~K, ~dec, k, r, xs) : Result<&2, &2, M.CmError, B.Octets>}: 1161 match r: 1162 case Fail{e}: 1163 {==} 1164 case Done{+t}: 1165 %tr.split_eq(xs) : {T.xts.d2(~K, ~dec, k, t, M.cm.split(xs), B.len(xs)) == T.xts.d2.fast(~K, ~dec, k, t, _, B.len.fast(xs)) : Result<&2, &2, M.CmError, B.Octets>} 1166 %BL.len_fast(xs) : {T.xts.d2(~K, ~dec, k, t, M.cm.split(xs), B.len(xs)) == T.xts.d2.fast(~K, ~dec, k, t, M.cm.split(xs), _) : Result<&2, &2, M.CmError, B.Octets>} 1167 tr.xts_d2(~K, ~dec, k, t, M.cm.split(xs), B.len(xs)) 1168 1169 def tr.xts_encrypt(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k1: K, +k2: K, +i: B.Octets, +p: B.Octets) -> {T.Xts.encrypt.ref(~K, ~enc, k1, k2, i, p) == T.Xts.encrypt(~K, ~enc, k1, k2, i, p) : Result<&2, &2, M.CmError, B.Octets>}: 1170 tr.xts_e1(~K, ~enc, k1, T.xts.tweak(~K, ~enc, k2, i), B.Octets.to_list(p)) 1171 1172 def tr.xts_decrypt(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, ~dec: K -> M.CmBlock -> M.CmBlock, +k1: K, +k2: K, +i: B.Octets, +c: B.Octets) -> {T.Xts.decrypt.ref(~K, ~enc, ~dec, k1, k2, i, c) == T.Xts.decrypt(~K, ~enc, ~dec, k1, k2, i, c) : Result<&2, &2, M.CmError, B.Octets>}: 1173 tr.xts_d1(~K, ~dec, k1, T.xts.tweak(~K, ~enc, k2, i), B.Octets.to_list(c)) 1174 1175 # a bind whose continuations agree on every value agrees 1176 def tr.bind_cong(r: Result<&2, &2, M.CmError, B.Octets>, f: B.Octets -> Result<&2, &2, M.CmError, B.Octets>, g: B.Octets -> Result<&2, &2, M.CmError, B.Octets>, h: @c: B.Octets -> {f(c) == g(c) : Result<&2, &2, M.CmError, B.Octets>}) -> {Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, r, f) == Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, r, g) : Result<&2, &2, M.CmError, B.Octets>}: 1177 match r: 1178 case Fail{e}: 1179 {==} 1180 case Done{c}: 1181 h(c) 1182 1183 1184 # CCM: the tail-recursive forms are the structural ones, piece by piece 1185 1186 def tr.pad(+xs: List<&2, U32>) -> {CC.ccm.pad(xs) == CC.ccm.pad.fast(xs) : List<&2, U32>}: 1187 %BL.len_fast(xs) : {CC.ccm.pad(xs) == B.append.fast(xs, B.zeros(Nat.mod(Nat.sub(16n, Nat.mod(_, 16n)), 16n))) : List<&2, U32>} 1188 %BL.append_fast(xs, B.zeros(Nat.mod(Nat.sub(16n, Nat.mod(B.len(xs), 16n)), 16n))) : {CC.ccm.pad(xs) == _ : List<&2, U32>} 1189 {==} 1190 1191 def tr.aad(empty: Bool, +a: List<&2, U32>) -> {CC.ccm.aad.pick(empty, a) == CC.ccm.aad.pick.fast(empty, a) : List<&2, U32>}: 1192 match empty: 1193 case True{}: 1194 {==} 1195 case False{}: 1196 %BL.len_fast(a) : {CC.ccm.aad.pick(False{}, a) == CC.ccm.pad.fast(B.append(CC.ccm.alen.pick(U32.is_lt(U32.from_nat(_), 65280), U32.from_nat(_)), a)) : List<&2, U32>} 1197 %tr.pad(B.append(CC.ccm.alen.pick(U32.is_lt(U32.from_nat(B.len(a)), 65280), U32.from_nat(B.len(a))), a)) : {CC.ccm.aad.pick(False{}, a) == _ : List<&2, U32>} 1198 {==} 1199 1200 def tr.mac(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +m: Nat, +l: Nat, +nonce: List<&2, U32>, +a: List<&2, U32>, +p: List<&2, U32>) -> {CC.ccm.mac(~K, ~enc, k, m, l, nonce, a, p) == CC.ccm.mac.fast(~K, ~enc, k, m, l, nonce, a, p) : M.CmBlock}: 1201 %BL.len_fast(a) : {CC.ccm.mac(~K, ~enc, k, m, l, nonce, a, p) == CC.ccm.cbcmac(~K, ~enc, k, M.cm.split.blocks(M.cm.split.fast(B.append(Con{U32.from_nat(Nat.add(Nat.add(Nat.mul(64n, Nat.min(_, 1n)), Nat.mul(8n, Nat.div(Nat.sub(m, 2n), 2n))), Nat.sub(l, 1n))), B.append(nonce, CC.ccm.be(l, U32.from_nat(B.len.fast(p))))}, B.append.fast(CC.ccm.aad.pick.fast(Nat.is_eq(_, 0n), a), CC.ccm.pad.fast(p))))), M.CmBlock.zero()) : M.CmBlock} 1202 %BL.len_fast(p) : {CC.ccm.mac(~K, ~enc, k, m, l, nonce, a, p) == CC.ccm.cbcmac(~K, ~enc, k, M.cm.split.blocks(M.cm.split.fast(B.append(Con{U32.from_nat(Nat.add(Nat.add(Nat.mul(64n, Nat.min(B.len(a), 1n)), Nat.mul(8n, Nat.div(Nat.sub(m, 2n), 2n))), Nat.sub(l, 1n))), B.append(nonce, CC.ccm.be(l, U32.from_nat(_)))}, B.append.fast(CC.ccm.aad.pick.fast(Nat.is_eq(B.len(a), 0n), a), CC.ccm.pad.fast(p))))), M.CmBlock.zero()) : M.CmBlock} 1203 %tr.pad(p) : {CC.ccm.mac(~K, ~enc, k, m, l, nonce, a, p) == CC.ccm.cbcmac(~K, ~enc, k, M.cm.split.blocks(M.cm.split.fast(B.append(Con{U32.from_nat(Nat.add(Nat.add(Nat.mul(64n, Nat.min(B.len(a), 1n)), Nat.mul(8n, Nat.div(Nat.sub(m, 2n), 2n))), Nat.sub(l, 1n))), B.append(nonce, CC.ccm.be(l, U32.from_nat(B.len(p))))}, B.append.fast(CC.ccm.aad.pick.fast(Nat.is_eq(B.len(a), 0n), a), _)))), M.CmBlock.zero()) : M.CmBlock} 1204 %tr.aad(Nat.is_eq(B.len(a), 0n), a) : {CC.ccm.mac(~K, ~enc, k, m, l, nonce, a, p) == CC.ccm.cbcmac(~K, ~enc, k, M.cm.split.blocks(M.cm.split.fast(B.append(Con{U32.from_nat(Nat.add(Nat.add(Nat.mul(64n, Nat.min(B.len(a), 1n)), Nat.mul(8n, Nat.div(Nat.sub(m, 2n), 2n))), Nat.sub(l, 1n))), B.append(nonce, CC.ccm.be(l, U32.from_nat(B.len(p))))}, B.append.fast(_, CC.ccm.pad(p))))), M.CmBlock.zero()) : M.CmBlock} 1205 %BL.append_fast(CC.ccm.aad.pick(Nat.is_eq(B.len(a), 0n), a), CC.ccm.pad(p)) : {CC.ccm.mac(~K, ~enc, k, m, l, nonce, a, p) == CC.ccm.cbcmac(~K, ~enc, k, M.cm.split.blocks(M.cm.split.fast(B.append(Con{U32.from_nat(Nat.add(Nat.add(Nat.mul(64n, Nat.min(B.len(a), 1n)), Nat.mul(8n, Nat.div(Nat.sub(m, 2n), 2n))), Nat.sub(l, 1n))), B.append(nonce, CC.ccm.be(l, U32.from_nat(B.len(p))))}, _))), M.CmBlock.zero()) : M.CmBlock} 1206 %tr.split_eq(B.append(Con{U32.from_nat(Nat.add(Nat.add(Nat.mul(64n, Nat.min(B.len(a), 1n)), Nat.mul(8n, Nat.div(Nat.sub(m, 2n), 2n))), Nat.sub(l, 1n))), B.append(nonce, CC.ccm.be(l, U32.from_nat(B.len(p))))}, B.append(CC.ccm.aad.pick(Nat.is_eq(B.len(a), 0n), a), CC.ccm.pad(p)))) : {CC.ccm.mac(~K, ~enc, k, m, l, nonce, a, p) == CC.ccm.cbcmac(~K, ~enc, k, M.cm.split.blocks(_), M.CmBlock.zero()) : M.CmBlock} 1207 {==} 1208 1209 def tr.tag(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +m: Nat, +l: Nat, +nonce: List<&2, U32>, +a: List<&2, U32>, +p: List<&2, U32>) -> {CC.ccm.tag(~K, ~enc, k, m, l, nonce, a, p) == CC.ccm.tag.fast(~K, ~enc, k, m, l, nonce, a, p) : List<&2, U32>}: 1210 %tr.mac(~K, ~enc, k, m, l, nonce, a, p) : {CC.ccm.tag(~K, ~enc, k, m, l, nonce, a, p) == B.take(m, M.cm.bytes_of(_)) : List<&2, U32>} 1211 {==} 1212 1213 def tr.ctrb_go(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, bs: List<&2, M.CmBlock>, +a0: M.CmBlock, +i: U32, +acc: List<&2, M.CmBlock>) -> {CC.ccm.ctrb.go(~K, ~enc, k, bs, a0, i, acc) == M.cm.blocks.rev_onto(acc, CC.ccm.ctrb(~K, ~enc, k, bs, a0, i)) : List<&2, M.CmBlock>}: 1214 match bs: 1215 case Nil{}: 1216 {==} 1217 case Con{+b, +rest}: 1218 tr.ctrb_go(~K, ~enc, k, rest, a0, U32.add(i, 1), Con{M.CmBlock.xor(b, enc(k, CC.ccm.ai(a0, i))), acc}) 1219 1220 def tr.ctrb_eq(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +bs: List<&2, M.CmBlock>, +a0: M.CmBlock, +i: U32) -> {CC.ccm.ctrb(~K, ~enc, k, bs, a0, i) == CC.ccm.ctrb.fast(~K, ~enc, k, bs, a0, i) : List<&2, M.CmBlock>}: 1221 Equal.sym(List<&2, M.CmBlock>, CC.ccm.ctrb.fast(~K, ~enc, k, bs, a0, i), CC.ccm.ctrb(~K, ~enc, k, bs, a0, i), tr.ctrb_go(~K, ~enc, k, bs, a0, i, Nil{})) 1222 1223 def tr.xcrypt(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +a0: M.CmBlock, s: M.CmSplit) -> {CC.ccm.xcrypt(~K, ~enc, k, a0, s) == CC.ccm.xcrypt.fast(~K, ~enc, k, a0, s) : List<&2, U32>}: 1224 match s: 1225 case M.CmSplit{+bs, +tail}: 1226 %tr.len_eq(bs) : {CC.ccm.xcrypt(~K, ~enc, k, a0, M.CmSplit{bs, tail}) == M.cm.join_onto.fast(CC.ccm.ctrb.fast(~K, ~enc, k, bs, a0, 1), M.cm.xor_bytes(tail, M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(_))))))) : List<&2, U32>} 1227 %tr.ctrb_eq(~K, ~enc, k, bs, a0, 1) : {CC.ccm.xcrypt(~K, ~enc, k, a0, M.CmSplit{bs, tail}) == M.cm.join_onto.fast(_, M.cm.xor_bytes(tail, M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, bs)))))))) : List<&2, U32>} 1228 %tr.join_eq(CC.ccm.ctrb(~K, ~enc, k, bs, a0, 1), M.cm.xor_bytes(tail, M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, bs)))))))) : {CC.ccm.xcrypt(~K, ~enc, k, a0, M.CmSplit{bs, tail}) == _ : List<&2, U32>} 1229 {==} 1230 1231 def tr.ebody(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +m: Nat, +nv: List<&2, U32>, +av: List<&2, U32>, +pv: List<&2, U32>) -> {CC.ccm.ebody(~K, ~enc, k, m, nv, av, pv) == CC.ccm.ebody.fast(~K, ~enc, k, m, nv, av, pv) : List<&2, U32>}: 1232 %tr.split_eq(pv) : {CC.ccm.ebody(~K, ~enc, k, m, nv, av, pv) == B.append.fast(CC.ccm.xcrypt.fast(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), _), M.cm.xor_bytes(CC.ccm.tag.fast(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv))))) : List<&2, U32>} 1233 %tr.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv)) : {CC.ccm.ebody(~K, ~enc, k, m, nv, av, pv) == B.append.fast(_, M.cm.xor_bytes(CC.ccm.tag.fast(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv))))) : List<&2, U32>} 1234 %tr.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv) : {CC.ccm.ebody(~K, ~enc, k, m, nv, av, pv) == B.append.fast(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv)), M.cm.xor_bytes(_, M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv))))) : List<&2, U32>} 1235 %BL.append_fast(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv)), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv))))) : {CC.ccm.ebody(~K, ~enc, k, m, nv, av, pv) == _ : List<&2, U32>} 1236 {==} 1237 1238 def tr.e2(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +m: Nat, +nv: List<&2, U32>, +av: List<&2, U32>, +pv: List<&2, U32>, r: Result<&2, &2, M.CmError, Unit>) -> {CC.ccm.e2(~K, ~enc, k, m, nv, av, pv, r) == CC.ccm.e2.fast(~K, ~enc, k, m, nv, av, pv, r) : Result<&2, &2, M.CmError, B.Octets>}: 1239 match r: 1240 case Fail{e}: 1241 {==} 1242 case Done{u}: 1243 %tr.ebody(~K, ~enc, k, m, nv, av, pv) : {Done{B.Octets.of_list(CC.ccm.ebody(~K, ~enc, k, m, nv, av, pv))} == Done{B.Octets.of_list(_)} : Result<&2, &2, M.CmError, B.Octets>} 1244 {==} 1245 1246 def tr.ccm_encrypt(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +m: Nat, +nonce: B.Octets, +aad: B.Octets, +p: B.Octets) -> {CC.Ccm.encrypt.ref(~K, ~enc, k, m, nonce, aad, p) == CC.Ccm.encrypt(~K, ~enc, k, m, nonce, aad, p) : Result<&2, &2, M.CmError, B.Octets>}: 1247 %BL.len_fast(B.Octets.to_list(p)) : {CC.Ccm.encrypt.ref(~K, ~enc, k, m, nonce, aad, p) == CC.ccm.e2.fast(~K, ~enc, k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p), CC.ccm.checks(m, B.len(B.Octets.to_list(nonce)), _)) : Result<&2, &2, M.CmError, B.Octets>} 1248 tr.e2(~K, ~enc, k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p), CC.ccm.checks(m, B.len(B.Octets.to_list(nonce)), B.len(B.Octets.to_list(p)))) 1249 1250 def tr.dbody(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +m: Nat, +nv: List<&2, U32>, +av: List<&2, U32>, +cv: List<&2, U32>) -> {CC.ccm.dbody(~K, ~enc, k, m, nv, av, cv) == CC.ccm.dbody.fast(~K, ~enc, k, m, nv, av, cv) : Result<&2, &2, M.CmError, B.Octets>}: 1251 %BL.len_fast(cv) : {CC.ccm.dbody(~K, ~enc, k, m, nv, av, cv) == CC.ccm.open(M.cm.ct_eq(M.cm.xor_bytes(B.drop(Nat.sub(_, m), cv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))), CC.ccm.tag.fast(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, CC.ccm.xcrypt.fast(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split.fast(B.take.fast(Nat.sub(_, m), cv))))), CC.ccm.xcrypt.fast(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split.fast(B.take.fast(Nat.sub(_, m), cv)))) : Result<&2, &2, M.CmError, B.Octets>} 1252 %BL.take_fast(Nat.sub(B.len(cv), m), cv) : {CC.ccm.dbody(~K, ~enc, k, m, nv, av, cv) == CC.ccm.open(M.cm.ct_eq(M.cm.xor_bytes(B.drop(Nat.sub(B.len(cv), m), cv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))), CC.ccm.tag.fast(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, CC.ccm.xcrypt.fast(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split.fast(_)))), CC.ccm.xcrypt.fast(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split.fast(_))) : Result<&2, &2, M.CmError, B.Octets>} 1253 %tr.split_eq(B.take(Nat.sub(B.len(cv), m), cv)) : {CC.ccm.dbody(~K, ~enc, k, m, nv, av, cv) == CC.ccm.open(M.cm.ct_eq(M.cm.xor_bytes(B.drop(Nat.sub(B.len(cv), m), cv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))), CC.ccm.tag.fast(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, CC.ccm.xcrypt.fast(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), _))), CC.ccm.xcrypt.fast(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), _)) : Result<&2, &2, M.CmError, B.Octets>} 1254 %tr.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(B.take(Nat.sub(B.len(cv), m), cv))) : {CC.ccm.dbody(~K, ~enc, k, m, nv, av, cv) == CC.ccm.open(M.cm.ct_eq(M.cm.xor_bytes(B.drop(Nat.sub(B.len(cv), m), cv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))), CC.ccm.tag.fast(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, _)), _) : Result<&2, &2, M.CmError, B.Octets>} 1255 %tr.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(B.take(Nat.sub(B.len(cv), m), cv)))) : {CC.ccm.dbody(~K, ~enc, k, m, nv, av, cv) == CC.ccm.open(M.cm.ct_eq(M.cm.xor_bytes(B.drop(Nat.sub(B.len(cv), m), cv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))), _), CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(B.take(Nat.sub(B.len(cv), m), cv)))) : Result<&2, &2, M.CmError, B.Octets>} 1256 {==} 1257 1258 def tr.d3(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +m: Nat, +nv: List<&2, U32>, +av: List<&2, U32>, +cv: List<&2, U32>, r: Result<&2, &2, M.CmError, Unit>) -> {CC.ccm.d3(~K, ~enc, k, m, nv, av, cv, r) == CC.ccm.d3.fast(~K, ~enc, k, m, nv, av, cv, r) : Result<&2, &2, M.CmError, B.Octets>}: 1259 match r: 1260 case Fail{e}: 1261 {==} 1262 case Done{u}: 1263 tr.dbody(~K, ~enc, k, m, nv, av, cv) 1264 1265 def tr.d2(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, ok: Bool, +k: K, +m: Nat, +nv: List<&2, U32>, +av: List<&2, U32>, +cv: List<&2, U32>) -> {CC.ccm.d2(~K, ~enc, ok, k, m, nv, av, cv) == CC.ccm.d2.fast(~K, ~enc, ok, k, m, nv, av, cv) : Result<&2, &2, M.CmError, B.Octets>}: 1266 match ok: 1267 case False{}: 1268 %BL.len_fast(cv) : {CC.ccm.d2(~K, ~enc, False{}, k, m, nv, av, cv) == Fail{M.CmTooShort{_}} : Result<&2, &2, M.CmError, B.Octets>} 1269 {==} 1270 case True{}: 1271 %BL.len_fast(cv) : {CC.ccm.d2(~K, ~enc, True{}, k, m, nv, av, cv) == CC.ccm.d3.fast(~K, ~enc, k, m, nv, av, cv, CC.ccm.checks(m, B.len(nv), Nat.sub(_, m))) : Result<&2, &2, M.CmError, B.Octets>} 1272 tr.d3(~K, ~enc, k, m, nv, av, cv, CC.ccm.checks(m, B.len(nv), Nat.sub(B.len(cv), m))) 1273 1274 def tr.ccm_decrypt(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +m: Nat, +nonce: B.Octets, +aad: B.Octets, +c: B.Octets) -> {CC.Ccm.decrypt.ref(~K, ~enc, k, m, nonce, aad, c) == CC.Ccm.decrypt(~K, ~enc, k, m, nonce, aad, c) : Result<&2, &2, M.CmError, B.Octets>}: 1275 %BL.len_fast(B.Octets.to_list(c)) : {CC.Ccm.decrypt.ref(~K, ~enc, k, m, nonce, aad, c) == CC.ccm.d2.fast(~K, ~enc, Nat.is_le(m, _), k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(c)) : Result<&2, &2, M.CmError, B.Octets>} 1276 tr.d2(~K, ~enc, Nat.is_le(m, B.len(B.Octets.to_list(c))), k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(c)) 1277 1278 # CBC on blocks 1279 1280 def cbcp.go(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, ~dec: K -> M.CmBlock -> M.CmBlock, ~inv: @k: K -> @b: M.CmBlock -> {dec(k, enc(k, b)) == b : M.CmBlock}, +k: K, bs: List<&2, M.CmBlock>, +iv: M.CmBlock) -> {C.cbc.dec(~K, ~dec, k, C.cbc.enc(~K, ~enc, k, bs, iv), iv) == bs : List<&2, M.CmBlock>}: 1281 match bs: 1282 case Nil{}: 1283 {==} 1284 case Con{+p, +t}: 1285 %Equal.sym(M.CmBlock, dec(k, enc(k, M.CmBlock.xor(iv, p))), M.CmBlock.xor(iv, p), inv(k, M.CmBlock.xor(iv, p))) : {Con{M.CmBlock.xor(iv, _), C.cbc.dec(~K, ~dec, k, C.cbc.enc(~K, ~enc, k, t, enc(k, M.CmBlock.xor(iv, p))), enc(k, M.CmBlock.xor(iv, p)))} == Con{p, t} : List<&2, M.CmBlock>} 1286 %bx.block(iv, p) : {Con{M.CmBlock.xor(iv, M.CmBlock.xor(iv, p)), C.cbc.dec(~K, ~dec, k, C.cbc.enc(~K, ~enc, k, t, enc(k, M.CmBlock.xor(iv, p))), enc(k, M.CmBlock.xor(iv, p)))} == Con{_, t} : List<&2, M.CmBlock>} 1287 %cbcp.go(~K, ~enc, ~dec, ~inv, k, t, enc(k, M.CmBlock.xor(iv, p))) : {Con{M.CmBlock.xor(iv, M.CmBlock.xor(iv, p)), C.cbc.dec(~K, ~dec, k, C.cbc.enc(~K, ~enc, k, t, enc(k, M.CmBlock.xor(iv, p))), enc(k, M.CmBlock.xor(iv, p)))} == Con{M.CmBlock.xor(iv, M.CmBlock.xor(iv, p)), _} : List<&2, M.CmBlock>} 1288 {==} 1289 1290 def Laws.cbc_blocks_round_trip(K, enc, dec, inv, k, iv, bs): 1291 +v = iv 1292 +b = bs 1293 # the tail-recursive forms are the structural ones 1294 %tr.cbc_enc_eq(~K, ~enc, k, b, v) : {C.cbc.dec.fast(~K, ~dec, k, _, iv) == bs : List<&2, M.CmBlock>} 1295 %tr.cbc_dec_eq(~K, ~dec, k, C.cbc.enc(~K, ~enc, k, b, v), v) : {_ == bs : List<&2, M.CmBlock>} 1296 cbcp.go(~K, ~enc, ~dec, ~inv, k, b, v) 1297 1298 def Laws.cbc_round_trip(K, enc, dec, inv, k, iv, m, hi, hm): 1299 +et = sp.mod_tail(B.Octets.to_list(m))(oc.mod(m, hm)) 1300 # the public defs are the structural ones 1301 %tr.cbc_encrypt(~K, ~enc, k, iv, m) : {Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, _, c => C.Cbc.decrypt(~K, ~dec, k, iv, c)) == Done{m} : Result<&2, &2, M.CmError, B.Octets>} 1302 %tr.bind_cong(C.Cbc.encrypt.ref(~K, ~enc, k, iv, m), c => C.Cbc.decrypt.ref(~K, ~dec, k, iv, c), c => C.Cbc.decrypt(~K, ~dec, k, iv, c), c => tr.cbc_decrypt(~K, ~dec, k, iv, c)) : {_ == Done{m} : Result<&2, &2, M.CmError, B.Octets>} 1303 # the IV is a block 1304 %Equal.sym(Result<&2, &2, M.CmError, M.CmBlock>, C.cbc.iv(iv), Done{M.cm.block_of(B.Octets.to_list(iv))}, cbcp.iv(iv, hi)) : {Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, C.cbc.e1(~K, ~enc, k, _, B.Octets.to_list(m)), c => C.cbc.d1(~K, ~dec, k, _, B.Octets.to_list(c))) == Done{m} : Result<&2, &2, M.CmError, B.Octets>} 1305 # the message is masked 1306 %oc.masked(m) : {Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, C.cbc.e2(~K, ~enc, k, M.cm.block_of(B.Octets.to_list(iv)), M.cm.split(_), B.len(B.Octets.to_list(m))), c => C.cbc.d1(~K, ~dec, k, Done{M.cm.block_of(B.Octets.to_list(iv))}, B.Octets.to_list(c))) == Done{m} : Result<&2, &2, M.CmError, B.Octets>} 1307 # its split is its blocks and tail 1308 %sp.eta(M.cm.split(B.mask(B.Octets.to_list(m)))) : {Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, C.cbc.e2(~K, ~enc, k, M.cm.block_of(B.Octets.to_list(iv)), _, B.len(B.Octets.to_list(m))), c => C.cbc.d1(~K, ~dec, k, Done{M.cm.block_of(B.Octets.to_list(iv))}, B.Octets.to_list(c))) == Done{m} : Result<&2, &2, M.CmError, B.Octets>} 1309 # whole blocks leave no tail, so encryption succeeds 1310 %Equal.sym(List<&2, U32>, M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(m)))), Nil{}, et) : {Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, C.cbc.e2(~K, ~enc, k, M.cm.block_of(B.Octets.to_list(iv)), M.CmSplit{M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), _}, B.len(B.Octets.to_list(m))), c => C.cbc.d1(~K, ~dec, k, Done{M.cm.block_of(B.Octets.to_list(iv))}, B.Octets.to_list(c))) == Done{m} : Result<&2, &2, M.CmError, B.Octets>} 1311 # decryption reads the ciphertext's bytes back, masked 1312 %Equal.sym(List<&2, U32>, B.Octets.to_list(B.Octets.of_list(M.cm.join_onto(C.cbc.enc(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.block_of(B.Octets.to_list(iv))), Nil{}))), B.mask(M.cm.join_onto(C.cbc.enc(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.block_of(B.Octets.to_list(iv))), Nil{})), BL.octets_to_of(M.cm.join_onto(C.cbc.enc(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.block_of(B.Octets.to_list(iv))), Nil{}))) : {C.cbc.d2(~K, ~dec, k, M.cm.block_of(B.Octets.to_list(iv)), M.cm.split(_), B.len(B.Octets.to_list(B.Octets.of_list(M.cm.join_onto(C.cbc.enc(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.block_of(B.Octets.to_list(iv))), Nil{}))))) == Done{m} : Result<&2, &2, M.CmError, B.Octets>} 1313 # which they already are 1314 %Equal.sym(List<&2, U32>, B.mask(M.cm.join_onto(C.cbc.enc(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.block_of(B.Octets.to_list(iv))), Nil{})), M.cm.join_onto(C.cbc.enc(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.block_of(B.Octets.to_list(iv))), Nil{}), sp.mask_join(C.cbc.enc(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.block_of(B.Octets.to_list(iv))))) : {C.cbc.d2(~K, ~dec, k, M.cm.block_of(B.Octets.to_list(iv)), M.cm.split(_), B.len(B.Octets.to_list(B.Octets.of_list(M.cm.join_onto(C.cbc.enc(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.block_of(B.Octets.to_list(iv))), Nil{}))))) == Done{m} : Result<&2, &2, M.CmError, B.Octets>} 1315 # and they split into the ciphertext blocks 1316 %Equal.sym(M.CmSplit, M.cm.split(M.cm.join_onto(C.cbc.enc(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.block_of(B.Octets.to_list(iv))), Nil{})), M.CmSplit{C.cbc.enc(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.block_of(B.Octets.to_list(iv))), Nil{}}, sp.split_join(C.cbc.enc(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.block_of(B.Octets.to_list(iv))))) : {C.cbc.d2(~K, ~dec, k, M.cm.block_of(B.Octets.to_list(iv)), _, B.len(B.Octets.to_list(B.Octets.of_list(M.cm.join_onto(C.cbc.enc(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.block_of(B.Octets.to_list(iv))), Nil{}))))) == Done{m} : Result<&2, &2, M.CmError, B.Octets>} 1317 # CBC on blocks 1318 %Equal.sym(List<&2, M.CmBlock>, C.cbc.dec(~K, ~dec, k, C.cbc.enc(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.block_of(B.Octets.to_list(iv))), M.cm.block_of(B.Octets.to_list(iv))), M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), cbcp.go(~K, ~enc, ~dec, ~inv, k, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.block_of(B.Octets.to_list(iv)))) : {Done{B.Octets.of_list(M.cm.join_onto(_, Nil{}))} == Done{m} : Result<&2, &2, M.CmError, B.Octets>} 1319 # the plaintext blocks and the empty tail 1320 %et : {Done{B.Octets.of_list(M.cm.join_onto(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), _))} == Done{m} : Result<&2, &2, M.CmError, B.Octets>} 1321 # join back to the message 1322 %Equal.sym(List<&2, U32>, M.cm.join_onto(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(m)))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(m))))), B.mask(B.Octets.to_list(m)), sp.join_split(B.Octets.to_list(m))) : {Done{B.Octets.of_list(_)} == Done{m} : Result<&2, &2, M.CmError, B.Octets>} 1323 # 1324 %Equal.sym(List<&2, U32>, B.mask(B.Octets.to_list(m)), B.Octets.to_list(m), oc.masked(m)) : {Done{B.Octets.of_list(_)} == Done{m} : Result<&2, &2, M.CmError, B.Octets>} 1325 # 1326 %Equal.sym(B.Octets, B.Octets.of_list(B.Octets.to_list(m)), m, BL.octets_of_to(m)) : {Done{_} == Done{m} : Result<&2, &2, M.CmError, B.Octets>} 1327 {==} 1328 1329 # XOR, cancelling on the right: xor(xor(a, b), b) == a 1330 1331 def bx.rbool(a: Bool, b: Bool) -> {Bool.xor(Bool.xor(a, b), b) == a : Bool}: 1332 match a b: 1333 case False{} False{}: 1334 {==} 1335 case False{} True{}: 1336 {==} 1337 case True{} False{}: 1338 {==} 1339 case True{} True{}: 1340 {==} 1341 1342 def bx.rword(n: Nat, a: Word(n), b: Word(n)) -> {Word.xor(n, Word.xor(n, a, b), b) == a : Word(n)}: 1343 match n: 1344 case 0n: 1345 match a: 1346 case WNil{}: 1347 {==} 1348 case 1n+p: 1349 match a b: 1350 case WCon{ah, at} WCon{bh, bt}: 1351 %bx.rbool(ah, bh) : {WCon{Bool.xor(Bool.xor(ah, bh), bh), Word.xor(p, Word.xor(p, at, bt), bt)} == WCon{_, at} : Word(1n+p)} 1352 %bx.rword(p, at, bt) : {WCon{Bool.xor(Bool.xor(ah, bh), bh), Word.xor(p, Word.xor(p, at, bt), bt)} == WCon{Bool.xor(Bool.xor(ah, bh), bh), _} : Word(1n+p)} 1353 {==} 1354 1355 def bx.ru32(a: U32, b: U32) -> {U32.xor(U32.xor(a, b), b) == a : U32}: 1356 match a b: 1357 case U32{x} U32{y}: 1358 %bx.rword(32n, x, y) : {U32{Word.xor(32n, Word.xor(32n, x, y), y)} == U32{_} : U32} 1359 {==} 1360 1361 def bx.rblock(+a: M.CmBlock, +b: M.CmBlock) -> {M.CmBlock.xor(M.CmBlock.xor(a, b), b) == a : M.CmBlock}: 1362 match a b: 1363 case M.CmBlock{a0, a1, a2, a3} M.CmBlock{b0, b1, b2, b3}: 1364 %bx.ru32(a0, b0) : {M.CmBlock.xor(M.CmBlock.xor(M.CmBlock{a0, a1, a2, a3}, M.CmBlock{b0, b1, b2, b3}), M.CmBlock{b0, b1, b2, b3}) == M.CmBlock{_, a1, a2, a3} : M.CmBlock} 1365 %bx.ru32(a1, b1) : {M.CmBlock.xor(M.CmBlock.xor(M.CmBlock{a0, a1, a2, a3}, M.CmBlock{b0, b1, b2, b3}), M.CmBlock{b0, b1, b2, b3}) == M.CmBlock{U32.xor(U32.xor(a0, b0), b0), _, a2, a3} : M.CmBlock} 1366 %bx.ru32(a2, b2) : {M.CmBlock.xor(M.CmBlock.xor(M.CmBlock{a0, a1, a2, a3}, M.CmBlock{b0, b1, b2, b3}), M.CmBlock{b0, b1, b2, b3}) == M.CmBlock{U32.xor(U32.xor(a0, b0), b0), U32.xor(U32.xor(a1, b1), b1), _, a3} : M.CmBlock} 1367 %bx.ru32(a3, b3) : {M.CmBlock.xor(M.CmBlock.xor(M.CmBlock{a0, a1, a2, a3}, M.CmBlock{b0, b1, b2, b3}), M.CmBlock{b0, b1, b2, b3}) == M.CmBlock{U32.xor(U32.xor(a0, b0), b0), U32.xor(U32.xor(a1, b1), b1), U32.xor(U32.xor(a2, b2), b2), _} : M.CmBlock} 1368 {==} 1369 1370 # XTS on blocks 1371 1372 # one block under one tweak: D(E(p xor t) xor t xor t) xor t == p 1373 def xtsp.blk(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, ~dec: K -> M.CmBlock -> M.CmBlock, ~inv: @k: K -> @b: M.CmBlock -> {dec(k, enc(k, b)) == b : M.CmBlock}, +k: K, +p: M.CmBlock, +t: M.CmBlock) -> {T.xts.bdec(~K, ~dec, k, T.xts.benc(~K, ~enc, k, p, t), t) == p : M.CmBlock}: 1374 %Equal.sym(M.CmBlock, M.CmBlock.xor(M.CmBlock.xor(enc(k, M.CmBlock.xor(p, t)), t), t), enc(k, M.CmBlock.xor(p, t)), bx.rblock(enc(k, M.CmBlock.xor(p, t)), t)) : {M.CmBlock.xor(dec(k, _), t) == p : M.CmBlock} 1375 %Equal.sym(M.CmBlock, dec(k, enc(k, M.CmBlock.xor(p, t))), M.CmBlock.xor(p, t), inv(k, M.CmBlock.xor(p, t))) : {M.CmBlock.xor(_, t) == p : M.CmBlock} 1376 bx.rblock(p, t) 1377 1378 def xtsp.go(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, ~dec: K -> M.CmBlock -> M.CmBlock, ~inv: @k: K -> @b: M.CmBlock -> {dec(k, enc(k, b)) == b : M.CmBlock}, +k: K, bs: List<&2, M.CmBlock>, +t: M.CmBlock) -> {T.xts.dec(~K, ~dec, k, T.xts.enc(~K, ~enc, k, bs, t), t) == bs : List<&2, M.CmBlock>}: 1379 match bs: 1380 case Nil{}: 1381 {==} 1382 case Con{+p, +rest}: 1383 %Equal.sym(M.CmBlock, T.xts.bdec(~K, ~dec, k, T.xts.benc(~K, ~enc, k, p, t), t), p, xtsp.blk(~K, ~enc, ~dec, ~inv, k, p, t)) : {Con{_, T.xts.dec(~K, ~dec, k, T.xts.enc(~K, ~enc, k, rest, T.Xts.mul_alpha(t)), T.Xts.mul_alpha(t))} == Con{p, rest} : List<&2, M.CmBlock>} 1384 %Equal.sym(List<&2, M.CmBlock>, T.xts.dec(~K, ~dec, k, T.xts.enc(~K, ~enc, k, rest, T.Xts.mul_alpha(t)), T.Xts.mul_alpha(t)), rest, xtsp.go(~K, ~enc, ~dec, ~inv, k, rest, T.Xts.mul_alpha(t))) : {Con{p, _} == Con{p, rest} : List<&2, M.CmBlock>} 1385 {==} 1386 1387 def Laws.xts_blocks_round_trip(K, enc, dec, inv, k1, t, bs): 1388 +v = t 1389 +b = bs 1390 # the tail-recursive forms are the structural ones 1391 %tr.xts_enc_eq(~K, ~enc, k1, b, v) : {T.xts.dec.fast(~K, ~dec, k1, _, t) == bs : List<&2, M.CmBlock>} 1392 %tr.xts_dec_eq(~K, ~dec, k1, T.xts.enc(~K, ~enc, k1, b, v), v) : {_ == bs : List<&2, M.CmBlock>} 1393 xtsp.go(~K, ~enc, ~dec, ~inv, k1, b, v) 1394 1395 # CMAC: the state after a ++ b is the state after a, then b 1396 1397 def cmacp.feed(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, xs: List<&2, U32>, s: CM.CmacState, ys: List<&2, U32>) -> {CM.cmac.feed(~K, ~enc, k, B.append(xs, ys), s) == CM.cmac.feed(~K, ~enc, k, ys, CM.cmac.feed(~K, ~enc, k, xs, s)) : CM.CmacState}: 1398 match xs: 1399 case Nil{}: 1400 {==} 1401 case Con{h, t}: 1402 cmacp.feed(~K, ~enc, k, t, CM.cmac.step(~K, ~enc, k, s, h), ys) 1403 1404 def Laws.cmac_streaming(K, enc, k, s, a, b): 1405 %Equal.sym(List<&2, U32>, B.Octets.to_list(B.Octets.append(a, b)), B.append(B.Octets.to_list(a), B.Octets.to_list(b)), BL.octets_append_list(a, b)) : {CM.cmac.feed(~K, ~enc, k, _, s) == CM.cmac.feed(~K, ~enc, k, B.Octets.to_list(b), CM.cmac.feed(~K, ~enc, k, B.Octets.to_list(a), s)) : CM.CmacState} 1406 cmacp.feed(~K, ~enc, k, B.Octets.to_list(a), s, B.Octets.to_list(b)) 1407 1408 1409 # More on joining and splitting 1410 1411 def sp.mask_join_onto(bs: List<&2, M.CmBlock>, +rest: List<&2, U32>) -> {B.mask(M.cm.join_onto(bs, rest)) == M.cm.join_onto(bs, B.mask(rest)) : List<&2, U32>}: 1412 match bs: 1413 case Nil{}: 1414 {==} 1415 case Con{+b, +t}: 1416 %Equal.sym(List<&2, U32>, B.mask(M.cm.bytes_onto(b, M.cm.join_onto(t, rest))), M.cm.bytes_onto(b, B.mask(M.cm.join_onto(t, rest))), sp.mask_blk(b, M.cm.join_onto(t, rest))) : {_ == M.cm.bytes_onto(b, M.cm.join_onto(t, B.mask(rest))) : List<&2, U32>} 1417 %sp.mask_join_onto(t, rest) : {M.cm.bytes_onto(b, B.mask(M.cm.join_onto(t, rest))) == M.cm.bytes_onto(b, _) : List<&2, U32>} 1418 {==} 1419 1420 # blocks joined in front of a short tail split back into those blocks and tail 1421 def sp.split_join_short(bs: List<&2, M.CmBlock>, +rest: List<&2, U32>) -> {M.cm.split(rest) == M.CmSplit{Nil{}, rest} : M.CmSplit} -> {M.cm.split(M.cm.join_onto(bs, rest)) == M.CmSplit{bs, rest} : M.CmSplit}: 1422 match bs: 1423 case Nil{}: 1424 h => h 1425 case Con{+b, +t}: 1426 h => %Equal.sym(M.CmSplit, M.cm.split(M.cm.bytes_onto(b, M.cm.join_onto(t, rest))), M.cm.split.cons(b, M.cm.split(M.cm.join_onto(t, rest))), sp.blk(b, M.cm.join_onto(t, rest))) : {_ == M.CmSplit{Con{b, t}, rest} : M.CmSplit} 1427 %Equal.sym(M.CmSplit, M.cm.split(M.cm.join_onto(t, rest)), M.CmSplit{t, rest}, sp.split_join_short(t, rest)(h)) : {M.cm.split.cons(b, _) == M.CmSplit{Con{b, t}, rest} : M.CmSplit} 1428 {==} 1429 1430 def sp.join_append(bs: List<&2, M.CmBlock>, +x: M.CmBlock, +rest: List<&2, U32>) -> {M.cm.join_onto(List.append(&2, M.CmBlock, bs, Con{x, Nil{}}), rest) == M.cm.join_onto(bs, M.cm.bytes_onto(x, rest)) : List<&2, U32>}: 1431 match bs: 1432 case Nil{}: 1433 {==} 1434 case Con{+b, +t}: 1435 %sp.join_append(t, x, rest) : {M.cm.bytes_onto(b, M.cm.join_onto(List.append(&2, M.CmBlock, t, Con{x, Nil{}}), rest)) == M.cm.bytes_onto(b, _) : List<&2, U32>} 1436 {==} 1437 1438 # The last block and the others 1439 1440 def li.init_app(es: List<&2, M.CmBlock>, +x: M.CmBlock, +e: M.CmBlock) -> {T.xts.init(List.append(&2, M.CmBlock, es, Con{x, Nil{}}), e) == Con{e, es} : List<&2, M.CmBlock>}: 1441 match es: 1442 case Nil{}: 1443 {==} 1444 case Con{+e2, +es2}: 1445 %li.init_app(es2, x, e2) : {Con{e, T.xts.init(List.append(&2, M.CmBlock, es2, Con{x, Nil{}}), e2)} == Con{e, _} : List<&2, M.CmBlock>} 1446 {==} 1447 1448 def li.last_app(es: List<&2, M.CmBlock>, +x: M.CmBlock, +e: M.CmBlock) -> {T.xts.last(List.append(&2, M.CmBlock, es, Con{x, Nil{}}), e) == x : M.CmBlock}: 1449 match es: 1450 case Nil{}: 1451 {==} 1452 case Con{+e2, +es2}: 1453 li.last_app(es2, x, e2) 1454 1455 def li.init_last(rest: List<&2, M.CmBlock>, +p: M.CmBlock) -> {List.append(&2, M.CmBlock, T.xts.init(rest, p), Con{T.xts.last(rest, p), Nil{}}) == Con{p, rest} : List<&2, M.CmBlock>}: 1456 match rest: 1457 case Nil{}: 1458 {==} 1459 case Con{+q, +r}: 1460 %li.init_last(r, q) : {Con{p, List.append(&2, M.CmBlock, T.xts.init(r, q), Con{T.xts.last(r, q), Nil{}})} == Con{p, _} : List<&2, M.CmBlock>} 1461 {==} 1462 1463 def li.len_enc(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, bs: List<&2, M.CmBlock>, +t: M.CmBlock) -> {List.length(&2, M.CmBlock, T.xts.enc(~K, ~enc, k, bs, t)) == List.length(&2, M.CmBlock, bs) : Nat}: 1464 match bs: 1465 case Nil{}: 1466 {==} 1467 case Con{+p, +rest}: 1468 %li.len_enc(~K, ~enc, k, rest, T.Xts.mul_alpha(t)) : {1n+List.length(&2, M.CmBlock, T.xts.enc(~K, ~enc, k, rest, T.Xts.mul_alpha(t))) == 1n+_ : Nat} 1469 {==} 1470 1471 # The byte layer 1472 1473 def oc.le16(+o: B.Octets, h: {Nat.is_le(16n, B.Octets.len(o)) == True{} : Bool}) -> {Nat.is_le(16n, B.len(B.Octets.to_list(o))) == True{} : Bool}: 1474 %BL.octets_len_list(o) : {Nat.is_le(16n, _) == True{} : Bool} 1475 h 1476 1477 def xtsp.tweak(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k2: K, +i: B.Octets, h: {B.Octets.len(i) == 16n : Nat}) -> {T.xts.tweak(~K, ~enc, k2, i) == Done{enc(k2, M.cm.block_of(B.Octets.to_list(i)))} : Result<&2, &2, M.CmError, M.CmBlock>}: 1478 %Equal.sym(Nat, B.len(B.Octets.to_list(i)), 16n, oc.len(i, 16n, h)) : {T.xts.tweak.go(~K, ~enc, k2, M.cm.need_block.pick(Nat.is_eq(_, 16n), B.Octets.to_list(i), M.CmBadTweakLength{B.len(B.Octets.to_list(i))})) == Done{enc(k2, M.cm.block_of(B.Octets.to_list(i)))} : Result<&2, &2, M.CmError, M.CmBlock>} 1479 {==} 1480 1481 # the final partial ciphertext block is masked, and splits into no blocks 1482 def xtsp.mask_steal_t(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +p: M.CmBlock, tl: List<&2, U32>, +t: M.CmBlock) -> {B.mask(T.xts.steal_t(~K, ~enc, k, p, tl, t)) == T.xts.steal_t(~K, ~enc, k, p, tl, t) : List<&2, U32>}: 1483 match tl: 1484 case Nil{}: 1485 {==} 1486 case Con{+h, +r}: 1487 %Equal.sym(List<&2, U32>, B.mask(B.take(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t)))), B.take(B.len(Con{h, r}), B.mask(M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t)))), li.mask_take(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t)))) : {_ == B.take(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))) : List<&2, U32>} 1488 %Equal.sym(List<&2, U32>, B.mask(M.cm.bytes_onto(T.xts.benc(~K, ~enc, k, p, t), Nil{})), M.cm.bytes_onto(T.xts.benc(~K, ~enc, k, p, t), B.mask(Nil{})), sp.mask_blk(T.xts.benc(~K, ~enc, k, p, t), Nil{})) : {B.take(B.len(Con{h, r}), _) == B.take(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))) : List<&2, U32>} 1489 {==} 1490 1491 def xtsp.lt_take(+n: Nat, +b: M.CmBlock, +h: {Nat.is_lt(n, 16n) == True{} : Bool}) -> {Nat.is_lt(B.len(B.take(n, M.cm.bytes_of(b))), 16n) == True{} : Bool}: 1492 %Equal.sym(Nat, B.len(B.take(n, M.cm.bytes_of(b))), n, li.len_take(n, M.cm.bytes_of(b))(na.lt_le(n, 16n)(h))) : {Nat.is_lt(_, 16n) == True{} : Bool} 1493 h 1494 1495 def xtsp.split_steal_t(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +p: M.CmBlock, tl: List<&2, U32>, +t: M.CmBlock) -> {Nat.is_lt(B.len(tl), 16n) == True{} : Bool} -> {M.cm.split(T.xts.steal_t(~K, ~enc, k, p, tl, t)) == M.CmSplit{Nil{}, T.xts.steal_t(~K, ~enc, k, p, tl, t)} : M.CmSplit}: 1496 match tl: 1497 case Nil{}: 1498 h => {==} 1499 case Con{+x, +r}: 1500 h => sp.short_split(B.take(B.len(Con{x, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))))(xtsp.lt_take(B.len(Con{x, r}), T.xts.benc(~K, ~enc, k, p, t), h)) 1501 1502 # the bytes the stealing passes through: tl, then the stolen tail of b 1503 def xtsp.len16(+tl: List<&2, U32>, +b: M.CmBlock, h: {Nat.is_lt(B.len(tl), 16n) == True{} : Bool}) -> {Nat.is_eq(B.len(B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b)))), 16n) == True{} : Bool}: 1504 %Equal.sym(Nat, B.len(B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b)))), Nat.add(B.len(tl), B.len(B.drop(B.len(tl), M.cm.bytes_of(b)))), li.len_append(tl, B.drop(B.len(tl), M.cm.bytes_of(b)))) : {Nat.is_eq(_, 16n) == True{} : Bool} 1505 %Equal.sym(Nat, B.len(B.drop(B.len(tl), M.cm.bytes_of(b))), Nat.sub(16n, B.len(tl)), li.len_drop(B.len(tl), M.cm.bytes_of(b))) : {Nat.is_eq(Nat.add(B.len(tl), _), 16n) == True{} : Bool} 1506 %Equal.sym(Nat, Nat.add(B.len(tl), Nat.sub(16n, B.len(tl))), 16n, na.add_sub(B.len(tl), 16n)(na.lt_le(B.len(tl), 16n)(h))) : {Nat.is_eq(_, 16n) == True{} : Bool} 1507 {==} 1508 1509 def xtsp.maskY(+tl: List<&2, U32>, +b: M.CmBlock, hm: {B.mask(tl) == tl : List<&2, U32>}) -> {B.mask(B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b)))) == B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b))) : List<&2, U32>}: 1510 %Equal.sym(List<&2, U32>, B.mask(B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b)))), B.append(B.mask(tl), B.mask(B.drop(B.len(tl), M.cm.bytes_of(b)))), li.mask_append(tl, B.drop(B.len(tl), M.cm.bytes_of(b)))) : {_ == B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b))) : List<&2, U32>} 1511 %Equal.sym(List<&2, U32>, B.mask(B.drop(B.len(tl), M.cm.bytes_of(b))), B.drop(B.len(tl), B.mask(M.cm.bytes_of(b))), li.mask_drop(B.len(tl), M.cm.bytes_of(b))) : {B.append(B.mask(tl), _) == B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b))) : List<&2, U32>} 1512 %Equal.sym(List<&2, U32>, B.mask(M.cm.bytes_onto(b, Nil{})), M.cm.bytes_onto(b, B.mask(Nil{})), sp.mask_blk(b, Nil{})) : {B.append(B.mask(tl), B.drop(B.len(tl), _)) == B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b))) : List<&2, U32>} 1513 %Equal.sym(List<&2, U32>, B.mask(tl), tl, hm) : {B.append(_, B.drop(B.len(tl), M.cm.bytes_of(b))) == B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b))) : List<&2, U32>} 1514 {==} 1515 1516 def xtsp.ppY(+tl: List<&2, U32>, +b: M.CmBlock, hm: {B.mask(tl) == tl : List<&2, U32>}, hl: {Nat.is_lt(B.len(tl), 16n) == True{} : Bool}) -> {M.cm.bytes_of(M.cm.block_of(B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b))))) == B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b))) : List<&2, U32>}: 1517 Equal.trans(List<&2, U32>, M.cm.bytes_of(M.cm.block_of(B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b))))), B.mask(B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b)))), B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b))), sp.bb16(B.append(tl, B.drop(B.len(tl), M.cm.bytes_of(b))))(xtsp.len16(tl, b, hl)), xtsp.maskY(tl, b, hm)) 1518 1519 # Ciphertext stealing undoes itself: the last whole block p and a tail tl 1520 # (masked, fewer than 16 bytes), encrypted by steal_c and steal_t and 1521 # decrypted by dsteal, come back as p's bytes and then tl 1522 def xtsp.steal(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, ~dec: K -> M.CmBlock -> M.CmBlock, ~inv: @k: K -> @b: M.CmBlock -> {dec(k, enc(k, b)) == b : M.CmBlock}, +k: K, +p: M.CmBlock, tl: List<&2, U32>, +t: M.CmBlock) -> {B.mask(tl) == tl : List<&2, U32>} -> {Nat.is_lt(B.len(tl), 16n) == True{} : Bool} -> {T.xts.dsteal(~K, ~dec, k, T.xts.steal_c(~K, ~enc, k, p, tl, t), T.xts.steal_t(~K, ~enc, k, p, tl, t), t) == M.cm.bytes_onto(p, tl) : List<&2, U32>}: 1523 match tl: 1524 case Nil{}: 1525 hm => hl => %Equal.sym(M.CmBlock, T.xts.bdec(~K, ~dec, k, T.xts.benc(~K, ~enc, k, p, t), t), p, xtsp.blk(~K, ~enc, ~dec, ~inv, k, p, t)) : {M.cm.bytes_of(_) == M.cm.bytes_onto(p, Nil{}) : List<&2, U32>} 1526 {==} 1527 case Con{+h, +r}: 1528 +hm => +hl => %Equal.sym(M.CmBlock, T.xts.bdec(~K, ~dec, k, T.xts.benc(~K, ~enc, k, M.cm.block_of(B.append(Con{h, r}, B.drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))))), T.Xts.mul_alpha(t)), T.Xts.mul_alpha(t)), M.cm.block_of(B.append(Con{h, r}, B.drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))))), xtsp.blk(~K, ~enc, ~dec, ~inv, k, M.cm.block_of(B.append(Con{h, r}, B.drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))))), T.Xts.mul_alpha(t))) : {M.cm.bytes_onto(T.xts.bdec(~K, ~dec, k, M.cm.block_of(B.append(B.take(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))), B.drop(B.len(B.take(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t)))), M.cm.bytes_of(_)))), t), B.take(B.len(B.take(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t)))), M.cm.bytes_of(_))) == M.cm.bytes_onto(p, Con{h, r}) : List<&2, U32>} 1529 %Equal.sym(Nat, B.len(B.take(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t)))), B.len(Con{h, r}), li.len_take(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t)))(na.lt_le(B.len(Con{h, r}), 16n)(hl))) : {M.cm.bytes_onto(T.xts.bdec(~K, ~dec, k, M.cm.block_of(B.append(B.take(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))), B.drop(_, M.cm.bytes_of(M.cm.block_of(B.append(Con{h, r}, B.drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))))))))), t), B.take(_, M.cm.bytes_of(M.cm.block_of(B.append(Con{h, r}, B.drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t)))))))) == M.cm.bytes_onto(p, Con{h, r}) : List<&2, U32>} 1530 %Equal.sym(List<&2, U32>, M.cm.bytes_of(M.cm.block_of(B.append(Con{h, r}, B.drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t)))))), B.append(Con{h, r}, B.drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t)))), xtsp.ppY(Con{h, r}, T.xts.benc(~K, ~enc, k, p, t), hm, hl)) : {M.cm.bytes_onto(T.xts.bdec(~K, ~dec, k, M.cm.block_of(B.append(B.take(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))), B.drop(B.len(Con{h, r}), _))), t), B.take(B.len(Con{h, r}), _)) == M.cm.bytes_onto(p, Con{h, r}) : List<&2, U32>} 1531 %Equal.sym(List<&2, U32>, B.take(B.len(Con{h, r}), B.append(Con{h, r}, B.drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))))), Con{h, r}, li.take_append(Con{h, r}, B.drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))))) : {M.cm.bytes_onto(T.xts.bdec(~K, ~dec, k, M.cm.block_of(B.append(B.take(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))), B.drop(B.len(Con{h, r}), B.append(Con{h, r}, B.drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))))))), t), _) == M.cm.bytes_onto(p, Con{h, r}) : List<&2, U32>} 1532 %Equal.sym(List<&2, U32>, B.drop(B.len(Con{h, r}), B.append(Con{h, r}, B.drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))))), B.drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))), li.drop_append(Con{h, r}, B.drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))))) : {M.cm.bytes_onto(T.xts.bdec(~K, ~dec, k, M.cm.block_of(B.append(B.take(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))), _)), t), Con{h, r}) == M.cm.bytes_onto(p, Con{h, r}) : List<&2, U32>} 1533 %Equal.sym(List<&2, U32>, B.append(B.take(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))), B.drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t)))), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t)), BL.take_drop(B.len(Con{h, r}), M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t)))) : {M.cm.bytes_onto(T.xts.bdec(~K, ~dec, k, M.cm.block_of(_), t), Con{h, r}) == M.cm.bytes_onto(p, Con{h, r}) : List<&2, U32>} 1534 %Equal.sym(M.CmBlock, M.cm.block_of(M.cm.bytes_of(T.xts.benc(~K, ~enc, k, p, t))), T.xts.benc(~K, ~enc, k, p, t), sp.block_bytes(T.xts.benc(~K, ~enc, k, p, t))) : {M.cm.bytes_onto(T.xts.bdec(~K, ~dec, k, _, t), Con{h, r}) == M.cm.bytes_onto(p, Con{h, r}) : List<&2, U32>} 1535 %Equal.sym(M.CmBlock, T.xts.bdec(~K, ~dec, k, T.xts.benc(~K, ~enc, k, p, t), t), p, xtsp.blk(~K, ~enc, ~dec, ~inv, k, p, t)) : {M.cm.bytes_onto(_, Con{h, r}) == M.cm.bytes_onto(p, Con{h, r}) : List<&2, U32>} 1536 {==} 1537 1538 def xtsp.d2(~K: Data, ~dec: K -> M.CmBlock -> M.CmBlock, +k: K, +t: M.CmBlock, ec: List<&2, M.CmBlock>, +sc: M.CmBlock, +st: List<&2, U32>, +n: Nat) -> {T.xts.d2(~K, ~dec, k, t, M.CmSplit{List.append(&2, M.CmBlock, ec, Con{sc, Nil{}}), st}, n) == Done{B.Octets.of_list(T.xts.dout(~K, ~dec, k, t, ec, sc, st))} : Result<&2, &2, M.CmError, B.Octets>}: 1539 match ec: 1540 case Nil{}: 1541 {==} 1542 case Con{+e, +es}: 1543 %Equal.sym(List<&2, M.CmBlock>, T.xts.init(List.append(&2, M.CmBlock, es, Con{sc, Nil{}}), e), Con{e, es}, li.init_app(es, sc, e)) : {Done{B.Octets.of_list(T.xts.dout(~K, ~dec, k, t, _, T.xts.last(List.append(&2, M.CmBlock, es, Con{sc, Nil{}}), e), st))} == Done{B.Octets.of_list(T.xts.dout(~K, ~dec, k, t, Con{e, es}, sc, st))} : Result<&2, &2, M.CmError, B.Octets>} 1544 %Equal.sym(M.CmBlock, T.xts.last(List.append(&2, M.CmBlock, es, Con{sc, Nil{}}), e), sc, li.last_app(es, sc, e)) : {Done{B.Octets.of_list(T.xts.dout(~K, ~dec, k, t, Con{e, es}, _, st))} == Done{B.Octets.of_list(T.xts.dout(~K, ~dec, k, t, Con{e, es}, sc, st))} : Result<&2, &2, M.CmError, B.Octets>} 1545 {==} 1546 1547 def Laws.xts_round_trip(K, enc, dec, inv, k1, k2, i, p, hi, hp): 1548 +hne = sp.nonempty(B.Octets.to_list(p))(oc.le16(p, hp)) 1549 +mo = Equal.trans(List<&2, U32>, B.mask(M.cm.join_onto(List.append(&2, M.CmBlock, T.xts.enc(~K, ~enc, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))), Con{T.xts.steal_c(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), Nil{}}), T.xts.steal_t(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))))), M.cm.join_onto(List.append(&2, M.CmBlock, T.xts.enc(~K, ~enc, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))), Con{T.xts.steal_c(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), Nil{}}), B.mask(T.xts. 1550 # the public defs are the structural ones 1551 %tr.xts_encrypt(~K, ~enc, k1, k2, i, p) : {Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, _, c => T.Xts.decrypt(~K, ~enc, ~dec, k1, k2, i, c)) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1552 %tr.bind_cong(T.Xts.encrypt.ref(~K, ~enc, k1, k2, i, p), c => T.Xts.decrypt.ref(~K, ~enc, ~dec, k1, k2, i, c), c => T.Xts.decrypt(~K, ~enc, ~dec, k1, k2, i, c), c => tr.xts_decrypt(~K, ~enc, ~dec, k1, k2, i, c)) : {_ == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1553 # the tweak 1554 %Equal.sym(Result<&2, &2, M.CmError, M.CmBlock>, T.xts.tweak(~K, ~enc, k2, i), Done{enc(k2, M.cm.block_of(B.Octets.to_list(i)))}, xtsp.tweak(~K, ~enc, k2, i, hi)) : {Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, T.xts.e1(~K, ~enc, k1, _, B.Octets.to_list(p)), c => T.xts.d1(~K, ~dec, k1, _, B.Octets.to_list(c))) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1555 # the data unit is masked 1556 %oc.masked(p) : {Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, T.xts.e2(~K, ~enc, k1, enc(k2, M.cm.block_of(B.Octets.to_list(i))), M.cm.split(_), B.len(B.Octets.to_list(p))), c => T.xts.d1(~K, ~dec, k1, Done{enc(k2, M.cm.block_of(B.Octets.to_list(i)))}, B.Octets.to_list(c))) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1557 # its blocks and tail 1558 %sp.eta(M.cm.split(B.mask(B.Octets.to_list(p)))) : {Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, T.xts.e2(~K, ~enc, k1, enc(k2, M.cm.block_of(B.Octets.to_list(i))), _, B.len(B.Octets.to_list(p))), c => T.xts.d1(~K, ~dec, k1, Done{enc(k2, M.cm.block_of(B.Octets.to_list(i)))}, B.Octets.to_list(c))) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1559 # at least one block, so encryption succeeds 1560 %hne : {Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, T.xts.e2(~K, ~enc, k1, enc(k2, M.cm.block_of(B.Octets.to_list(i))), M.CmSplit{_, M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p))))}, B.len(B.Octets.to_list(p))), c => T.xts.d1(~K, ~dec, k1, Done{enc(k2, M.cm.block_of(B.Octets.to_list(i)))}, B.Octets.to_list(c))) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1561 # decryption reads the ciphertext back, masked 1562 %Equal.sym(List<&2, U32>, B.Octets.to_list(B.Octets.of_list(M.cm.join_onto(List.append(&2, M.CmBlock, T.xts.enc(~K, ~enc, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))), Con{T.xts.steal_c(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), Nil{}}), T.xts.steal_t(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))))))), B.mask(M.cm.join_onto(List.append(&2, M.CmBlock, T.xts.enc(~K, ~enc, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))), Con{T.xts.steal_c(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i) 1563 # which it already is 1564 %Equal.sym(List<&2, U32>, B.mask(M.cm.join_onto(List.append(&2, M.CmBlock, T.xts.enc(~K, ~enc, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))), Con{T.xts.steal_c(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), Nil{}}), T.xts.steal_t(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))))), M.cm.join_onto(List.append(&2, M.CmBlock, T.xts.enc(~K, ~enc, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))), Con{T.xts.steal_c(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), Nil{}}), T.xts.steal_t(~K, ~e 1565 # it splits into the ciphertext blocks and the partial block 1566 %Equal.sym(M.CmSplit, M.cm.split(M.cm.join_onto(List.append(&2, M.CmBlock, T.xts.enc(~K, ~enc, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))), Con{T.xts.steal_c(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), Nil{}}), T.xts.steal_t(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))))), M.CmSplit{List.append(&2, M.CmBlock, T.xts.enc(~K, ~enc, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))), Con{T.xts.steal_c(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), Nil{}}), T.xts.steal_t(~K, ~enc, k 1567 # decryption takes the last block apart 1568 %Equal.sym(Result<&2, &2, M.CmError, B.Octets>, T.xts.d2(~K, ~dec, k1, enc(k2, M.cm.block_of(B.Octets.to_list(i))), M.CmSplit{List.append(&2, M.CmBlock, T.xts.enc(~K, ~enc, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))), Con{T.xts.steal_c(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), Nil{}}), T.xts.steal_t(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))))}, B.len(B.Octets.to_list(B.Octets.of_list(M.cm.join_onto(List.append(&2, M.CmBlock, T.xts.enc(~K, ~enc, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))), Con{T.xts.steal_c(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm 1569 # XTS on blocks 1570 %Equal.sym(List<&2, M.CmBlock>, T.xts.dec(~K, ~dec, k1, T.xts.enc(~K, ~enc, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))), T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), xtsp.go(~K, ~enc, ~dec, ~inv, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))) : {Done{B.Octets.of_list(M.cm.join_onto(_, T.xts.dsteal(~K, ~dec, k1, T.xts.steal_c(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), T.xts.steal_t(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.enc(~K, ~enc, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))))) 1571 # as many ciphertext blocks as plaintext blocks: the same last tweak 1572 %Equal.sym(Nat, List.length(&2, M.CmBlock, T.xts.enc(~K, ~enc, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), li.len_enc(~K, ~enc, k1, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))) : {Done{B.Octets.of_list(M.cm.join_onto(T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), T.xts.dsteal(~K, ~dec, k1, T.xts.steal_c(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), T.xts.steal_t(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), T.xts.alpha_n(_, enc(k2, M.cm.block_of(B.Octets.to_list(i)))))))} == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1573 # ciphertext stealing undoes itself 1574 %Equal.sym(List<&2, U32>, T.xts.dsteal(~K, ~dec, k1, T.xts.steal_c(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), T.xts.steal_t(~K, ~enc, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i))))), M.cm.bytes_onto(T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p))))), xtsp.steal(~K, ~enc, ~dec, ~inv, k1, T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p)))), T.xts.alpha_n(List.length(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))), enc(k2, M.cm.block_of(B.Octets.to_list(i)))))(sp.tail_masked(B.Octets.to_list(p)))(sp.tail_short(B.Octets.to_list(p)))) : {Don 1575 # the blocks back together 1576 %sp.join_append(T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p))))) : {Done{B.Octets.of_list(_)} == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1577 # 1578 %Equal.sym(List<&2, M.CmBlock>, List.append(&2, M.CmBlock, T.xts.init(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), Con{T.xts.last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))), Nil{}}), Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))}, li.init_last(sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))))) : {Done{B.Octets.of_list(M.cm.join_onto(_, M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p))))))} == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1579 # 1580 %Equal.sym(List<&2, M.CmBlock>, Con{sp.hd(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p))))), sp.tl(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))))}, M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))), hne) : {Done{B.Octets.of_list(M.cm.join_onto(_, M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p))))))} == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1581 # and with the tail, the data unit 1582 %Equal.sym(List<&2, U32>, M.cm.join_onto(M.cm.split.blocks(M.cm.split(B.mask(B.Octets.to_list(p)))), M.cm.split.tail(M.cm.split(B.mask(B.Octets.to_list(p))))), B.mask(B.Octets.to_list(p)), sp.join_split(B.Octets.to_list(p))) : {Done{B.Octets.of_list(_)} == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1583 # 1584 %Equal.sym(List<&2, U32>, B.mask(B.Octets.to_list(p)), B.Octets.to_list(p), oc.masked(p)) : {Done{B.Octets.of_list(_)} == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1585 # 1586 %Equal.sym(B.Octets, B.Octets.of_list(B.Octets.to_list(p)), p, BL.octets_of_to(p)) : {Done{_} == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1587 {==} 1588 # XOR with a byte twice, and with itself 1589 1590 def bx.wself(n: Nat, w: Word(n)) -> {Word.xor(n, w, w) == Word.zero(n) : Word(n)}: 1591 match n: 1592 case 0n: 1593 match w: 1594 case WNil{}: 1595 {==} 1596 case 1n+p: 1597 match w: 1598 case WCon{h, t}: 1599 match h: 1600 case False{}: 1601 %bx.wself(p, t) : {WCon{False{}, Word.xor(p, t, t)} == WCon{False{}, _} : Word(1n+p)} 1602 {==} 1603 case True{}: 1604 %bx.wself(p, t) : {WCon{False{}, Word.xor(p, t, t)} == WCon{False{}, _} : Word(1n+p)} 1605 {==} 1606 1607 def bits.xor_self(a: U32) -> {B.byte(U32.xor(a, a)) == 0 : U32}: 1608 match a: 1609 case U32{x}: 1610 %Equal.sym(Word(32n), Word.xor(32n, x, x), Word.zero(32n), bx.wself(32n, x)) : {B.byte(U32{_}) == 0 : U32} 1611 {==} 1612 1613 def bits.xor_xor(a: U32, y: U32) -> {B.byte(U32.xor(B.byte(U32.xor(a, y)), y)) == B.byte(a) : U32}: 1614 match a y: 1615 case U32{WCon{a0, WCon{a1, WCon{a2, WCon{a3, WCon{a4, WCon{a5, WCon{a6, WCon{a7, WCon{a8, WCon{a9, WCon{a10, WCon{a11, WCon{a12, WCon{a13, WCon{a14, WCon{a15, WCon{a16, WCon{a17, WCon{a18, WCon{a19, WCon{a20, WCon{a21, WCon{a22, WCon{a23, WCon{a24, WCon{a25, WCon{a26, WCon{a27, WCon{a28, WCon{a29, WCon{a30, WCon{a31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} U32{WCon{y0, WCon{y1, WCon{y2, WCon{y3, WCon{y4, WCon{y5, WCon{y6, WCon{y7, WCon{y8, WCon{y9, WCon{y10, WCon{y11, WCon{y12, WCon{y13, WCon{y14, WCon{y15, WCon{y16, WCon{y17, WCon{y18, WCon{y19, WCon{y20, WCon{y21, WCon{y22, WCon{y23, WCon{y24, WCon{y25, WCon{y26, WCon{y27, WCon{y28, WCon{y29, WCon{y30, WCon{y31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}: 1616 %Equal.sym(Word(8n), Word.xor(8n, Word.xor(8n, WCon{a0, WCon{a1, WCon{a2, WCon{a3, WCon{a4, WCon{a5, WCon{a6, WCon{a7, WNil{}}}}}}}}}, WCon{y0, WCon{y1, WCon{y2, WCon{y3, WCon{y4, WCon{y5, WCon{y6, WCon{y7, WNil{}}}}}}}}}), WCon{y0, WCon{y1, WCon{y2, WCon{y3, WCon{y4, WCon{y5, WCon{y6, WCon{y7, WNil{}}}}}}}}}), WCon{a0, WCon{a1, WCon{a2, WCon{a3, WCon{a4, WCon{a5, WCon{a6, WCon{a7, WNil{}}}}}}}}}, bx.rword(8n, WCon{a0, WCon{a1, WCon{a2, WCon{a3, WCon{a4, WCon{a5, WCon{a6, WCon{a7, WNil{}}}}}}}}}, WCon{y0, WCon{y1, WCon{y2, WCon{y3, WCon{y4, WCon{y5, WCon{y6, WCon{y7, WNil{}}}}}}}}})) : {U32{W.W64.bits.cat(8n, 24n, _, Word.zero(24n))} == B.byte(U32{WCon{a0, WCon{a1, WCon{a2, WCon{a3, WCon{a4, WCon{a5, WCon{a6, WCon{a7, WCon{a8, WCon{a9, WCon{a10, WCon{a11, WCon{a12, WCon{a13, WCon{a14, WCon{a15, WCon{a16, WCon{a17, WCon{a18, WCon{a19, WCon{a20, WCon{a21, WCon{a22, WCon{a23, WCon{a24, WCon{a25, WCon{a26, WCon{a27, WCon{a28, WCon{a29, WCon{a30, WCon{a31, WNil{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}) : U32} 1617 {==} 1618 1619 1620 def li.mask_xor(xs: List<&2, U32>, ys: List<&2, U32>) -> {B.mask(M.cm.xor_bytes(xs, ys)) == M.cm.xor_bytes(xs, ys) : List<&2, U32>}: 1621 match xs: 1622 case Nil{}: 1623 {==} 1624 case Con{+a, +s}: 1625 match ys: 1626 case Nil{}: 1627 {==} 1628 case Con{+b, +t}: 1629 %bits.byte_byte(U32.xor(a, b)) : {Con{B.byte(B.byte(U32.xor(a, b))), B.mask(M.cm.xor_bytes(s, t))} == Con{_, M.cm.xor_bytes(s, t)} : List<&2, U32>} 1630 %li.mask_xor(s, t) : {Con{B.byte(B.byte(U32.xor(a, b))), B.mask(M.cm.xor_bytes(s, t))} == Con{B.byte(B.byte(U32.xor(a, b))), _} : List<&2, U32>} 1631 {==} 1632 1633 def li.len_xor(xs: List<&2, U32>, ys: List<&2, U32>) -> {Nat.is_le(B.len(xs), B.len(ys)) == True{} : Bool} -> {B.len(M.cm.xor_bytes(xs, ys)) == B.len(xs) : Nat}: 1634 match xs: 1635 case Nil{}: 1636 h => {==} 1637 case Con{+a, +s}: 1638 match ys: 1639 case Nil{}: 1640 h => bo.absurd({B.len(M.cm.xor_bytes(Con{a, s}, Nil{})) == B.len(Con{a, s}) : Nat}, h) 1641 case Con{+b, +t}: 1642 h => %li.len_xor(s, t)(h) : {1n+B.len(M.cm.xor_bytes(s, t)) == 1n+_ : Nat} 1643 {==} 1644 1645 def li.xor_xor(xs: List<&2, U32>, ys: List<&2, U32>) -> {Nat.is_le(B.len(xs), B.len(ys)) == True{} : Bool} -> {M.cm.xor_bytes(M.cm.xor_bytes(xs, ys), ys) == B.mask(xs) : List<&2, U32>}: 1646 match xs: 1647 case Nil{}: 1648 h => {==} 1649 case Con{+a, +s}: 1650 match ys: 1651 case Nil{}: 1652 h => bo.absurd({M.cm.xor_bytes(M.cm.xor_bytes(Con{a, s}, Nil{}), Nil{}) == B.mask(Con{a, s}) : List<&2, U32>}, h) 1653 case Con{+b, +t}: 1654 h => %Equal.sym(U32, B.byte(U32.xor(B.byte(U32.xor(a, b)), b)), B.byte(a), bits.xor_xor(a, b)) : {Con{_, M.cm.xor_bytes(M.cm.xor_bytes(s, t), t)} == Con{B.byte(a), B.mask(s)} : List<&2, U32>} 1655 %Equal.sym(List<&2, U32>, M.cm.xor_bytes(M.cm.xor_bytes(s, t), t), B.mask(s), li.xor_xor(s, t)(h)) : {Con{B.byte(a), _} == Con{B.byte(a), B.mask(s)} : List<&2, U32>} 1656 {==} 1657 1658 def li.len_bytes(+b: M.CmBlock, +rest: List<&2, U32>) -> {B.len(M.cm.bytes_onto(b, rest)) == Nat.add(16n, B.len(rest)) : Nat}: 1659 {==} 1660 1661 def na.add_zero(a: Nat) -> {Nat.add(a, 0n) == a : Nat}: 1662 match a: 1663 case 0n: 1664 {==} 1665 case 1n+p: 1666 %na.add_zero(p) : {1n+Nat.add(p, 0n) == 1n+_ : Nat} 1667 {==} 1668 1669 def na.add_succ(a: Nat, +b: Nat) -> {Nat.add(a, 1n+b) == 1n+Nat.add(a, b) : Nat}: 1670 match a: 1671 case 0n: 1672 {==} 1673 case 1n+p: 1674 %na.add_succ(p, b) : {1n+Nat.add(p, 1n+b) == 1n+_ : Nat} 1675 {==} 1676 1677 def na.sub_zero(a: Nat) -> {Nat.sub(a, 0n) == a : Nat}: 1678 match a: 1679 case 0n: 1680 {==} 1681 case 1n+p: 1682 {==} 1683 1684 # (a + b) - b == a 1685 def na.sub_add(+a: Nat, +b: Nat) -> {Nat.sub(Nat.add(a, b), b) == a : Nat}: 1686 match b: 1687 case 0n: 1688 %Equal.sym(Nat, Nat.add(a, 0n), a, na.add_zero(a)) : {Nat.sub(_, 0n) == a : Nat} 1689 na.sub_zero(a) 1690 case 1n+p: 1691 %Equal.sym(Nat, Nat.add(a, 1n+p), 1n+Nat.add(a, p), na.add_succ(a, p)) : {Nat.sub(_, 1n+p) == a : Nat} 1692 na.sub_add(a, p) 1693 1694 def na.le_zero(a: Nat) -> {Nat.is_le(0n, a) == True{} : Bool}: 1695 match a: 1696 case 0n: 1697 {==} 1698 case 1n+q: 1699 {==} 1700 1701 # b <= a + b 1702 def na.le_add(+a: Nat, +b: Nat) -> {Nat.is_le(b, Nat.add(a, b)) == True{} : Bool}: 1703 match b: 1704 case 0n: 1705 %Equal.sym(Nat, Nat.add(a, 0n), a, na.add_zero(a)) : {Nat.is_le(0n, _) == True{} : Bool} 1706 na.le_zero(a) 1707 case 1n+p: 1708 %Equal.sym(Nat, Nat.add(a, 1n+p), 1n+Nat.add(a, p), na.add_succ(a, p)) : {Nat.is_le(1n+p, _) == True{} : Bool} 1709 na.le_add(a, p) 1710 1711 def bo.and_r(+a: Bool, +b: Bool) -> {Bool.and(a, b) == True{} : Bool} -> {b == True{} : Bool}: 1712 match a: 1713 case False{}: 1714 h => bo.absurd({b == True{} : Bool}, h) 1715 case True{}: 1716 h => h 1717 1718 def bo.and_l(+a: Bool, +b: Bool) -> {Bool.and(a, b) == True{} : Bool} -> {a == True{} : Bool}: 1719 match a: 1720 case False{}: 1721 h => bo.absurd({False{} == True{} : Bool}, h) 1722 case True{}: 1723 h => {==} 1724 1725 def rs.disc(r: Result<&2, &2, M.CmError, Unit>) -> Type: 1726 match r: 1727 case Fail{e}: 1728 Unit 1729 case Done{u}: 1730 Empty 1731 1732 def rs.empty(+e: M.CmError, +u: Unit, h: {Fail{e} == Done{u} : Result<&2, &2, M.CmError, Unit>}) -> Empty: 1733 %h : rs.disc(_) 1734 Unit{} 1735 1736 def rs.absurd(-A: Type, +e: M.CmError, +u: Unit, h: {Fail{e} == Done{u} : Result<&2, &2, M.CmError, Unit>}) -> A: 1737 Empty.absurd(A, rs.empty(e, u, h)) 1738 1739 1740 # CCM 1741 1742 # checks that pass mean a tag of at most 16 bytes 1743 def ccmp.tag_le.go(b: Bool, +m: Nat, +nl: Nat, +n: Nat, +u: Unit) -> {CC.ccm.tag_ok(m) == b : Bool} -> {CC.ccm.checks(m, nl, n) == Done{u} : Result<&2, &2, M.CmError, Unit>} -> {Nat.is_le(m, 16n) == True{} : Bool}: 1744 match b: 1745 case False{}: 1746 eb => h => rs.absurd({Nat.is_le(m, 16n) == True{} : Bool}, M.CmBadTagLength{m}, u, Equal.trans(Result<&2, &2, M.CmError, Unit>, CC.ccm.checks.tag(False{}, m, nl, n), CC.ccm.checks.tag(CC.ccm.tag_ok(m), m, nl, n), Done{u}, Equal.cong(Bool, Result<&2, &2, M.CmError, Unit>, x => CC.ccm.checks.tag(x, m, nl, n), False{}, CC.ccm.tag_ok(m), Equal.sym(Bool, CC.ccm.tag_ok(m), False{}, eb)), h)) 1747 case True{}: 1748 eb => h => bo.and_l(Nat.is_le(m, 16n), Nat.is_eq(Nat.mod(m, 2n), 0n))(bo.and_r(Nat.is_le(4n, m), Bool.and(Nat.is_le(m, 16n), Nat.is_eq(Nat.mod(m, 2n), 0n)))(eb)) 1749 1750 def ccmp.tag_le(+m: Nat, +nl: Nat, +n: Nat, +u: Unit, h: {CC.ccm.checks(m, nl, n) == Done{u} : Result<&2, &2, M.CmError, Unit>}) -> {Nat.is_le(m, 16n) == True{} : Bool}: 1751 ccmp.tag_le.go(CC.ccm.tag_ok(m), m, nl, n, u)({==})(h) 1752 1753 def ccmp.diff_self(xs: List<&2, U32>) -> {M.cm.diff(xs, xs, 0) == 0 : U32}: 1754 match xs: 1755 case Nil{}: 1756 {==} 1757 case Con{+a, +s}: 1758 %Equal.sym(U32, B.byte(U32.xor(a, a)), 0, bits.xor_self(a)) : {M.cm.diff(s, s, U32.or(0, _)) == 0 : U32} 1759 ccmp.diff_self(s) 1760 1761 def ccmp.ct_refl(+xs: List<&2, U32>) -> {M.cm.ct_eq(xs, xs) == True{} : Bool}: 1762 %Equal.sym(U32, M.cm.diff(xs, xs, 0), 0, ccmp.diff_self(xs)) : {U32.is_eq(_, 0) == True{} : Bool} 1763 {==} 1764 1765 def ccmp.len_ctrb(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, bs: List<&2, M.CmBlock>, +a0: M.CmBlock, +i: U32) -> {List.length(&2, M.CmBlock, CC.ccm.ctrb(~K, ~enc, k, bs, a0, i)) == List.length(&2, M.CmBlock, bs) : Nat}: 1766 match bs: 1767 case Nil{}: 1768 {==} 1769 case Con{+b, +rest}: 1770 %ccmp.len_ctrb(~K, ~enc, k, rest, a0, U32.add(i, 1)) : {1n+List.length(&2, M.CmBlock, CC.ccm.ctrb(~K, ~enc, k, rest, a0, U32.add(i, 1))) == 1n+_ : Nat} 1771 {==} 1772 1773 # CTR twice is the identity on blocks 1774 def ccmp.ctrb2(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, bs: List<&2, M.CmBlock>, +a0: M.CmBlock, +i: U32) -> {CC.ccm.ctrb(~K, ~enc, k, CC.ccm.ctrb(~K, ~enc, k, bs, a0, i), a0, i) == bs : List<&2, M.CmBlock>}: 1775 match bs: 1776 case Nil{}: 1777 {==} 1778 case Con{+b, +rest}: 1779 %Equal.sym(M.CmBlock, M.CmBlock.xor(M.CmBlock.xor(b, enc(k, CC.ccm.ai(a0, i))), enc(k, CC.ccm.ai(a0, i))), b, bx.rblock(b, enc(k, CC.ccm.ai(a0, i)))) : {Con{_, CC.ccm.ctrb(~K, ~enc, k, CC.ccm.ctrb(~K, ~enc, k, rest, a0, U32.add(i, 1)), a0, U32.add(i, 1))} == Con{b, rest} : List<&2, M.CmBlock>} 1780 %Equal.sym(List<&2, M.CmBlock>, CC.ccm.ctrb(~K, ~enc, k, CC.ccm.ctrb(~K, ~enc, k, rest, a0, U32.add(i, 1)), a0, U32.add(i, 1)), rest, ccmp.ctrb2(~K, ~enc, k, rest, a0, U32.add(i, 1))) : {Con{b, _} == Con{b, rest} : List<&2, M.CmBlock>} 1781 {==} 1782 1783 def ccmp.mask_xcrypt(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +a0: M.CmBlock, s: M.CmSplit) -> {B.mask(CC.ccm.xcrypt(~K, ~enc, k, a0, s)) == CC.ccm.xcrypt(~K, ~enc, k, a0, s) : List<&2, U32>}: 1784 match s: 1785 case M.CmSplit{+bs, +tail}: 1786 %Equal.sym(List<&2, U32>, B.mask(M.cm.join_onto(CC.ccm.ctrb(~K, ~enc, k, bs, a0, 1), M.cm.xor_bytes(tail, M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, bs))))))))), M.cm.join_onto(CC.ccm.ctrb(~K, ~enc, k, bs, a0, 1), B.mask(M.cm.xor_bytes(tail, M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, bs))))))))), sp.mask_join_onto(CC.ccm.ctrb(~K, ~enc, k, bs, a0, 1), M.cm.xor_bytes(tail, M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, bs))))))))) : {_ == M.cm.join_onto(CC.ccm.ctrb(~K, ~enc, k, bs, a0, 1), M.cm.xor_bytes(tail, M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, bs)))))))) : List<&2, U32>} 1787 %li.mask_xor(tail, M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, bs))))))) : {M.cm.join_onto(CC.ccm.ctrb(~K, ~enc, k, bs, a0, 1), B.mask(M.cm.xor_bytes(tail, M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, bs))))))))) == M.cm.join_onto(CC.ccm.ctrb(~K, ~enc, k, bs, a0, 1), _) : List<&2, U32>} 1788 {==} 1789 1790 def ccmp.len_join(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, bs: List<&2, M.CmBlock>, +a0: M.CmBlock, +i: U32, +x: List<&2, U32>, +y: List<&2, U32>, h: {B.len(x) == B.len(y) : Nat}) -> {B.len(M.cm.join_onto(CC.ccm.ctrb(~K, ~enc, k, bs, a0, i), x)) == B.len(M.cm.join_onto(bs, y)) : Nat}: 1791 match bs: 1792 case Nil{}: 1793 h 1794 case Con{+b, +rest}: 1795 %Equal.sym(Nat, B.len(M.cm.join_onto(CC.ccm.ctrb(~K, ~enc, k, rest, a0, U32.add(i, 1)), x)), B.len(M.cm.join_onto(rest, y)), ccmp.len_join(~K, ~enc, k, rest, a0, U32.add(i, 1), x, y, h)) : {Nat.add(16n, _) == Nat.add(16n, B.len(M.cm.join_onto(rest, y))) : Nat} 1796 {==} 1797 # the CTR tail is as short as the plaintext tail 1798 def ccmp.xt_short(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +a0: M.CmBlock, +ys: List<&2, U32>) -> {Nat.is_lt(B.len(M.cm.xor_bytes(M.cm.split.tail(M.cm.split(B.mask(ys))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys))))))))))), 16n) == True{} : Bool}: 1799 %Equal.sym(Nat, B.len(M.cm.xor_bytes(M.cm.split.tail(M.cm.split(B.mask(ys))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys))))))))))), B.len(M.cm.split.tail(M.cm.split(B.mask(ys)))), li.len_xor(M.cm.split.tail(M.cm.split(B.mask(ys))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys))))))))))(na.lt_le(B.len(M.cm.split.tail(M.cm.split(B.mask(ys)))), 16n)(sp.tail_short(ys)))) : {Nat.is_lt(_, 16n) == True{} : Bool} 1800 sp.tail_short(ys) 1801 1802 # CTR from counter 1 undoes itself (on a masked byte string) 1803 def ccmp.xx(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +a0: M.CmBlock, +ys: List<&2, U32>) -> {CC.ccm.xcrypt(~K, ~enc, k, a0, M.cm.split(CC.ccm.xcrypt(~K, ~enc, k, a0, M.cm.split(B.mask(ys))))) == B.mask(ys) : List<&2, U32>}: 1804 %sp.eta(M.cm.split(B.mask(ys))) : {CC.ccm.xcrypt(~K, ~enc, k, a0, M.cm.split(CC.ccm.xcrypt(~K, ~enc, k, a0, _))) == B.mask(ys) : List<&2, U32>} 1805 %Equal.sym(M.CmSplit, M.cm.split(M.cm.join_onto(CC.ccm.ctrb(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(ys))), a0, 1), M.cm.xor_bytes(M.cm.split.tail(M.cm.split(B.mask(ys))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys)))))))))))), M.CmSplit{CC.ccm.ctrb(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(ys))), a0, 1), M.cm.xor_bytes(M.cm.split.tail(M.cm.split(B.mask(ys))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys))))))))))}, sp.split_join_short(CC.ccm.ctrb(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(ys))), a0, 1), M.cm.xor_bytes(M.cm.split.tail(M.cm.split(B.mask(ys))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys)))))))))))(sp.short_split(M.cm.xor_bytes(M.cm.split.tail(M.cm.split(B.mask(ys))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys)))))))))))(ccmp.xt_short(~K, ~enc, k, a0, ys)))) : {CC.ccm.xcrypt(~K, ~enc, k, a0, _) == B.mask(ys) : List<&2, U32>} 1806 %Equal.sym(Nat, List.length(&2, M.CmBlock, CC.ccm.ctrb(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(ys))), a0, 1)), List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys)))), ccmp.len_ctrb(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(ys))), a0, 1)) : {M.cm.join_onto(CC.ccm.ctrb(~K, ~enc, k, CC.ccm.ctrb(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(ys))), a0, 1), a0, 1), M.cm.xor_bytes(M.cm.xor_bytes(M.cm.split.tail(M.cm.split(B.mask(ys))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys)))))))))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(_))))))) == B.mask(ys) : List<&2, U32>} 1807 %Equal.sym(List<&2, M.CmBlock>, CC.ccm.ctrb(~K, ~enc, k, CC.ccm.ctrb(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(ys))), a0, 1), a0, 1), M.cm.split.blocks(M.cm.split(B.mask(ys))), ccmp.ctrb2(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(ys))), a0, 1)) : {M.cm.join_onto(_, M.cm.xor_bytes(M.cm.xor_bytes(M.cm.split.tail(M.cm.split(B.mask(ys))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys)))))))))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys))))))))))) == B.mask(ys) : List<&2, U32>} 1808 %Equal.sym(List<&2, U32>, M.cm.xor_bytes(M.cm.xor_bytes(M.cm.split.tail(M.cm.split(B.mask(ys))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys)))))))))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys)))))))))), B.mask(M.cm.split.tail(M.cm.split(B.mask(ys)))), li.xor_xor(M.cm.split.tail(M.cm.split(B.mask(ys))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys))))))))))(na.lt_le(B.len(M.cm.split.tail(M.cm.split(B.mask(ys)))), 16n)(sp.tail_short(ys)))) : {M.cm.join_onto(M.cm.split.blocks(M.cm.split(B.mask(ys))), _) == B.mask(ys) : List<&2, U32>} 1809 %Equal.sym(List<&2, U32>, B.mask(M.cm.split.tail(M.cm.split(B.mask(ys)))), M.cm.split.tail(M.cm.split(B.mask(ys))), sp.tail_masked(ys)) : {M.cm.join_onto(M.cm.split.blocks(M.cm.split(B.mask(ys))), _) == B.mask(ys) : List<&2, U32>} 1810 sp.join_split(ys) 1811 1812 # and keeps its length 1813 def ccmp.len_xc(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +a0: M.CmBlock, +ys: List<&2, U32>) -> {B.len(CC.ccm.xcrypt(~K, ~enc, k, a0, M.cm.split(B.mask(ys)))) == B.len(B.mask(ys)) : Nat}: 1814 %sp.eta(M.cm.split(B.mask(ys))) : {B.len(CC.ccm.xcrypt(~K, ~enc, k, a0, _)) == B.len(B.mask(ys)) : Nat} 1815 %sp.join_split(ys) : {B.len(M.cm.join_onto(CC.ccm.ctrb(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(ys))), a0, 1), M.cm.xor_bytes(M.cm.split.tail(M.cm.split(B.mask(ys))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys)))))))))))) == B.len(_) : Nat} 1816 ccmp.len_join(~K, ~enc, k, M.cm.split.blocks(M.cm.split(B.mask(ys))), a0, 1, M.cm.xor_bytes(M.cm.split.tail(M.cm.split(B.mask(ys))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys)))))))))), M.cm.split.tail(M.cm.split(B.mask(ys))), li.len_xor(M.cm.split.tail(M.cm.split(B.mask(ys))), M.cm.bytes_of(enc(k, CC.ccm.ai(a0, U32.add(1, U32.from_nat(List.length(&2, M.CmBlock, M.cm.split.blocks(M.cm.split(B.mask(ys))))))))))(na.lt_le(B.len(M.cm.split.tail(M.cm.split(B.mask(ys)))), 16n)(sp.tail_short(ys)))) 1817 1818 def ccmp.xxp(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +a0: M.CmBlock, +p: B.Octets) -> {CC.ccm.xcrypt(~K, ~enc, k, a0, M.cm.split(CC.ccm.xcrypt(~K, ~enc, k, a0, M.cm.split(B.Octets.to_list(p))))) == B.Octets.to_list(p) : List<&2, U32>}: 1819 %oc.masked(p) : {CC.ccm.xcrypt(~K, ~enc, k, a0, M.cm.split(CC.ccm.xcrypt(~K, ~enc, k, a0, M.cm.split(_)))) == _ : List<&2, U32>} 1820 ccmp.xx(~K, ~enc, k, a0, B.Octets.to_list(p)) 1821 1822 def ccmp.len_xcp(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +a0: M.CmBlock, +p: B.Octets) -> {B.len(CC.ccm.xcrypt(~K, ~enc, k, a0, M.cm.split(B.Octets.to_list(p)))) == B.len(B.Octets.to_list(p)) : Nat}: 1823 %oc.masked(p) : {B.len(CC.ccm.xcrypt(~K, ~enc, k, a0, M.cm.split(_))) == B.len(_) : Nat} 1824 ccmp.len_xc(~K, ~enc, k, a0, B.Octets.to_list(p)) 1825 1826 def ccmp.len_tag(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +m: Nat, +l: Nat, +nv: List<&2, U32>, +av: List<&2, U32>, +pv: List<&2, U32>, h: {Nat.is_le(m, 16n) == True{} : Bool}) -> {B.len(CC.ccm.tag(~K, ~enc, k, m, l, nv, av, pv)) == m : Nat}: 1827 li.len_take(m, M.cm.bytes_of(CC.ccm.mac(~K, ~enc, k, m, l, nv, av, pv)))(h) 1828 1829 def ccmp.le_tag(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +m: Nat, +l: Nat, +nv: List<&2, U32>, +av: List<&2, U32>, +pv: List<&2, U32>, +h: {Nat.is_le(m, 16n) == True{} : Bool}) -> {Nat.is_le(B.len(CC.ccm.tag(~K, ~enc, k, m, l, nv, av, pv)), 16n) == True{} : Bool}: 1830 %Equal.sym(Nat, B.len(CC.ccm.tag(~K, ~enc, k, m, l, nv, av, pv)), m, ccmp.len_tag(~K, ~enc, k, m, l, nv, av, pv, h)) : {Nat.is_le(_, 16n) == True{} : Bool} 1831 h 1832 1833 def ccmp.mask_tag(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +m: Nat, +l: Nat, +nv: List<&2, U32>, +av: List<&2, U32>, +pv: List<&2, U32>) -> {B.mask(CC.ccm.tag(~K, ~enc, k, m, l, nv, av, pv)) == CC.ccm.tag(~K, ~enc, k, m, l, nv, av, pv) : List<&2, U32>}: 1834 %Equal.sym(List<&2, U32>, B.mask(CC.ccm.tag(~K, ~enc, k, m, l, nv, av, pv)), B.take(m, B.mask(M.cm.bytes_of(CC.ccm.mac(~K, ~enc, k, m, l, nv, av, pv)))), li.mask_take(m, M.cm.bytes_of(CC.ccm.mac(~K, ~enc, k, m, l, nv, av, pv)))) : {_ == CC.ccm.tag(~K, ~enc, k, m, l, nv, av, pv) : List<&2, U32>} 1835 %Equal.sym(List<&2, U32>, B.mask(M.cm.bytes_onto(CC.ccm.mac(~K, ~enc, k, m, l, nv, av, pv), Nil{})), M.cm.bytes_onto(CC.ccm.mac(~K, ~enc, k, m, l, nv, av, pv), B.mask(Nil{})), sp.mask_blk(CC.ccm.mac(~K, ~enc, k, m, l, nv, av, pv), Nil{})) : {B.take(m, _) == CC.ccm.tag(~K, ~enc, k, m, l, nv, av, pv) : List<&2, U32>} 1836 {==} 1837 1838 def ccmp.mask_eb(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +m: Nat, +nv: List<&2, U32>, +av: List<&2, U32>, +pv: List<&2, U32>) -> {B.mask(B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv)), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))))) == B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv)), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv))))) : List<&2, U32>}: 1839 %Equal.sym(List<&2, U32>, B.mask(B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv)), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))))), B.append(B.mask(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv))), B.mask(M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))))), li.mask_append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv)), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))))) : {_ == B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv)), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv))))) : List<&2, U32>} 1840 %ccmp.mask_xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv)) : {B.append(B.mask(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv))), B.mask(M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))))) == B.append(_, M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv))))) : List<&2, U32>} 1841 %li.mask_xor(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))) : {B.append(B.mask(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv))), B.mask(M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))))) == B.append(B.mask(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv))), _) : List<&2, U32>} 1842 {==} 1843 1844 def ccmp.len_eb(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +m: Nat, +nv: List<&2, U32>, +av: List<&2, U32>, +pv: List<&2, U32>, +h: {Nat.is_le(m, 16n) == True{} : Bool}) -> {B.len(B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv)), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))))) == Nat.add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv))), m) : Nat}: 1845 %Equal.sym(Nat, B.len(B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv)), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))))), Nat.add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv))), B.len(M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))))), li.len_append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv)), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv)))))) : {_ == Nat.add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv))), m) : Nat} 1846 %Equal.sym(Nat, B.len(M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv))))), B.len(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv)), li.len_xor(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv))))(ccmp.le_tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv, h))) : {Nat.add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv))), _) == Nat.add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv))), m) : Nat} 1847 %Equal.sym(Nat, B.len(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv)), m, ccmp.len_tag(~K, ~enc, k, m, Nat.sub(15n, B.len(nv)), nv, av, pv, h)) : {Nat.add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv))), _) == Nat.add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(nv)), nv), M.cm.split(pv))), m) : Nat} 1848 {==} 1849 1850 # decryption accepts what encryption produced, whatever the parameter checks answer 1851 def ccmp.main(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, +k: K, +m: Nat, +nonce: B.Octets, +aad: B.Octets, +p: B.Octets, r: Result<&2, &2, M.CmError, Unit>) -> {CC.ccm.checks(m, B.len(B.Octets.to_list(nonce)), B.len(B.Octets.to_list(p))) == r : Result<&2, &2, M.CmError, Unit>} -> {Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, CC.ccm.e2(~K, ~enc, k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p), r), c => CC.Ccm.decrypt.ref(~K, ~enc, k, m, nonce, aad, c)) == Result.map(&2, &2, M.CmError, B.Octets, B.Octets, c => p, CC.ccm.e2(~K, ~enc, k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p), r)) : Result<&2, &2, M.CmError, B.Octets>}: 1852 match r: 1853 case Fail{e}: 1854 h => {==} 1855 case Done{+u}: 1856 +h => +hm = ccmp.tag_le(m, B.len(B.Octets.to_list(nonce)), B.len(B.Octets.to_list(p)), u, h) 1857 +leb = ccmp.len_eb(~K, ~enc, k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p), hm) 1858 # decryption reads the ciphertext back, masked 1859 %Equal.sym(List<&2, U32>, B.Octets.to_list(B.Octets.of_list(B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)))))))), B.mask(B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))), BL.octets_to_of(B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)))))))) : {CC.ccm.d2(~K, ~enc, Nat.is_le(m, B.len(_)), k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), _) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1860 # which it already is 1861 %Equal.sym(List<&2, U32>, B.mask(B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))), B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)))))), ccmp.mask_eb(~K, ~enc, k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p))) : {CC.ccm.d2(~K, ~enc, Nat.is_le(m, B.len(_)), k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), _) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1862 # it is longer than the tag 1863 %Equal.sym(Nat, B.len(B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))), Nat.add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), m), leb) : {CC.ccm.d2(~K, ~enc, Nat.is_le(m, _), k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1864 # 1865 %Equal.sym(Bool, Nat.is_le(m, Nat.add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), m)), True{}, na.le_add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), m)) : {CC.ccm.d2(~K, ~enc, _, k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1866 # its body is as long as the message 1867 %Equal.sym(Nat, B.len(B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))), Nat.add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), m), leb) : {CC.ccm.d3(~K, ~enc, k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)))))), CC.ccm.checks(m, B.len(B.Octets.to_list(nonce)), Nat.sub(_, m))) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1868 # 1869 %Equal.sym(Nat, Nat.sub(Nat.add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), m), m), B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), na.sub_add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), m)) : {CC.ccm.d3(~K, ~enc, k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)))))), CC.ccm.checks(m, B.len(B.Octets.to_list(nonce)), _)) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1870 # 1871 %Equal.sym(Nat, B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), B.len(B.Octets.to_list(p)), ccmp.len_xcp(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), p)) : {CC.ccm.d3(~K, ~enc, k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)))))), CC.ccm.checks(m, B.len(B.Octets.to_list(nonce)), _)) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1872 # so its checks pass as encryption's did 1873 %Equal.sym(Result<&2, &2, M.CmError, Unit>, CC.ccm.checks(m, B.len(B.Octets.to_list(nonce)), B.len(B.Octets.to_list(p))), Done{u}, h) : {CC.ccm.d3(~K, ~enc, k, m, B.Octets.to_list(nonce), B.Octets.to_list(aad), B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)))))), _) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1874 # the body and the tag apart 1875 %Equal.sym(Nat, B.len(B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))), Nat.add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), m), leb) : {CC.ccm.open(M.cm.ct_eq(M.cm.xor_bytes(B.drop(Nat.sub(_, m), B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))), CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.take(Nat.sub(_, m), B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))))))), CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm 1876 # 1877 %Equal.sym(Nat, Nat.sub(Nat.add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), m), m), B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), na.sub_add(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), m)) : {CC.ccm.open(M.cm.ct_eq(M.cm.xor_bytes(B.drop(_, B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))), CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.take(_, B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))))))), CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.take(_, B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list( 1878 # 1879 %Equal.sym(List<&2, U32>, B.take(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))), CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), li.take_append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))) : {CC.ccm.open(M.cm.ct_eq(M.cm.xor_bytes(B.drop(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))), CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Oct 1880 # 1881 %Equal.sym(List<&2, U32>, B.drop(B.len(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p)))), B.append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))), li.drop_append(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))), M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))))) : {CC.ccm.open(M.cm.ct_eq(M.cm.xor_bytes(_, M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))), CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))))))), CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(1 1882 # CTR undoes itself: the plaintext 1883 %Equal.sym(List<&2, U32>, CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(CC.ccm.xcrypt(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), M.cm.split(B.Octets.to_list(p))))), B.Octets.to_list(p), ccmp.xxp(~K, ~enc, k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)), p)) : {CC.ccm.open(M.cm.ct_eq(M.cm.xor_bytes(M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))), CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), _)), _) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1884 # the received tag, unmasked from S_0 1885 %Equal.sym(List<&2, U32>, M.cm.xor_bytes(M.cm.xor_bytes(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce))))), B.mask(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p))), li.xor_xor(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), M.cm.bytes_of(enc(k, CC.ccm.a0(Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce)))))(ccmp.le_tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p), hm))) : {CC.ccm.open(M.cm.ct_eq(_, CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p))), B.Octets.to_list(p)) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1886 # 1887 %Equal.sym(List<&2, U32>, B.mask(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p))), CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), ccmp.mask_tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p))) : {CC.ccm.open(M.cm.ct_eq(_, CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p))), B.Octets.to_list(p)) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1888 # matches the tag recomputed 1889 %Equal.sym(Bool, M.cm.ct_eq(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)), CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p))), True{}, ccmp.ct_refl(CC.ccm.tag(~K, ~enc, k, m, Nat.sub(15n, B.len(B.Octets.to_list(nonce))), B.Octets.to_list(nonce), B.Octets.to_list(aad), B.Octets.to_list(p)))) : {CC.ccm.open(_, B.Octets.to_list(p)) == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1890 # 1891 %Equal.sym(B.Octets, B.Octets.of_list(B.Octets.to_list(p)), p, BL.octets_of_to(p)) : {Done{_} == Done{p} : Result<&2, &2, M.CmError, B.Octets>} 1892 {==} 1893 1894 def Laws.ccm_round_trip(K, enc, k, m, nonce, aad, p): 1895 # the public defs are the structural ones 1896 %tr.ccm_encrypt(~K, ~enc, k, m, nonce, aad, p) : {Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, _, c => CC.Ccm.decrypt(~K, ~enc, k, m, nonce, aad, c)) == Result.map(&2, &2, M.CmError, B.Octets, B.Octets, c => p, _) : Result<&2, &2, M.CmError, B.Octets>} 1897 %tr.bind_cong(CC.Ccm.encrypt.ref(~K, ~enc, k, m, nonce, aad, p), c => CC.Ccm.decrypt.ref(~K, ~enc, k, m, nonce, aad, c), c => CC.Ccm.decrypt(~K, ~enc, k, m, nonce, aad, c), c => tr.ccm_decrypt(~K, ~enc, k, m, nonce, aad, c)) : {_ == Result.map(&2, &2, M.CmError, B.Octets, B.Octets, c => p, CC.Ccm.encrypt.ref(~K, ~enc, k, m, nonce, aad, p)) : Result<&2, &2, M.CmError, B.Octets>} 1898 ccmp.main(~K, ~enc, k, m, nonce, aad, p, CC.ccm.checks(m, B.len(B.Octets.to_list(nonce)), B.len(B.Octets.to_list(p))))({==}) 1899 1900 # A block through Octets and back 1901 1902 def Laws.block_octets_round_trip(b): 1903 %Equal.sym(List<&2, U32>, B.Octets.to_list(B.Octets.of_list(M.cm.bytes_of(b))), B.mask(M.cm.bytes_of(b)), BL.octets_to_of(M.cm.bytes_of(b))) : {M.CmBlock.of_octets.pick(Nat.is_eq(B.len(_), 16n), _) == Some{b} : Maybe<&2, M.CmBlock>} 1904 %Equal.sym(List<&2, U32>, B.mask(M.cm.bytes_onto(b, Nil{})), M.cm.bytes_onto(b, B.mask(Nil{})), sp.mask_blk(b, Nil{})) : {M.CmBlock.of_octets.pick(Nat.is_eq(B.len(_), 16n), _) == Some{b} : Maybe<&2, M.CmBlock>} 1905 %Equal.sym(M.CmBlock, M.cm.block_of(M.cm.bytes_of(b)), b, sp.block_bytes(b)) : {Some{_} == Some{b} : Maybe<&2, M.CmBlock>} 1906 {==} 1907 1908 # Vectors 1909 1910 def Laws.aes128_fips197_c1(): 1911 {==} 1912 1913 def Laws.aes_bad_key_length(): 1914 {==} 1915 1916 def Laws.cbc_sp800_38a_f21_block1(): 1917 {==} 1918 1919 def Laws.cbc_not_whole_blocks(): 1920 {==} 1921 1922 def Laws.cbc_short_iv(): 1923 {==} 1924 1925 def Laws.pkcs7_pad_empty(): 1926 {==} 1927 1928 def Laws.pkcs7_pad_15(): 1929 {==} 1930 1931 def Laws.pkcs7_unpad_15(): 1932 {==} 1933 1934 def Laws.pkcs7_unpad_zero(): 1935 {==} 1936 1937 def Laws.pkcs7_unpad_mixed(): 1938 {==} 1939 1940 def Laws.xts_short(): 1941 {==} 1942 1943 def Laws.xts_sector(): 1944 {==} 1945 1946 def Laws.ccm_bad_tag_length(): 1947 {==} 1948 1949 def Laws.ccm_bad_nonce_length(): 1950 {==} 1951 1952 def Laws.cmac_rfc4493_k1(): 1953 {==}