diff --git a/Ascon.cry b/Ascon.cry index 5a1d609..fbdd44e 100644 --- a/Ascon.cry +++ b/Ascon.cry @@ -48,11 +48,11 @@ 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) +Ascon_p S = foldl round 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)) +round : State -> [64] -> State +round S ci = pL (pS (pC S ci)) // 3.1. Internal State @@ -149,3 +149,151 @@ wordsToBits M = join (map reverse M) bitsToWords : {w,n} (fin w) => [w*n] -> [n][w] bitsToWords M = map reverse (split M) + +// 4. Authenticated Encryption Schema: Ascon-AEAD128 + +/// Encryption using Ascon-AEAD128 +/// +/// Parameters: +/// - Key +/// - Nonce +/// - Additional data +/// - Plaintext +/// +/// Returns: +/// - Authenticated ciphertext +AEAD128_encrypt : {a, p} (fin a, fin p) => [128] -> [128] -> [a] -> [p] -> [p + 128] +AEAD128_encrypt K N A P = C # T + where + // key and nonce as two 64-bit integers + [K0,K1] = bitsToWords K + [N0,N1] = bitsToWords N + + S0 = Ascon_p`{12} [Ascon_AEAD128_IV, K0, K1, N0, N1] ^ [0, 0, 0, K0, K1] + SA = AddAD S0 A + + SCs = [XorBlock s p | s <- [SA] # map Ascon_p`{8} SCs | p <- toBlocks P] + + C = take (join (map ExtractC SCs)) + + ST = Ascon_p`{12} (last SCs ^ [0, 0, K0, K1, 0]) + T = ExtractT ST ^ K + +/// Decryption using Ascon-AEAD128 +/// +/// Parameters: +/// - Key +/// - Nonce +/// - Additional data +/// - Ciphertext +/// +/// Returns: +/// - Some plaintext on success +/// - None when message authentication fails +AEAD128_decrypt : {a, p} (fin a, fin p) => [128] -> [128] -> [a] -> [p + 128] -> Option [p] +AEAD128_decrypt K N A (Cs_ # Cl # T) = + if T == T' then Some P else trace "P" P None + where + // key and nonce as two 64-bit integers + [K0,K1] = bitsToWords K + [N0,N1] = bitsToWords N + + S0 = Ascon_p`{12} [Ascon_AEAD128_IV, K0, K1, N0, N1] ^ [0, 0, 0, K0, K1] + SA = AddAD S0 A + + Cs = split`{p/128, 128} Cs_ + + SCs # [SCl] = [SA] # [Ascon_p`{8} (AssignC s c) | s <- SCs | c <- Cs] + + Plmask # SCl' = ExtractC SCl + Sl' = AssignC SCl (Cl # (0b1#0 ^ SCl')) + + Ps = zipWith (\x y -> ExtractC x ^ y) SCs Cs + Pl = Plmask ^ Cl + P = join Ps # Pl + + ST = Ascon_p`{12} (Sl' ^ [0, 0, K0, K1, 0]) + T' = ExtractT ST ^ K + +AEAD128_encrypt_bytes : {a, p} (fin a, fin p) => [16][8] -> [16][8] -> [a][8] -> [p][8] -> [p + 16][8] +AEAD128_encrypt_bytes K N A P = + bitsToWords (AEAD128_encrypt (wordsToBits K) (wordsToBits N) (wordsToBits A) (wordsToBits P)) + +AEAD128_decrypt_bytes : {a, p} (fin a, fin p) => [16][8] -> [16][8] -> [a][8] -> [p + 16][8] -> Option ([p][8]) +AEAD128_decrypt_bytes K N A C = + case AEAD128_decrypt (wordsToBits K) (wordsToBits N) (wordsToBits A) (wordsToBits C) of + None -> None + Some p -> Some (bitsToWords p) + +AddAD : {a} (fin a) => State -> [a] -> State +AddAD S A + | a == 0 => DomainSep S + | a > 0 => DomainSep (foldl AbsorbBlock128 S (toBlocks A)) + +DomainSep : State -> State +DomainSep [s0, s1, s2, s3, s4] = [s0, s1, s2, s3, s4 ^ 0b1 # 0] + +AbsorbBlock128 : State -> [128] -> State +AbsorbBlock128 S X = Ascon_p`{8} (XorBlock S X) + +XorBlock : State -> [128] -> State +XorBlock [s0, s1, s2, s3, s4] (xhi # xlo) = [s0 ^ xlo, s1 ^ xhi, s2, s3, s4] + +ExtractC : State -> [128] +ExtractC [s0, s1, _, _, _] = wordsToBits [s0, s1] + +AssignC : State -> [128] -> State +AssignC [_, _, s2, s3, s4] C = bitsToWords C # [s2, s3, s4] + +ExtractT : State -> [128] +ExtractT [_, _, _, s3, s4] = wordsToBits [s3, s4] + +Ascon_AEAD128_IV : [64] +Ascon_AEAD128_IV = 0x00001000808c0001 + +// 5. Hash and eXtendable-Output Functions (XOFs) + +hashBlocks : {n} (fin n) => [64] -> [n][64] -> [inf] +hashBlocks IV Ms = wordsToBits [head S | S <- iterate Ascon_p`{12} Sn] + where + S0 = Ascon_p`{12} [IV, 0, 0, 0, 0] + Sn = foldl AbsorbBlock64 S0 Ms + +AbsorbBlock64 : State -> [64] -> State +AbsorbBlock64 [s0, s1, s2, s3, s4] X = Ascon_p`{12} [X ^ s0, s1, s2, s3, s4] + +/// 5.1. Specification of Ascon-Hash256 +Hash256 : {n} (fin n) => [n] -> [256] +Hash256 M = take (hashBlocks Hash256_IV (toBlocks M)) + +Hash256_bytes : {n} (fin n) => [n][8] -> [32][8] +Hash256_bytes M = bitsToWords (Hash256 (wordsToBits M)) + +Hash256_IV : [64] +Hash256_IV = 0x0000080100cc0002 + +// 5.2. Specification of Ascon-XOF128 + +XOF128 : {r, n} (fin n, fin r) => [n] -> [r] +XOF128 M = take (hashBlocks XOF128_IV (toBlocks M)) + +XOF128_bytes : {r, n} (fin n, fin r) => [n][8] -> [r][8] +XOF128_bytes M = bitsToWords (XOF128 (wordsToBits M)) + +XOF128_IV : [64] +XOF128_IV = 0x0000080000cc0003 + +// 5.3. Specification of Ascon-CXOF128 + +CXOF128 : {r, c, n} (fin n, fin r, fin c, 64 >= width c) => [c] -> [n] -> [r] +CXOF128 Z M = take (hashBlocks CXOF128_IV Ms) + where + Ms = [`c] + # toBlocks Z + # toBlocks M + +CXOF128_bytes : {r, z, n} (fin n, fin r, 61 >= width z) => [z][8] -> [n][8] -> [r][8] +CXOF128_bytes Z M = bitsToWords (CXOF128 (wordsToBits Z) (wordsToBits M)) + +CXOF128_IV : [64] +CXOF128_IV = 0x0000080000cc0004 diff --git a/AsconCipher.cry b/AsconCipher.cry deleted file mode 100644 index 2dfafaa..0000000 --- a/AsconCipher.cry +++ /dev/null @@ -1,51 +0,0 @@ -module AsconCipher where - -import Ascon - -// 4. Authenticated Encryption Schema: Ascon-AEAD128 - -Ascon_AEAD128 : {a, p} (fin a, fin p) => [128] -> [128] -> [a] -> [p] -> [p + 128] -Ascon_AEAD128 K N A P = C # T - where - // key and nonce as two 64-bit integers - [K0,K1] = bitsToWords K - [N0,N1] = bitsToWords N - - S0 = Ascon_p`{12} [Ascon_AEAD128_IV, K0, K1, N0, N1] - ^ [0, 0, 0, K0, K1] - - SA = AddAD S0 A - - SCs = zipWith XorBlock (take ([SA] # map Ascon_p`{8} SCs)) (toBlocks P) - - C = take (join (map ExtractC SCs)) - - ST = Ascon_p`{12} (last SCs ^ [0, 0, K0, K1, 0]) - T = ExtractT ST ^ K - -Ascon_AEAD128_bytes : {a, p} (fin a, fin p) => [16][8] -> [16][8] -> [a][8] -> [p][8] -> [p + 16][8] -Ascon_AEAD128_bytes K N A P = - bitsToWords (Ascon_AEAD128 (wordsToBits K) (wordsToBits N) (wordsToBits A) (wordsToBits P)) - -AddAD : {a} (fin a) => State -> [a] -> State -AddAD S A - | a == 0 => DomainSep S - | a > 0 => DomainSep (foldl AbsorbBlock S (toBlocks A)) - -XorBlock : State -> [128] -> State -XorBlock [s0, s1, s2, s3, s4] (xhi # xlo) = [s0 ^ xlo, s1 ^ xhi, s2, s3, s4] - -AbsorbBlock : State -> [128] -> State -AbsorbBlock S X = Ascon_p`{8} (XorBlock S X) - -DomainSep : State -> State -DomainSep [s0, s1, s2, s3, s4] = [s0, s1, s2, s3, s4 ^ 0b1 # 0] - -ExtractC : State -> [128] -ExtractC [s0, s1, _, _, _] = wordsToBits [s0, s1] - -ExtractT : State -> [128] -ExtractT [_, _, _, s3, s4] = wordsToBits [s3, s4] - -Ascon_AEAD128_IV : [64] -Ascon_AEAD128_IV = 0x00001000808c0001 diff --git a/AsconHash.cry b/AsconHash.cry deleted file mode 100644 index 23698d6..0000000 --- a/AsconHash.cry +++ /dev/null @@ -1,56 +0,0 @@ -module AsconHash where - -import Ascon - -// 5. Hash and eXtendable-Output Functions (XOFs) - -Ascon_Digest : {n} (fin n) => [64] -> [n][64] -> [inf] -Ascon_Digest IV Ms = wordsToBits [head S | S <- iterate Ascon_p`{12} Sn] - where - S0 = Ascon_p`{12} [IV, 0, 0, 0, 0] - Sn = foldl AbsorbBlock S0 Ms - -AbsorbBlock : State -> [64] -> State -AbsorbBlock [s0, s1, s2, s3, s4] X = Ascon_p`{12} [X ^ s0, s1, s2, s3, s4] - -/// 5.1. Specification of Ascon-Hash256 -Ascon_Hash256 : {n} (fin n) => [n] -> [256] -Ascon_Hash256 M = take (Ascon_Digest Ascon_Hash256_IV (toBlocks M)) - -Ascon_Hash256_IV : [64] -Ascon_Hash256_IV = 0x0000080100cc0002 - -Ascon_Hash256_bytes : {n} (fin n) => [n][8] -> [32][8] -Ascon_Hash256_bytes M = bitsToWords (Ascon_Hash256 (wordsToBits M)) - -property - initial_value_works = - Ascon_p`{12} ([Ascon_Hash256_IV] # zero) - == - [0x9b1e5494e934d681, 0x4bc3a01e333751d2, 0xae65396c6b34b81a, 0x3c7fd4a4d56a4db3, 0x1a5c464906c5976d] - -// 5.2. Specification of Ascon-XOF128 - -Ascon_XOF128 : {r, n} (fin n, fin r) => [n] -> [r] -Ascon_XOF128 M = take (Ascon_Digest Ascon_XOF128_IV (toBlocks M)) - -Ascon_XOF128_IV : [64] -Ascon_XOF128_IV = 0x0000080000cc0003 - -Ascon_XOF128_bytes : {r, n} (fin n, fin r) => [n][8] -> [r][8] -Ascon_XOF128_bytes M = bitsToWords (Ascon_XOF128 (wordsToBits M)) - -// 5.3. Specification of Ascon-CXOF128 - -Ascon_CXOF128 : {r, c, n} (fin n, fin r, fin c, 64 >= width c) => [c] -> [n] -> [r] -Ascon_CXOF128 Z M = take (Ascon_Digest Ascon_CXOF128_IV Ms) - where - Ms = [`c] - # toBlocks Z - # toBlocks M - -Ascon_CXOF128_bytes : {r, z, n} (fin n, fin r, 61 >= width z) => [z][8] -> [n][8] -> [r][8] -Ascon_CXOF128_bytes Z M = bitsToWords (Ascon_CXOF128 (wordsToBits Z) (wordsToBits M)) - -Ascon_CXOF128_IV : [64] -Ascon_CXOF128_IV = 0x0000080000cc0004 diff --git a/TestAsconAEAD128.cry b/TestAsconAEAD128.cry index 68cc5bc..60253d7 100644 --- a/TestAsconAEAD128.cry +++ b/TestAsconAEAD128.cry @@ -1,11 +1,14 @@ module TestAsconAEAD128 where import Ascon -import AsconCipher testcase : {n, m} (fin m, fin n) => [128] -> [128] -> [8 * m] -> [8 * n] -> [8 * (m + 16)] -> Bit testcase K N P A C = - Ascon_AEAD128_bytes (split K) (split N) (split A) (split P) == split C + AEAD128_encrypt_bytes (split K) (split N) (split A) (split P) == split C + /\ + case AEAD128_decrypt_bytes (split K) (split N) (split A) (split C) of + None -> False + Some p -> p == split P property test1 = testcase 0x000102030405060708090A0B0C0D0E0F 0x101112131415161718191A1B1C1D1E1F [] 0x 0x4F9C278211BEC9316BF68F46EE8B2EC6 diff --git a/TestAsconCXOF128.cry b/TestAsconCXOF128.cry index 2cda2ed..3b256be 100644 --- a/TestAsconCXOF128.cry +++ b/TestAsconCXOF128.cry @@ -1,9 +1,9 @@ module TestAsconCXOF128 where -import AsconHash +import Ascon testcase : {r, z, n} (fin n, fin r, 61 >= width z) => [8*n] -> [8*z] -> [8*r] -> Bool -testcase M Z D = Ascon_CXOF128_bytes (split Z) (split M) == split D +testcase M Z D = CXOF128_bytes (split Z) (split M) == split D property test1 = testcase [] [] 0x4F50159EF70BB3DAD8807E034EAEBD44C4FA2CBBC8CF1F05511AB66CDCC529905CA12083FC186AD899B270B1473DC5F7EC88D1052082DCDFE69FB75D269E7B74 diff --git a/TestAsconHash256.cry b/TestAsconHash256.cry index cff9f46..28eb790 100644 --- a/TestAsconHash256.cry +++ b/TestAsconHash256.cry @@ -1,9 +1,9 @@ module TestAsconHash256 where -import AsconHash +import Ascon testcase : {n} (fin n) => [8*n] -> [256] -> Bool -testcase M D = Ascon_Hash256_bytes (split M) == split D +testcase M D = Hash256_bytes (split M) == split D property test1 = testcase [] 0x0B3BE5850F2F6B98CAF29F8FDEA89B64A1FA70AA249B8F839BD53BAA304D92B2 diff --git a/TestAsconXOF128.cry b/TestAsconXOF128.cry index 25aa5a0..7899535 100644 --- a/TestAsconXOF128.cry +++ b/TestAsconXOF128.cry @@ -1,9 +1,9 @@ module TestAsconXOF128 where -import AsconHash +import Ascon testcase : {r, n} (fin n, fin r) => [8*n] -> [8*r] -> Bool -testcase M D = Ascon_XOF128_bytes (split M) == split D +testcase M D = XOF128_bytes (split M) == split D property test1 = testcase [] 0x473D5E6164F58B39DFD84AACDB8AE42EC2D91FED33388EE0D960D9B3993295C6AD77855A5D3B13FE6AD9E6098988373AF7D0956D05A8F1665D2C67D1A3AD10FF