1 # Camellia: RFC 3713's three vectors, both ways (the ciphertext, then the 2 # plaintext decrypted back), and Camellia-128 through cbc's CBC over 3 # 32 KB both ways. 4 import Base 5 import bend-osdev-bytes@0.1.1.0/bytes.bend as B 6 import bend-osdev-mode-core@0.1.0.0/mode_core.bend as M 7 import bend-osdev-cbc@0.1.0.0/cbc.bend as CB 8 import bend-osdev-cipher-core@0.1.0.0/cipher_core.bend as L 9 import ./camellia.bend as C 10 11 def b128.of(m: Maybe<&2, M.CmBlock>) -> M.CmBlock: 12 match m: 13 case None{}: 14 M.CmBlock.zero() 15 case Some{b}: 16 b 17 18 def b128(o: B.Octets) -> M.CmBlock: 19 b128.of(M.CmBlock.of_octets(o)) 20 21 def key(~K: Data, r: Result<&2, &2, L.LcError, K>, d: K) -> K: 22 match r: 23 case Fail{e}: 24 d 25 case Done{k}: 26 k 27 28 def both(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, ~dec: K -> M.CmBlock -> M.CmBlock, +k: K, b: M.CmBlock) -> String: 29 +c = enc(k, b) 30 M.CmBlock.hex(c) ++ " " ++ M.CmBlock.hex(dec(k, c)) 31 32 def camellia(k: B.Octets, b: B.Octets) -> String: 33 both(~C.LcCamelliaKey, ~C.LcCamellia.encrypt, ~C.LcCamellia.decrypt, key(~C.LcCamelliaKey, C.LcCamellia.key(k), C.LcCamelliaKey{Nil{}}), b128(b)) 34 35 # n bytes, byte i = 7i + 3 (mod 256) 36 def big.go(n: Nat, +i: U32, acc: List<&2, U32>) -> List<&2, U32>: 37 match n: 38 case 0n: 39 B.rev(acc) 40 case 1n+p: 41 big.go(p, U32.add(i, 1), Con{U32.and(255, U32.add(U32.mul(i, 7), 3)), acc}) 42 43 def big(n: Nat) -> B.Octets: 44 B.Octets.of_list(big.go(n, 0, Nil{})) 45 46 def iv16() -> B.Octets: 47 B.Octets.of_list([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) 48 49 def last16(r: Result<&2, &2, M.CmError, B.Octets>) -> String: 50 match r: 51 case Fail{e}: 52 "fail" 53 case Done{+o}: 54 B.Octets.hex(B.Octets.drop(Nat.sub(B.Octets.len(o), 16n), o)) 55 56 def verdict(b: Bool) -> String: 57 match b: 58 case True{}: 59 "ok" 60 case False{}: 61 "differs" 62 63 def same(r: Result<&2, &2, M.CmError, B.Octets>, +m: B.Octets) -> String: 64 match r: 65 case Fail{e}: 66 "fail" 67 case Done{o}: 68 verdict(B.Octets.is_eq(o, m)) 69 70 def cbc128(~K: Data, ~enc: K -> M.CmBlock -> M.CmBlock, ~dec: K -> M.CmBlock -> M.CmBlock, +k: K, n: Nat) -> String: 71 +m = big(n) 72 +c = CB.Cbc.encrypt(~K, ~enc, k, iv16(), m) 73 last16(c) ++ " " ++ same(Result.bind(&2, &2, M.CmError, B.Octets, B.Octets, c, x => CB.Cbc.decrypt(~K, ~dec, k, iv16(), x)), m) 74 75 def camellia_cbc(k: B.Octets, n: Nat) -> String: 76 cbc128(~C.LcCamelliaKey, ~C.LcCamellia.encrypt, ~C.LcCamellia.decrypt, key(~C.LcCamelliaKey, C.LcCamellia.key(k), C.LcCamelliaKey{Nil{}}), n) 77 78 # BEGIN GENERATED by gen/vectors.py: check 79 def main() -> IO(Unit): 80 do IO: 81 IO.print(camellia(B.Octets.of_list([1, 35, 69, 103, 137, 171, 205, 239, 254, 220, 186, 152, 118, 84, 50, 16]), B.Octets.of_list([1, 35, 69, 103, 137, 171, 205, 239, 254, 220, 186, 152, 118, 84, 50, 16]))) 82 IO.print(camellia(B.Octets.of_list([1, 35, 69, 103, 137, 171, 205, 239, 254, 220, 186, 152, 118, 84, 50, 16, 0, 17, 34, 51, 68, 85, 102, 119]), B.Octets.of_list([1, 35, 69, 103, 137, 171, 205, 239, 254, 220, 186, 152, 118, 84, 50, 16]))) 83 IO.print(camellia(B.Octets.of_list([1, 35, 69, 103, 137, 171, 205, 239, 254, 220, 186, 152, 118, 84, 50, 16, 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255]), B.Octets.of_list([1, 35, 69, 103, 137, 171, 205, 239, 254, 220, 186, 152, 118, 84, 50, 16]))) 84 IO.print(camellia_cbc(B.Octets.of_list([1, 35, 69, 103, 137, 171, 205, 239, 254, 220, 186, 152, 118, 84, 50, 16]), 32768n)) 85 86 #|67673138549669730857065648eabe43 0123456789abcdeffedcba9876543210 87 #|b4993401b3e996f84ee5cee7d79b09b9 0123456789abcdeffedcba9876543210 88 #|9acc237dff16d76c20ef7c919e3a7509 0123456789abcdeffedcba9876543210 89 #|01fbbba61e8bb08562d59ae3b7e70881 ok 90 # END GENERATED: check