block.bend

bend-osdev-crypto@0.1.0.0 · 55 lines · 4 definitions

1# The block-cipher interface.
2#
3# A block cipher (template arguments, in this order):
4#   ~K: Data                                    its key schedule
5#   ~Blk: Data                                  a block
6#   ~bsize: Nat                                 the block size in bytes
7#   ~key: B.Octets -> Result<&2, &2, CrError, K>
8#                                               the key schedule of a raw
9#                                               key, refusing a key of a
10#                                               length the cipher does not
11#                                               take (CrBadKeyLength{got})
12#   ~enc: K -> Blk -> Blk                       encrypt one block
13#   ~dec: K -> Blk -> Blk                       decrypt one block
14# and its block format, the bytes of a block:
15#   ~blk_of: B.Octets -> Maybe<&2, Blk>         bsize bytes as a block (None
16#                                               for any other length)
17#   ~blk_to: Blk -> B.Octets                    the bsize bytes of a block
18#   ~bxor: Blk -> Blk -> Blk                    two blocks XORed
19# A generic algorithm takes only the arguments it uses (CBC encryption: ~K,
20# ~Blk, ~enc, ~bxor). A value of K is only ever made by ~key, so every K is a
21# valid key, and every value of Blk is a block.
22#
23# Laws, for every key schedule and block (README.md, "Laws"):
24#   round_trip       dec(k, enc(k, b)) == b
25#   round_trip_dual  enc(k, dec(k, b)) == b   (the cipher is a permutation;
26#                                             where the cipher proves it)
27#   format           blk_of(blk_to(b)) == Some{b}
28#   xor              bxor(bxor(a, b), b) == a
29#   key_length       a key of a length the cipher does not take is refused
30#
31# The formats of the existing ciphers: inst_cm.bend (cipher-modes' 128-bit
32# CmBlock) and inst_lc.bend (legacy-ciphers' 64-bit LcBlock64). Modes over
33# any block cipher are in modes.bend.
34import Base
35import bend-osdev-bytes@0.1.0.0/bytes.bend as B
36import bend-osdev-crypto@0.1.0.0/crypto.bend as Cr
37
38def cr.blk.enc(~K: Data, ~Blk: Data, ~enc: K -> Blk -> Blk, ~blk_to: Blk -> B.Octets, m: Maybe<&2, Blk>, +k: K, +n: Nat) -> Result<&2, &2, Cr.CrError, B.Octets>:
39  match m:
40    case None{}:
41      Fail{Cr.CrBadBlockSize{n}}
42    case Some{b}:
43      Done{blk_to(enc(k, b))}
44
45# One block of bytes encrypted (CrBadBlockSize for another length)
46def CrBlockCipher.encrypt_octets(~K: Data, ~Blk: Data, ~enc: K -> Blk -> Blk, ~blk_of: B.Octets -> Maybe<&2, Blk>, ~blk_to: Blk -> B.Octets, +k: K, +o: B.Octets) -> Result<&2, &2, Cr.CrError, B.Octets>:
47  cr.blk.enc(~K, ~Blk, ~enc, ~blk_to, blk_of(o), k, B.Octets.len(o))
48
49# One block of bytes decrypted
50def CrBlockCipher.decrypt_octets(~K: Data, ~Blk: Data, ~dec: K -> Blk -> Blk, ~blk_of: B.Octets -> Maybe<&2, Blk>, ~blk_to: Blk -> B.Octets, +k: K, +o: B.Octets) -> Result<&2, &2, Cr.CrError, B.Octets>:
51  cr.blk.enc(~K, ~Blk, ~dec, ~blk_to, blk_of(o), k, B.Octets.len(o))
52
53# The key schedule of a raw key, then one block of bytes encrypted
54def CrBlockCipher.encrypt_with(~K: Data, ~Blk: Data, ~key: B.Octets -> Result<&2, &2, Cr.CrError, K>, ~enc: K -> Blk -> Blk, ~blk_of: B.Octets -> Maybe<&2, Blk>, ~blk_to: Blk -> B.Octets, key_o: B.Octets, +o: B.Octets) -> Result<&2, &2, Cr.CrError, B.Octets>:
55  Result.bind(&2, &2, Cr.CrError, K, B.Octets, key(key_o), k => CrBlockCipher.encrypt_octets(~K, ~Blk, ~enc, ~blk_of, ~blk_to, k, o))