mirror of
https://github.com/vlang/v.git
synced 2025-09-16 16:02:29 +03:00
x.crypto.ascon: optimize ascon_pnr permutation routine
This commit is contained in:
parent
f073169177
commit
13f1fe50ab
7 changed files with 129 additions and 331 deletions
|
@ -1,15 +1,17 @@
|
|||
# ascon
|
||||
|
||||
`ascon` is a implementation of Ascon-Based Cryptography module implemented in pure V language.
|
||||
`ascon` is an implementation of Ascon-Based Cryptography module implemented in pure V language.
|
||||
This module was mostly based on NIST Special Publication of 800 NIST SP 800-232 document.
|
||||
Its describes an Ascon-Based Lightweight Cryptography Standards for Constrained Devices
|
||||
thats provides Authenticated Encryption, Hash, and Extendable Output Functions.
|
||||
See the [NIST.SP.800-232 Standard](https://doi.org/10.6028/NIST.SP.800-232) for more detail.
|
||||
|
||||
This module does not fully implements all the features availables on the document.
|
||||
This module mostly implements all the features availables on the document.
|
||||
Its currently implements:
|
||||
- `Ascon-Hash256`, Ascon-based hashing implementation that produces 256-bits output.
|
||||
- `Ascon-XOF128`, Ascon-based eXtendible Output Function (XOF) where the output size of
|
||||
- `Ascon-XOF128`, Ascon-based eXtendable Output Function (XOF) where the output size of
|
||||
the hash of the message can be selected by the user.
|
||||
- `Ascon-CXOF128`, a customized XOF that allows users to specify a customization
|
||||
string and choose the output size of the message hash.
|
||||
- `Ascon-AEAD128`, an Authenticated Encryption with Additional Data (AEAD) Scheme based
|
||||
on Ascon-family crypto.
|
||||
|
|
|
@ -181,7 +181,7 @@ pub fn (mut c Aead128) encrypt(msg []u8, nonce []u8, ad []u8) ![]u8 {
|
|||
c.State.e4 = n1
|
||||
|
||||
// Update state by permutation
|
||||
ascon_pnr(mut c.State, 12)
|
||||
ascon_pnr(mut c.State, ascon_prnd_12)
|
||||
// XOR-ing with the cipher's key
|
||||
c.State.e3 ^= c.key[0]
|
||||
c.State.e4 ^= c.key[1]
|
||||
|
@ -229,7 +229,7 @@ pub fn (mut c Aead128) decrypt(ciphertext []u8, nonce []u8, ad []u8) ![]u8 {
|
|||
c.State.e4 = n1
|
||||
|
||||
// scrambled with permutation routine
|
||||
ascon_pnr(mut c.State, 12)
|
||||
ascon_pnr(mut c.State, ascon_prnd_12)
|
||||
// xor-ing with the cipher's key
|
||||
c.State.e3 ^= c.key[0]
|
||||
c.State.e4 ^= c.key[1]
|
||||
|
@ -288,7 +288,7 @@ fn aead128_init(mut s State, key []u8, nonce []u8) (u64, u64) {
|
|||
s.e4 = n1
|
||||
|
||||
// updates State using the permutation 𝐴𝑠𝑐𝑜𝑛-𝑝[12], S ← 𝐴𝑠𝑐𝑜𝑛-𝑝[12](S)
|
||||
ascon_pnr(mut s, 12)
|
||||
ascon_pnr(mut s, ascon_prnd_12)
|
||||
|
||||
// Then XORing the secret key 𝐾 into the last 128 bits of internal state:
|
||||
// S ← S ⊕ (0¹⁹² ∥ 𝐾).
|
||||
|
@ -312,7 +312,7 @@ fn aead128_process_ad(mut s State, ad []u8) {
|
|||
s.e1 ^= binary.little_endian_u64(block[8..16])
|
||||
|
||||
// Apply permutation 𝐴𝑠𝑐𝑜𝑛-𝑝[8] to the state
|
||||
ascon_pnr(mut s, 8)
|
||||
ascon_pnr(mut s, ascon_prnd_8)
|
||||
// Updates index
|
||||
ad_length -= aead128_block_size
|
||||
ad_idx += aead128_block_size
|
||||
|
@ -339,7 +339,7 @@ fn aead128_process_ad(mut s State, ad []u8) {
|
|||
}
|
||||
}
|
||||
// Apply permutation 𝐴𝑠𝑐𝑜𝑛-𝑝[8] to the state
|
||||
ascon_pnr(mut s, 8)
|
||||
ascon_pnr(mut s, ascon_prnd_8)
|
||||
}
|
||||
// The final step of processing associated data is to update the state
|
||||
// with a constant that provides domain separation.
|
||||
|
@ -361,7 +361,7 @@ fn aead128_process_msg(mut out []u8, mut s State, msg []u8) int {
|
|||
binary.little_endian_put_u64(mut out[pos..pos + 8], s.e0)
|
||||
binary.little_endian_put_u64(mut out[pos + 8..], s.e1)
|
||||
// apply permutation
|
||||
ascon_pnr(mut s, 8)
|
||||
ascon_pnr(mut s, ascon_prnd_8)
|
||||
|
||||
// updates index
|
||||
mlen -= aead128_block_size
|
||||
|
@ -413,7 +413,7 @@ fn aead128_partial_dec(mut out []u8, mut s State, cmsg []u8) {
|
|||
s.e0 = c0
|
||||
s.e1 = c1
|
||||
|
||||
ascon_pnr(mut s, 8)
|
||||
ascon_pnr(mut s, ascon_prnd_8)
|
||||
// updates index
|
||||
pos += aead128_block_size
|
||||
cmsg_len -= aead128_block_size
|
||||
|
@ -448,7 +448,7 @@ fn aead128_finalize(mut s State, k0 u64, k1 u64) {
|
|||
s.e2 ^= k0
|
||||
s.e3 ^= k1
|
||||
// then updated using the permutation 𝐴𝑠𝑐𝑜𝑛-𝑝[12]
|
||||
ascon_pnr(mut s, 12)
|
||||
ascon_pnr(mut s, ascon_prnd_12)
|
||||
|
||||
// Finally, the tag 𝑇 is generated by XORing the key with the last 128 bits of the state:
|
||||
// 𝑇 ← 𝑆[192∶319] ⊕ 𝐾.
|
||||
|
|
|
@ -2,246 +2,53 @@
|
|||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
//
|
||||
import encoding.hex
|
||||
import x.crypto.ascon
|
||||
module ascon
|
||||
|
||||
// This test materials was taken and adapted into v from references implementation of Ascon-aead128
|
||||
// especially for the known answer test data, but, its not all fully-taken, just randomly choosen item.
|
||||
// See at https://github.com/ascon/ascon-c/blob/main/crypto_aead/asconaead128/LWC_AEAD_KAT_128_128.txt
|
||||
struct KatTest {
|
||||
cnt int
|
||||
key string
|
||||
nonce string
|
||||
pt string
|
||||
ad string
|
||||
ct string
|
||||
}
|
||||
|
||||
// testing for Ascon-AEAD128 encryption and decryption.
|
||||
fn test_ascon_aead128_enc_dec() ! {
|
||||
for item in aead128_kat_tests_data {
|
||||
key := hex.decode(item.key)!
|
||||
nonce := hex.decode(item.nonce)!
|
||||
pt := hex.decode(item.pt)!
|
||||
ad := hex.decode(item.ad)!
|
||||
ct := hex.decode(item.ct)!
|
||||
|
||||
out := ascon.encrypt(key, nonce, ad, pt)!
|
||||
assert out == ct
|
||||
|
||||
msg := ascon.decrypt(key, nonce, ad, ct)!
|
||||
assert msg == pt
|
||||
|
||||
// Work with object-based Cipher
|
||||
mut c := ascon.new_aead128(key)!
|
||||
// Lets encrypt the message
|
||||
exp_ct := c.encrypt(msg, nonce, ad)!
|
||||
assert exp_ct == ct
|
||||
// Lets decrypt it back
|
||||
exp_msg := c.decrypt(exp_ct, nonce, ad)!
|
||||
assert exp_msg == msg
|
||||
// This test mostly taken from https://docs.rs/ascon/latest/src/ascon/lib.rs.html
|
||||
fn test_ascon_round_p6() {
|
||||
mut s := State{
|
||||
e0: u64(0x0123456789abcdef)
|
||||
e1: 0xef0123456789abcd
|
||||
e2: 0xcdef0123456789ab
|
||||
e3: 0xabcdef0123456789
|
||||
e4: 0x89abcdef01234567
|
||||
}
|
||||
ascon_pnr(mut s, 6)
|
||||
assert s.e0 == u64(0xc27b505c635eb07f)
|
||||
assert s.e1 == u64(0xd388f5d2a72046fa)
|
||||
assert s.e2 == u64(0x9e415c204d7b15e7)
|
||||
assert s.e3 == u64(0xce0d71450fe44581)
|
||||
assert s.e4 == u64(0xdd7c5fef57befe48)
|
||||
}
|
||||
|
||||
const aead128_kat_tests_data = [
|
||||
KatTest{
|
||||
cnt: 1
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: ''
|
||||
ct: '4F9C278211BEC9316BF68F46EE8B2EC6'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 2
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '30'
|
||||
ct: 'CCCB674FE18A09A285D6AB11B35675C0'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 3
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '3031'
|
||||
ct: 'F65B191550C4DF9CFDD4460EBBCCA782'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 4
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '303132'
|
||||
ct: 'D127CF7D2CD4DA8930616C70B3619F42'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 5
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '30313233'
|
||||
ct: '000BA92E52B5ED6B97C9D913CC4C82DF'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 6
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '3031323334'
|
||||
ct: 'F7CC167F8FED3AEEA99B385B8622157E'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 7
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '303132333435'
|
||||
ct: '51CCBC46D56E93B89B1A3BFDAD0AA4D5'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 8
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '30313233343536'
|
||||
ct: 'B38ABBD573E071C6265EEAC4A68F65AB'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 9
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '3031323334353637'
|
||||
ct: '865C594093A9EDEE2C1D6384CCB4939E'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 10
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '303132333435363738'
|
||||
ct: '24F13284A0F90F906B18C7E4061C0896'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 27
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '303132333435363738393A3B3C3D3E3F40414243444546474849'
|
||||
ct: '4ED362C4407B1D3BE17A51465659DECF'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 28
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '303132333435363738393A3B3C3D3E3F404142434445464748494A'
|
||||
ct: 'A35C52EC6E7C78C051B23D03F691916F'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 29
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '303132333435363738393A3B3C3D3E3F404142434445464748494A4B'
|
||||
ct: 'F1C946363A21CCFFE291A289202FC64C'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 30
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C'
|
||||
ct: 'F1D453E933904578EEC3EA8E85550CE5'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 31
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D'
|
||||
ct: '82E22C860881C0485EC5F5E8CEA42CEA'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 32
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E'
|
||||
ct: 'C6306F1F154C78833984173360AAE874'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 33
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: ''
|
||||
ad: '303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F'
|
||||
ct: 'EFC3E78B02AD9A80A6F0548C5B0BB5BA'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 34
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: '20'
|
||||
ad: ''
|
||||
ct: 'E8DD576ABA1CD3E6FC704DE02AEDB79588'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 35
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: '20'
|
||||
ad: '30'
|
||||
ct: '962B8016836C75A7D86866588CA245D886'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 49
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: '20'
|
||||
ad: '303132333435363738393A3B3C3D3E'
|
||||
ct: '2089CB1DE2AE7D3E45BA7E9CC293548546'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 599
|
||||
key: '000102030405060708090a0b0c0d0e0f'
|
||||
nonce: '101112131415161718191a1b1c1d1e1f'
|
||||
pt: '202122232425262728292a2b2c2d2e2f3031'
|
||||
ad: '30313233'
|
||||
ct: 'cf5337fcb70ec45d179e0c3f51bb25ac967a2e7062ee9bd80da6c72e3a9b43aed9e0'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 600
|
||||
key: '000102030405060708090a0b0c0d0e0f'
|
||||
nonce: '101112131415161718191a1b1c1d1e1f'
|
||||
pt: '202122232425262728292a2b2c2d2e2f3031'
|
||||
ad: '3031323334'
|
||||
ct: '3076658cba8bf3bb6dccaa2f1255ee2e7db6f6493c7698f65f6860a7433a0f561e6c'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 601
|
||||
key: '000102030405060708090a0b0c0d0e0f'
|
||||
nonce: '101112131415161718191a1b1c1d1e1f'
|
||||
pt: '202122232425262728292a2b2c2d2e2f3031'
|
||||
ad: '303132333435'
|
||||
ct: '9310c6dd8e9cbc3e406c0ebfbea312435f2c6975faf3b6b2b17ef1ea2503c3d31ef5'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 602
|
||||
key: '000102030405060708090a0b0c0d0e0f'
|
||||
nonce: '101112131415161718191a1b1c1d1e1f'
|
||||
pt: '202122232425262728292a2b2c2d2e2f3031'
|
||||
ad: '30313233343536'
|
||||
ct: '6e024bd403f386eb9d1c56f459cfdcde1b2fdf8fd8be2faf0576c81e8d21c0dd8f8a'
|
||||
},
|
||||
KatTest{
|
||||
cnt: 603
|
||||
key: '000102030405060708090A0B0C0D0E0F'
|
||||
nonce: '101112131415161718191A1B1C1D1E1F'
|
||||
pt: '202122232425262728292A2B2C2D2E2F3031'
|
||||
ad: '3031323334353637'
|
||||
ct: 'fabe2cb1e7eba6329a30080f26e7dc72503dfc57f4de06a334b7ebadca03b44b73e9'
|
||||
},
|
||||
]
|
||||
fn test_ascon_round_p8() {
|
||||
mut s := State{
|
||||
e0: u64(0x0123456789abcdef)
|
||||
e1: 0xef0123456789abcd
|
||||
e2: 0xcdef0123456789ab
|
||||
e3: 0xabcdef0123456789
|
||||
e4: 0x89abcdef01234567
|
||||
}
|
||||
ascon_pnr(mut s, 8)
|
||||
assert s.e0 == u64(0x67ed228272f46eee)
|
||||
assert s.e1 == u64(0x80bc0b097aad7944)
|
||||
assert s.e2 == u64(0x2fa599382c6db215)
|
||||
assert s.e3 == u64(0x368133fae2f7667a)
|
||||
assert s.e4 == u64(0x28cefb195a7c651c)
|
||||
}
|
||||
|
||||
fn test_ascon_round_p12() {
|
||||
mut s := State{
|
||||
e0: u64(0x0123456789abcdef)
|
||||
e1: 0xef0123456789abcd
|
||||
e2: 0xcdef0123456789ab
|
||||
e3: 0xabcdef0123456789
|
||||
e4: 0x89abcdef01234567
|
||||
}
|
||||
ascon_pnr(mut s, 12)
|
||||
assert s.e0 == u64(0x206416dfc624bb14)
|
||||
assert s.e1 == u64(0x1b0c47a601058aab)
|
||||
assert s.e2 == u64(0x8934cfc93814cddd)
|
||||
assert s.e3 == u64(0xa9738d287a748e4b)
|
||||
assert s.e4 == u64(0xddd934f058afc7e1)
|
||||
}
|
||||
|
|
|
@ -10,6 +10,10 @@ module ascon
|
|||
// constants for up to 16 rounds to accommodate potential functionality extensions in the future.
|
||||
const max_nr_perm = 16
|
||||
|
||||
// The number how many round(s) for the Ascon permutation routine called.
|
||||
const ascon_prnd_8 = 8
|
||||
const ascon_prnd_12 = 12
|
||||
|
||||
// The constants to derive round constants of the Ascon permutations
|
||||
// See Table 5. of NIST SP 800-232 docs
|
||||
//
|
||||
|
@ -26,72 +30,74 @@ const max_nr_perm = 16
|
|||
const rnc = [u8(0x3c), 0x2d, 0x1e, 0x0f, 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, 0x78,
|
||||
0x69, 0x5a, 0x4b]
|
||||
|
||||
// ascon_pnr is ascon permutation routine with specified numbers of round nr, where 1 ≤ nr ≤ 16
|
||||
// ascon_pnr is the core of Ascon family permutation routine with specified numbers of round nr, where 1 ≤ nr ≤ 16
|
||||
// Its consist of iterations of the round function that is defined as the composition of three steps, ie:
|
||||
// 1. the constant-addition layer (see Sec. 3.2),
|
||||
// 2. the substitution layer (see Sec.3.3), and,
|
||||
// 3. the linear diffusion layer (Sec 3.4)
|
||||
@[direct_array_access]
|
||||
fn ascon_pnr(mut s State, nr int) {
|
||||
// We dont allow nr == 0
|
||||
if nr < 1 || nr > 16 {
|
||||
panic('Invalid round number')
|
||||
}
|
||||
// Ascon permutation routine
|
||||
for i := max_nr_perm - nr; i < max_nr_perm; i++ {
|
||||
ascon_perm(mut s, rnc[i])
|
||||
// 3.2 Constant-Addition Layer step
|
||||
//
|
||||
// The constant-addition layer adds a 64-bit round constant 𝑐𝑖
|
||||
// to 𝑆₂ in round 𝑖, for 𝑖 ≥ 0, ie, this is equivalent to applying
|
||||
// the constant to only the least significant eight bits of 𝑆₂
|
||||
s.e2 ^= rnc[i]
|
||||
|
||||
// 3.3. Substitution Layer
|
||||
// The substitution layer updates the state S with 64 parallel applications of the 5-bit
|
||||
// substitution box SBOX
|
||||
s.e0 ^= s.e4
|
||||
s.e4 ^= s.e3
|
||||
s.e2 ^= s.e1
|
||||
|
||||
t0 := s.e4 ^ (~s.e0 & s.e1)
|
||||
t1 := s.e0 ^ (~s.e1 & s.e2)
|
||||
t2 := s.e1 ^ (~s.e2 & s.e3)
|
||||
t3 := s.e2 ^ (~s.e3 & s.e4)
|
||||
t4 := s.e3 ^ (~s.e4 & s.e0)
|
||||
|
||||
s.e0 = t1
|
||||
s.e1 = t2
|
||||
s.e2 = t3
|
||||
s.e3 = t4
|
||||
s.e4 = t0
|
||||
|
||||
s.e1 ^= s.e0
|
||||
s.e0 ^= s.e4
|
||||
s.e3 ^= s.e2
|
||||
s.e2 = ~(s.e2)
|
||||
|
||||
// 3.4. Linear Diffusion Layer
|
||||
//
|
||||
// The linear diffusion layer provides diffusion within each 64-bit word S,
|
||||
// defined as :
|
||||
// Σ0(𝑆0) = 𝑆0 ⊕ (𝑆0 ⋙ 19) ⊕ (𝑆0 ⋙ 28)
|
||||
// Σ1(𝑆1) = 𝑆1 ⊕ (𝑆1 ⋙ 61) ⊕ (𝑆1 ⋙ 39)
|
||||
// Σ2(𝑆2) = 𝑆2 ⊕ (𝑆2 ⋙ 1) ⊕ (𝑆2 ⋙ 6)
|
||||
// Σ3(𝑆3) = 𝑆3 ⊕ (𝑆3 ⋙ 10) ⊕ (𝑆3 ⋙ 17)
|
||||
// Σ4(𝑆4) = 𝑆4 ⊕ (𝑆4 ⋙ 7) ⊕ (𝑆4 ⋙ 41)
|
||||
//
|
||||
// This diffusion layer, especially on the bits right rotation part is a most widely called
|
||||
// for Ascon permutation routine. So, even bits rotation almost efficient on most platform,
|
||||
// to reduce overhead on function call, we work on the raw bits right rotation here.
|
||||
// Bits right rotation, basically can be defined as:
|
||||
// ror = (x >> n) | x << (64 - n) for some u64 x
|
||||
//
|
||||
s.e0 ^= (s.e0 >> 19 | (s.e0 << (64 - 19))) ^ (s.e0 >> 28 | (s.e0 << (64 - 28)))
|
||||
s.e1 ^= (s.e1 >> 61 | (s.e1 << (64 - 61))) ^ (s.e1 >> 39 | (s.e1 << (64 - 39)))
|
||||
s.e2 ^= (s.e2 >> 1 | (s.e2 << (64 - 1))) ^ (s.e2 >> 6 | (s.e2 << (64 - 6))) //
|
||||
s.e3 ^= (s.e3 >> 10 | (s.e3 << (64 - 10))) ^ (s.e3 >> 17 | (s.e3 << (64 - 17)))
|
||||
s.e4 ^= (s.e4 >> 7 | (s.e4 << (64 - 7))) ^ (s.e4 >> 41 | (s.e4 << (64 - 41)))
|
||||
}
|
||||
}
|
||||
|
||||
// ascon_perm was the main permutations routine in Ascon-family crypto. Its consist of
|
||||
// iterations of the round function that is defined as the composition of three steps, ie:
|
||||
// 1. the constant-addition layer (see Sec. 3.2),
|
||||
// 2. the substitution layer (see Sec.3.3), and,
|
||||
// 3. the linear diffusion layer
|
||||
fn ascon_perm(mut s State, c u8) {
|
||||
// 3.2 Constant-Addition Layer step
|
||||
//
|
||||
// The constant-addition layer adds a 64-bit round constant 𝑐𝑖
|
||||
// to 𝑆₂ in round 𝑖, for 𝑖 ≥ 0, ie, this is equivalent to applying
|
||||
// the constant to only the least significant eight bits of 𝑆₂
|
||||
s.e2 ^= c
|
||||
|
||||
// 3.3. Substitution Layer
|
||||
// The substitution layer updates the state S with 64 parallel applications of the 5-bit
|
||||
// substitution box SBOX
|
||||
s.e0 ^= s.e4
|
||||
s.e4 ^= s.e3
|
||||
s.e2 ^= s.e1
|
||||
|
||||
t0 := s.e4 ^ (~s.e0 & s.e1)
|
||||
t1 := s.e0 ^ (~s.e1 & s.e2)
|
||||
t2 := s.e1 ^ (~s.e2 & s.e3)
|
||||
t3 := s.e2 ^ (~s.e3 & s.e4)
|
||||
t4 := s.e3 ^ (~s.e4 & s.e0)
|
||||
|
||||
s.e0 = t1
|
||||
s.e1 = t2
|
||||
s.e2 = t3
|
||||
s.e3 = t4
|
||||
s.e4 = t0
|
||||
|
||||
s.e1 ^= s.e0
|
||||
s.e0 ^= s.e4
|
||||
s.e3 ^= s.e2
|
||||
s.e2 = ~(s.e2)
|
||||
|
||||
// 3.4. Linear Diffusion Layer
|
||||
//
|
||||
// The linear diffusion layer provides diffusion within each 64-bit word S,
|
||||
// defined as :
|
||||
// Σ0(𝑆0) = 𝑆0 ⊕ (𝑆0 ⋙ 19) ⊕ (𝑆0 ⋙ 28)
|
||||
// Σ1(𝑆1) = 𝑆1 ⊕ (𝑆1 ⋙ 61) ⊕ (𝑆1 ⋙ 39)
|
||||
// Σ2(𝑆2) = 𝑆2 ⊕ (𝑆2 ⋙ 1) ⊕ (𝑆2 ⋙ 6)
|
||||
// Σ3(𝑆3) = 𝑆3 ⊕ (𝑆3 ⋙ 10) ⊕ (𝑆3 ⋙ 17)
|
||||
// Σ4(𝑆4) = 𝑆4 ⊕ (𝑆4 ⋙ 7) ⊕ (𝑆4 ⋙ 41)
|
||||
|
||||
s.e0 ^= ascon_rotate_right(s.e0, 19) ^ ascon_rotate_right(s.e0, 28)
|
||||
s.e1 ^= ascon_rotate_right(s.e1, 61) ^ ascon_rotate_right(s.e1, 39)
|
||||
s.e2 ^= ascon_rotate_right(s.e2, 1) ^ ascon_rotate_right(s.e2, 6)
|
||||
s.e3 ^= ascon_rotate_right(s.e3, 10) ^ ascon_rotate_right(s.e3, 17)
|
||||
s.e4 ^= ascon_rotate_right(s.e4, 7) ^ ascon_rotate_right(s.e4, 41)
|
||||
}
|
||||
|
||||
// State is structure represents Ascon state. Its operates on the 320-bit opaque,
|
||||
// which is represented as five of 64-bit words.
|
||||
@[noinit]
|
||||
|
|
|
@ -5,23 +5,6 @@
|
|||
module ascon
|
||||
|
||||
// This test mostly taken from https://docs.rs/ascon/latest/src/ascon/lib.rs.html
|
||||
fn test_ascon_round_one() {
|
||||
mut s := State{
|
||||
e0: u64(0x0123456789abcdef)
|
||||
e1: 0x23456789abcdef01
|
||||
e2: 0x456789abcdef0123
|
||||
e3: 0x6789abcdef012345
|
||||
e4: 0x89abcde01234567f
|
||||
}
|
||||
ascon_perm(mut s, 0x1f)
|
||||
|
||||
assert s.e0 == u64(0x3c1748c9be2892ce)
|
||||
assert s.e1 == u64(0x5eafb305cd26164f)
|
||||
assert s.e2 == u64(0xf9470254bb3a4213)
|
||||
assert s.e3 == u64(0xf0428daf0c5d3948)
|
||||
assert s.e4 == u64(0x281375af0b294899)
|
||||
}
|
||||
|
||||
fn test_ascon_round_p6() {
|
||||
mut s := State{
|
||||
e0: u64(0x0123456789abcdef)
|
||||
|
|
|
@ -33,7 +33,7 @@ fn (mut d Digest) finish() {
|
|||
d.State.e0 ^= load_bytes(d.buf[..d.length], d.length)
|
||||
|
||||
// Permutation step was done in squeezing-phase
|
||||
// ascon_pnr(mut d.State, 12)
|
||||
// ascon_pnr(mut d.State, ascon_prnd_12)
|
||||
|
||||
// zeroing Digest buffer
|
||||
d.length = 0
|
||||
|
@ -70,7 +70,7 @@ fn (mut d Digest) absorb(msg_ []u8) int {
|
|||
// If this d.buf length has reached block_size bytes, absorb it.
|
||||
if d.length == block_size {
|
||||
d.State.e0 ^= binary.little_endian_u64(d.buf)
|
||||
ascon_pnr(mut d.State, 12)
|
||||
ascon_pnr(mut d.State, ascon_prnd_12)
|
||||
// reset the internal buffer
|
||||
d.length = 0
|
||||
d.buf.reset()
|
||||
|
@ -87,7 +87,7 @@ fn (mut d Digest) absorb(msg_ []u8) int {
|
|||
for msg.len >= block_size {
|
||||
d.State.e0 ^= binary.little_endian_u64(msg[0..block_size])
|
||||
msg = msg[block_size..]
|
||||
ascon_pnr(mut d.State, 12)
|
||||
ascon_pnr(mut d.State, ascon_prnd_12)
|
||||
}
|
||||
// If there are partial block, just stored into buffer.
|
||||
if msg.len > 0 {
|
||||
|
@ -113,14 +113,14 @@ fn (mut d Digest) squeeze(mut dst []u8) int {
|
|||
}
|
||||
// The squeezing phase begins after msg is absorbed with an
|
||||
// permutation 𝐴𝑠𝑐𝑜𝑛-𝑝[12] to the state:
|
||||
ascon_pnr(mut d.State, 12)
|
||||
ascon_pnr(mut d.State, ascon_prnd_12)
|
||||
|
||||
mut pos := 0
|
||||
mut clen := dst.len
|
||||
// process for full block size
|
||||
for clen >= block_size {
|
||||
binary.little_endian_put_u64(mut dst[pos..pos + 8], d.State.e0)
|
||||
ascon_pnr(mut d.State, 12)
|
||||
ascon_pnr(mut d.State, ascon_prnd_12)
|
||||
pos += block_size
|
||||
clen -= block_size
|
||||
}
|
||||
|
|
|
@ -305,7 +305,7 @@ pub fn (mut x CXof128) free() {
|
|||
fn cxof128_absorb_custom_string(mut s State, cs []u8) {
|
||||
// absorb Z0, the length of the customization string (in bits) encoded as a u64
|
||||
s.e0 ^= u64(cs.len) << 3
|
||||
ascon_pnr(mut s, 12)
|
||||
ascon_pnr(mut s, ascon_prnd_12)
|
||||
|
||||
// absorb the customization string
|
||||
mut zlen := cs.len
|
||||
|
@ -313,7 +313,7 @@ fn cxof128_absorb_custom_string(mut s State, cs []u8) {
|
|||
for zlen >= block_size {
|
||||
block := unsafe { cs[zidx..zidx + block_size] }
|
||||
s.e0 ^= binary.little_endian_u64(block)
|
||||
ascon_pnr(mut s, 12)
|
||||
ascon_pnr(mut s, ascon_prnd_12)
|
||||
|
||||
// updates a index
|
||||
zlen -= block_size
|
||||
|
@ -323,5 +323,5 @@ fn cxof128_absorb_custom_string(mut s State, cs []u8) {
|
|||
last_block := unsafe { cs[zidx..] }
|
||||
s.e0 ^= load_bytes(last_block, last_block.len)
|
||||
s.e0 ^= pad(last_block.len)
|
||||
ascon_pnr(mut s, 12)
|
||||
ascon_pnr(mut s, ascon_prnd_12)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue