diff --git a/Ascon.cry b/Ascon.cry index 103b30b..21c1244 100644 --- a/Ascon.cry +++ b/Ascon.cry @@ -25,10 +25,10 @@ private /** Parse function. * * The parse(𝑋, π‘Ÿ) function parses the input bitstring 𝑋 into a sequence - * of blocks 𝑋₀, 𝑋₁, …, 𝑋̃ℓ, where 𝓁 ← ⌊|𝑋|/π‘ŸβŒ‹ (i.e., 𝑋 ← 𝑋₀ βˆ₯ 𝑋₁ βˆ₯ … βˆ₯ 𝑋̃ℓ). + * 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). + * 0 ≀ |𝑋͠ℓ| ≀ π‘Ÿ βˆ’ 1 (see Algorithm 1). When |𝑋| mod π‘Ÿ = 0, the final + * block is empty (i.e., |𝑋͠ℓ| = 0). */ parse : {r, m} (fin m, fin r, r >= 1) => [m] -> ([m / r][r], [m % r]) parse (M # Ml) = (split M, Ml) @@ -36,7 +36,7 @@ private /** 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 + * by the 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. @@ -201,9 +201,18 @@ AEAD128_encrypt K N A P = C # T [K0, K1] = bitsToWords K [N0, N1] = bitsToWords N + // 𝑆 ← 𝐼𝑉 β€– 𝐾 β€– 𝑁 (15) + // 𝑆 ← Ascon-p[12](𝑆) (16) + // 𝑆 ← 𝑆 βŠ• (0¹⁹² β€– K) (17) S0 = Ascon_p`{12} [AEAD128_IV, K0, K1, N0, N1] ^ [0, 0, 0, K0, K1] + SA = AddAD S0 A + // 𝑃₀, 𝑃₁, …, 𝑃ₙ₋₁, 𝑃͠ₙ ← parse(𝑃,128) (23) + // For each 𝑃ᡒ, 0 ≀ 𝑖 ≀ π‘›βˆ’1 + // 𝑆[0:127] ← 𝑆[0:127] βŠ• 𝑃ᡒ (24) + // 𝐢ᡒ ← 𝑆[0:127] (25) + // 𝑆 ← Ascon-p[8](𝑆) (26) SCs = [XorBlock s p | s <- [SA] # map Ascon_p`{8} SCs | p <- toBlocks P] C = take (join (map ExtractC SCs)) @@ -292,14 +301,28 @@ private /** Absorb all of the associated data into the permutation state. */ AddAD : {a} (fin a) => State -> [a] -> State AddAD S A - | a == 0 => DomainSep S + + /* If the AD is non-empty (i.e., |𝐴| > 0): + * 𝐴₀, 𝐴₁, …, π΄β‚˜β‚‹β‚, π΄Ν β‚˜ ← parse(𝐴,128) (18) + * π΄β‚˜ ← pad(π΄Ν β‚˜,128) (19) + */ | a > 0 => DomainSep (foldl AbsorbADBlock S (toBlocks A)) - /** Absorb a single block of associated data into the permutation state. */ - AbsorbADBlock : State -> [128] -> State - AbsorbADBlock S X = Ascon_p`{8} (XorBlock S X) + /* If the AD is empty (i.e., |𝐴| = 0): Only the final step + * described in (22) is applied. + */ + | a == 0 => DomainSep S - /** Toggle the domain separation bit indicating end of associated data. */ + /* Absorb a block in input into the state. + * 𝑆[0:127] ← 𝑆[0:127] βŠ• 𝐴ᡒ (20) + * 𝑆 ← Ascon-p[8](𝑆) (21) + **/ + AbsorbADBlock : State -> [128] -> State + AbsorbADBlock S Ai = Ascon_p`{8} (XorBlock S Ai) + + /** Toggle the domain separation bit indicating end of associated data. + * 𝑆 ← 𝑆 βŠ• (0³¹⁹ β€– 1) (22) + */ DomainSep : State -> State DomainSep [s0, s1, s2, s3, s4] = [s0, s1, s2, s3, s4 ^ 0b1#0]