/** Implementation of Ascon-Based Lightweight Cryptography Reference: Meltem SΓΆnmez Turan, Kerry A. McKay, Donghoon Chang, Jinkeon Kang, John Kelsey (2025) Ascon-Based Lightweight Cryptography Standards for Constrained Devices. (National Institute of Standards and Technology, Gaithersburg, MD), NIST Special Publication (SP) NIST SP 800-232. https://doi.org/10.6028/NIST.SP.800-232 */ module Ascon where // 2.1. Auxiliary Functions /// Parse function. /// /// The parse(𝑋, π‘Ÿ) function parses the input bitstring 𝑋 into a sequence /// of blocks 𝑋₀, 𝑋₁, …, 𝑋̃ℓ, where 𝓁 ← ⌊|𝑋|/π‘ŸβŒ‹ (i.e., 𝑋 ← 𝑋₀ βˆ₯ 𝑋₁ βˆ₯ … βˆ₯ 𝑋̃ℓ). /// The 𝑋ᡒ blocks for 0 ≀ i ≀ 𝓁 βˆ’ 1 each have a bit length π‘Ÿ, whereas /// 0 ≀ |𝑋̃ℓ| ≀ π‘Ÿ βˆ’ 1 (see Algorithm 1). When |𝑋| mod π‘Ÿ = 0, the final /// block is empty (i.e., |𝑋̃ℓ| = 0). parse : {r, n} (fin n, fin r, r >= 1) => [n] -> ([n/r][r], [n%r]) parse (M_ # Ml) = (split M_, Ml) /// Padding rule. /// /// The function pad(𝑋, π‘Ÿ) appends the bit 1 to the bitstring 𝑋, followed /// bythe bitstring 0Κ², where 𝑗 is equal to (βˆ’|𝑋|βˆ’1) mod π‘Ÿ. The length of /// the output bitstring is a multiple of π‘Ÿ (see Algorithm 2). For examples /// of padding when representing the data as 64-bit unsigned integers, see /// Appendix A.2. pad : {r, n} (n < r, fin r) => [n] -> [r] pad M = M # 0b1 # 0 /// Combination of parse and pad that splits a bitstring into a sequence /// of integers using Cryptol's native big-endian representation. toBlocks : {r, n} (r >= 1, fin r, fin n) => [n] -> [n / r + 1][r] toBlocks M = map reverse (M1 # [pad M2]) where (M1, M2) = parse M // 3. Ascon Permutations type constraint ValidRnd rnd = rnd <= 16 /// Core permutation function parameterized by a round count. Ascon_p : {rnd} (ValidRnd rnd) => State -> State Ascon_p S = foldl p`{rnd} S (drop`{back=rnd} Const) /// Single round of the Ascon-p permutation. p : {rnd} (ValidRnd rnd) => State -> [64] -> State p S ci = pL (pS (pC S ci)) // 3.1. Internal State /// The permutations operate on the 320-bit state 𝑆, which is represented /// as five 64-bit words denoted as 𝑆ᡒ for 0 ≀ 𝑖 ≀ 4: /// /// 𝑆 = 𝑆₀ β€– 𝑆₁ β€– 𝑆₂ β€– 𝑆₃ β€– 𝑆₄ /// /// Let 𝑠ᡒⱼ represent the 𝑗th bit of 𝑆ᡒ, 0 ≀ 𝑗 < 64. In this specification /// of the Ascon permutation, each state word represents a 64-bit unsigned /// integer, where the least significant bit is the rightmost bit. Details /// on other representations of the state can be found in Appendix A. type State = [5][64] // 3.2. Constant-Addition Layer pC /// The constant cα΅’ of round 𝑖 of the Ascon permutation Ascon-p[π‘Ÿπ‘›π‘‘] /// (instantiated with π‘Ÿπ‘›π‘‘ rounds) for π‘Ÿπ‘›π‘‘ ≀ 16 and 0 ≀ 𝑖 < π‘Ÿπ‘›π‘‘ βˆ’ 1 /// is defined as /// /// cα΅’ = const[16 βˆ’ π‘Ÿπ‘›π‘‘ + 𝑖] /// /// where const[0],…,const[15] are defined in Table 5. The constant-addition /// layer 𝑃𝑐 adds a 64-bit round constant cα΅’ to 𝑆₂ in round 𝑖, for i β‰₯ 0, /// /// 𝑆₂ = 𝑆₂ βŠ• cα΅’. pC : State -> [64] -> State pC [S0, S1, S2, S3, S4] ci = [S0, S1, S2 ^ ci, S3, S4] /// Table 5. The constants constα΅’ to derive round constants of the Ascon /// permutations Const : [16][64] Const = [ 0x000000000000003c , 0x000000000000002d , 0x000000000000001e , 0x000000000000000f , 0x00000000000000f0 , 0x00000000000000e1 , 0x00000000000000d2 , 0x00000000000000c3 , 0x00000000000000b4 , 0x00000000000000a5 , 0x0000000000000096 , 0x0000000000000087 , 0x0000000000000078 , 0x0000000000000069 , 0x000000000000005a , 0x000000000000004b ] // 3.3. Substitution Layer pS pS : State -> State pS S = transpose (map SBox (transpose S)) SBox : [5] -> [5] SBox i = SBoxTable@i /// Table 6. SBoxTable : [32][5] SBoxTable = map drop [ 0x04, 0x0b, 0x1f, 0x14, 0x1a, 0x15, 0x09, 0x02 , 0x1b, 0x05, 0x08, 0x12, 0x1d, 0x03, 0x06, 0x1c , 0x1e, 0x13, 0x07, 0x0e, 0x00, 0x0d, 0x11, 0x18 , 0x10, 0x0c, 0x01, 0x19, 0x16, 0x0a, 0x0f, 0x17 ] property SBoxCorrect x0 x1 x2 x3 x4 = [y0, y1, y2, y3, y4] == SBox [x0, x1, x2, x3, x4] where y0 = x4&&x1 ^ x3 ^ x2&&x1 ^ x2 ^ x1&&x0 ^ x1 ^ x0 y1 = x4 ^ x3&&x2 ^ x3&&x1 ^ x3 ^ x2&&x1 ^ x2 ^ x1 ^ x0 y2 = x4&&x3 ^ x4 ^ x2 ^ x1 ^ 1 y3 = x4&&x0 ^ x4 ^ x3&&x0 ^ x3 ^ x2 ^ x1 ^ x0 y4 = x4&&x1 ^ x4 ^ x3 ^ x1&&x0 ^ x1 // 3.4. Linear Diffusion Layer pL pL : State -> State pL [S0, S1, S2, S3, S4] = [ sigma S0 19 28 , sigma S1 61 39 , sigma S2 1 6 , sigma S3 10 17 , sigma S4 7 41 ] where sigma : [64] -> [6] -> [6] -> [64] sigma x i j = x ^ (x >>> i) ^ (x >>> j) wordsToBits : {w,n} (fin w) => [n][w] -> [w*n] wordsToBits M = join (map reverse M) bitsToWords : {w,n} (fin w) => [w*n] -> [n][w] bitsToWords M = map reverse (split M)