1 # The modes with AES as the cipher: the named defaults. Each takes the raw key 2 # as Octets and picks AES-128 or AES-256 by its length (XTS: the two keys 3 # joined, 32 or 64 bytes), so a wrong length answers CmBadKeyLength. To 4 # expand a key once and use it many times, call CmAes.key (aes.bend; and 5 # CmAes.prepare before decrypting) and the generic mode with ~X.CmAesKey, 6 # ~X.CmAes.encrypt, ~X.CmAes.decrypt. 7 import Base 8 import bend-osdev-bytes@0.1.0.0/bytes.bend as B 9 import ./cipher_modes.bend as M 10 import ./aes.bend as X 11 import ./cbc.bend as C 12 import ./xts.bend as T 13 import ./ccm.bend as CC 14 import ./cmac.bend as CM 15 16 def CmAes.cbc_encrypt(key: B.Octets, iv: B.Octets, m: B.Octets) -> Result<&2, &2, M.CmError, B.Octets>: 17 do Result<&2, &2, M.CmError, B.Octets>: 18 k : X.CmAesKey <- X.CmAes.key(key) 19 C.Cbc.encrypt(~X.CmAesKey, ~X.CmAes.encrypt, k, iv, m) 20 21 def CmAes.cbc_decrypt(key: B.Octets, iv: B.Octets, c: B.Octets) -> Result<&2, &2, M.CmError, B.Octets>: 22 do Result<&2, &2, M.CmError, B.Octets>: 23 k : X.CmAesKey <- X.CmAes.key(key) 24 C.Cbc.decrypt(~X.CmAesKey, ~X.CmAes.decrypt, X.CmAes.prepare(k), iv, c) 25 26 def CmAes.cbc_encrypt_padded(key: B.Octets, iv: B.Octets, m: B.Octets) -> Result<&2, &2, M.CmError, B.Octets>: 27 do Result<&2, &2, M.CmError, B.Octets>: 28 k : X.CmAesKey <- X.CmAes.key(key) 29 C.Cbc.encrypt_padded(~X.CmAesKey, ~X.CmAes.encrypt, k, iv, m) 30 31 def CmAes.cbc_decrypt_padded(key: B.Octets, iv: B.Octets, c: B.Octets) -> Result<&2, &2, M.CmError, B.Octets>: 32 do Result<&2, &2, M.CmError, B.Octets>: 33 k : X.CmAesKey <- X.CmAes.key(key) 34 C.Cbc.decrypt_padded(~X.CmAesKey, ~X.CmAes.decrypt, X.CmAes.prepare(k), iv, c) 35 36 # XTS-AES-128 (a 32-byte key) or XTS-AES-256 (64 bytes): Key1 (data) then 37 # Key2 (tweak), as IEEE 1619 writes them 38 39 # the data unit p with 16-byte sequence number i (Xts.sector(n) for sector n) 40 def CmAes.xts_encrypt(+key: B.Octets, i: B.Octets, p: B.Octets) -> Result<&2, &2, M.CmError, B.Octets>: 41 +n = B.Octets.len(key) 42 +h = Nat.div(n, 2n) 43 do Result<&2, &2, M.CmError, B.Octets>: 44 M.cm.check(Bool.or(Nat.is_eq(n, 32n), Nat.is_eq(n, 64n)), M.CmBadKeyLength{n}) 45 k1 : X.CmAesKey <- X.CmAes.key(B.Octets.take(h, key)) 46 k2 : X.CmAesKey <- X.CmAes.key(B.Octets.drop(h, key)) 47 T.Xts.encrypt(~X.CmAesKey, ~X.CmAes.encrypt, k1, k2, i, p) 48 49 def CmAes.xts_decrypt(+key: B.Octets, i: B.Octets, c: B.Octets) -> Result<&2, &2, M.CmError, B.Octets>: 50 +n = B.Octets.len(key) 51 +h = Nat.div(n, 2n) 52 do Result<&2, &2, M.CmError, B.Octets>: 53 M.cm.check(Bool.or(Nat.is_eq(n, 32n), Nat.is_eq(n, 64n)), M.CmBadKeyLength{n}) 54 k1 : X.CmAesKey <- X.CmAes.key(B.Octets.take(h, key)) 55 k2 : X.CmAesKey <- X.CmAes.key(B.Octets.drop(h, key)) 56 T.Xts.decrypt(~X.CmAesKey, ~X.CmAes.encrypt, ~X.CmAes.decrypt, X.CmAes.prepare(k1), k2, i, c) 57 58 # CCM with an m-byte tag: the ciphertext, then the tag 59 def CmAes.ccm_encrypt(key: B.Octets, +m: Nat, nonce: B.Octets, aad: B.Octets, p: B.Octets) -> Result<&2, &2, M.CmError, B.Octets>: 60 do Result<&2, &2, M.CmError, B.Octets>: 61 k : X.CmAesKey <- X.CmAes.key(key) 62 CC.Ccm.encrypt(~X.CmAesKey, ~X.CmAes.encrypt, k, m, nonce, aad, p) 63 64 def CmAes.ccm_decrypt(key: B.Octets, +m: Nat, nonce: B.Octets, aad: B.Octets, c: B.Octets) -> Result<&2, &2, M.CmError, B.Octets>: 65 do Result<&2, &2, M.CmError, B.Octets>: 66 k : X.CmAesKey <- X.CmAes.key(key) 67 CC.Ccm.decrypt(~X.CmAesKey, ~X.CmAes.encrypt, k, m, nonce, aad, c) 68 69 # AES-CMAC (RFC 4493 with a 16-byte key): the 16-byte MAC 70 def CmAes.cmac(key: B.Octets, m: B.Octets) -> Result<&2, &2, M.CmError, B.Octets>: 71 do Result<&2, &2, M.CmError, B.Octets>: 72 k : X.CmAesKey <- X.CmAes.key(key) 73 return CM.Cmac.mac(~X.CmAesKey, ~X.CmAes.encrypt, k, m)