mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00

Some checks failed
Graphics CI / gg-regressions (push) Waiting to run
vlib modules CI / build-module-docs (push) Waiting to run
Sanitized CI / sanitize-undefined-clang (push) Waiting to run
Sanitized CI / sanitize-undefined-gcc (push) Waiting to run
Sanitized CI / tests-sanitize-address-clang (push) Waiting to run
Sanitized CI / sanitize-address-msvc (push) Waiting to run
Sanitized CI / sanitize-address-gcc (push) Waiting to run
Sanitized CI / sanitize-memory-clang (push) Waiting to run
sdl CI / v-compiles-sdl-examples (push) Waiting to run
Time CI / time-linux (push) Waiting to run
Time CI / time-macos (push) Waiting to run
Time CI / time-windows (push) Waiting to run
toml CI / toml-module-pass-external-test-suites (push) Waiting to run
Tools CI / tools-linux (clang) (push) Waiting to run
Tools CI / tools-linux (gcc) (push) Waiting to run
Tools CI / tools-linux (tcc) (push) Waiting to run
Tools CI / tools-macos (clang) (push) Waiting to run
Tools CI / tools-windows (gcc) (push) Waiting to run
Tools CI / tools-windows (msvc) (push) Waiting to run
Tools CI / tools-windows (tcc) (push) Waiting to run
Tools CI / tools-docker-ubuntu-musl (push) Waiting to run
vab CI / vab-compiles-v-examples (push) Waiting to run
vab CI / v-compiles-os-android (push) Waiting to run
native backend CI / native-backend-ubuntu (push) Has been cancelled
native backend CI / native-backend-windows (push) Has been cancelled
Shy and PV CI / v-compiles-puzzle-vibes (push) Has been cancelled
wasm backend CI / wasm-backend (ubuntu-22.04) (push) Has been cancelled
wasm backend CI / wasm-backend (windows-2022) (push) Has been cancelled
140 lines
4.6 KiB
V
140 lines
4.6 KiB
V
// Copyright ©2025 blackshirt.
|
||
// Use of this source code is governed by an MIT license
|
||
// that can be found in the LICENSE file.
|
||
//
|
||
module ascon
|
||
|
||
// max_nr_perm is the maximum number of permutations round supported on this module.
|
||
// The previous Ascon submission defined three Ascon permutations with 6, 8, and 12 rounds.
|
||
// The NIST SP 800-232 standard specifies additional Ascon permutations by providing round
|
||
// 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
|
||
//
|
||
// 0 0x000000000000003c 8 0x00000000000000b4
|
||
// 1 0x000000000000002d 9 0x00000000000000a5
|
||
// 2 0x000000000000001e 10 0x0000000000000096
|
||
// 3 0x000000000000000f 11 0x0000000000000087
|
||
// 4 0x00000000000000f0 12 0x0000000000000078
|
||
// 5 0x00000000000000e1 13 0x0000000000000069
|
||
// 6 0x00000000000000d2 14 0x000000000000005a
|
||
// 7 0x00000000000000c3 15 0x000000000000004b
|
||
//
|
||
// We use u8 instead, since the first 56 bits of the constants are zero
|
||
const rnc = [u8(0x3c), 0x2d, 0x1e, 0x0f, 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, 0x78,
|
||
0x69, 0x5a, 0x4b]
|
||
|
||
// 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')
|
||
}
|
||
// Allocate temporary vars to reduce allocation within loop
|
||
mut x0 := u64(0)
|
||
mut y0 := u64(0)
|
||
// Ascon permutation routine
|
||
for i := max_nr_perm - nr; i < max_nr_perm; 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
|
||
// Set temp vars to values
|
||
x0 = s.e0
|
||
y0 = s.e4 ^ (~s.e0 & 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 = s.e0 ^ (~s.e1 & s.e2) // t1
|
||
s.e1 = s.e1 ^ (~s.e2 & s.e3) // t2
|
||
s.e2 = s.e2 ^ (~s.e3 & s.e4) // t3
|
||
s.e3 = s.e3 ^ (~s.e4 & x0) // t4, change s.e0 to x0
|
||
s.e4 = y0
|
||
|
||
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)))
|
||
}
|
||
}
|
||
|
||
// State is structure represents Ascon state. Its operates on the 320-bit opaque,
|
||
// which is represented as five of 64-bit words.
|
||
@[noinit]
|
||
struct State {
|
||
mut:
|
||
e0 u64
|
||
e1 u64
|
||
e2 u64
|
||
e3 u64
|
||
e4 u64
|
||
}
|
||
|
||
// clone returns a clone of current state.
|
||
@[inline]
|
||
fn clone_state(s State) State {
|
||
return State{
|
||
e0: s.e0
|
||
e1: s.e1
|
||
e2: s.e2
|
||
e3: s.e3
|
||
e4: s.e4
|
||
}
|
||
}
|
||
|
||
// reset this state with default value
|
||
@[inline]
|
||
fn reset_state(mut s State) {
|
||
s.e0 = 0
|
||
s.e1 = 0
|
||
s.e2 = 0
|
||
s.e3 = 0
|
||
s.e4 = 0
|
||
}
|