Coverage Report

Created: 2026-07-13 08:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/argon2-0.5.3/src/block.rs
Line
Count
Source
1
//! Argon2 memory block functions
2
3
use core::{
4
    convert::{AsMut, AsRef},
5
    num::Wrapping,
6
    ops::{BitXor, BitXorAssign},
7
    slice,
8
};
9
10
#[cfg(feature = "zeroize")]
11
use zeroize::Zeroize;
12
13
const TRUNC: u64 = u32::MAX as u64;
14
15
#[rustfmt::skip]
16
macro_rules! permute_step {
17
    ($a:expr, $b:expr, $c:expr, $d:expr) => {
18
        $a = (Wrapping($a) + Wrapping($b) + (Wrapping(2) * Wrapping(($a & TRUNC) * ($b & TRUNC)))).0;
19
        $d = ($d ^ $a).rotate_right(32);
20
        $c = (Wrapping($c) + Wrapping($d) + (Wrapping(2) * Wrapping(($c & TRUNC) * ($d & TRUNC)))).0;
21
        $b = ($b ^ $c).rotate_right(24);
22
23
        $a = (Wrapping($a) + Wrapping($b) + (Wrapping(2) * Wrapping(($a & TRUNC) * ($b & TRUNC)))).0;
24
        $d = ($d ^ $a).rotate_right(16);
25
        $c = (Wrapping($c) + Wrapping($d) + (Wrapping(2) * Wrapping(($c & TRUNC) * ($d & TRUNC)))).0;
26
        $b = ($b ^ $c).rotate_right(63);
27
    };
28
}
29
30
macro_rules! permute {
31
    (
32
        $v0:expr, $v1:expr, $v2:expr, $v3:expr,
33
        $v4:expr, $v5:expr, $v6:expr, $v7:expr,
34
        $v8:expr, $v9:expr, $v10:expr, $v11:expr,
35
        $v12:expr, $v13:expr, $v14:expr, $v15:expr,
36
    ) => {
37
        permute_step!($v0, $v4, $v8, $v12);
38
        permute_step!($v1, $v5, $v9, $v13);
39
        permute_step!($v2, $v6, $v10, $v14);
40
        permute_step!($v3, $v7, $v11, $v15);
41
        permute_step!($v0, $v5, $v10, $v15);
42
        permute_step!($v1, $v6, $v11, $v12);
43
        permute_step!($v2, $v7, $v8, $v13);
44
        permute_step!($v3, $v4, $v9, $v14);
45
    };
46
}
47
48
/// Structure for the (1 KiB) memory block implemented as 128 64-bit words.
49
#[derive(Copy, Clone, Debug)]
50
#[repr(align(64))]
51
pub struct Block([u64; Self::SIZE / 8]);
52
53
impl Block {
54
    /// Memory block size in bytes
55
    pub const SIZE: usize = 1024;
56
57
    /// Returns a Block initialized with zeros.
58
0
    pub const fn new() -> Self {
59
0
        Self([0u64; Self::SIZE / 8])
60
0
    }
61
62
    /// Load a block from a block-sized byte slice
63
    #[inline(always)]
64
1.96k
    pub(crate) fn load(&mut self, input: &[u8; Block::SIZE]) {
65
251k
        for (i, chunk) in input.chunks(8).enumerate() {
66
251k
            self.0[i] = u64::from_le_bytes(chunk.try_into().expect("should be 8 bytes"));
67
251k
        }
68
1.96k
    }
69
70
    /// Iterate over the `u64` values contained in this block
71
    #[inline(always)]
72
981
    pub(crate) fn iter(&self) -> slice::Iter<'_, u64> {
73
981
        self.0.iter()
74
981
    }
75
76
    /// NOTE: do not call this directly. It should only be called via
77
    /// `Argon2::compress`.
78
    #[inline(always)]
79
38.3M
    pub(crate) fn compress(rhs: &Self, lhs: &Self) -> Self {
80
38.3M
        let r = *rhs ^ lhs;
81
82
        // Apply permutations rowwise
83
38.3M
        let mut q = r;
84
306M
        for chunk in q.0.chunks_exact_mut(16) {
85
306M
            #[rustfmt::skip]
86
306M
            permute!(
87
306M
                chunk[0], chunk[1], chunk[2], chunk[3],
88
306M
                chunk[4], chunk[5], chunk[6], chunk[7],
89
306M
                chunk[8], chunk[9], chunk[10], chunk[11],
90
306M
                chunk[12], chunk[13], chunk[14], chunk[15],
91
306M
            );
92
306M
        }
93
94
        // Apply permutations columnwise
95
306M
        for i in 0..8 {
96
306M
            let b = i * 2;
97
306M
98
306M
            #[rustfmt::skip]
99
306M
            permute!(
100
306M
                q.0[b], q.0[b + 1],
101
306M
                q.0[b + 16], q.0[b + 17],
102
306M
                q.0[b + 32], q.0[b + 33],
103
306M
                q.0[b + 48], q.0[b + 49],
104
306M
                q.0[b + 64], q.0[b + 65],
105
306M
                q.0[b + 80], q.0[b + 81],
106
306M
                q.0[b + 96], q.0[b + 97],
107
306M
                q.0[b + 112], q.0[b + 113],
108
306M
            );
109
306M
        }
110
111
38.3M
        q ^= &r;
112
38.3M
        q
113
38.3M
    }
114
}
115
116
impl Default for Block {
117
24.5k
    fn default() -> Self {
118
24.5k
        Self([0u64; Self::SIZE / 8])
119
24.5k
    }
120
}
121
122
impl AsRef<[u64]> for Block {
123
38.1M
    fn as_ref(&self) -> &[u64] {
124
38.1M
        &self.0
125
38.1M
    }
126
}
127
128
impl AsMut<[u64]> for Block {
129
76.5k
    fn as_mut(&mut self) -> &mut [u64] {
130
76.5k
        &mut self.0
131
76.5k
    }
132
}
133
134
impl BitXor<&Block> for Block {
135
    type Output = Block;
136
137
38.3M
    fn bitxor(mut self, rhs: &Block) -> Self::Output {
138
38.3M
        self ^= rhs;
139
38.3M
        self
140
38.3M
    }
141
}
142
143
impl BitXorAssign<&Block> for Block {
144
95.7M
    fn bitxor_assign(&mut self, rhs: &Block) {
145
12.2G
        for (dst, src) in self.0.iter_mut().zip(rhs.0.iter()) {
146
12.2G
            *dst ^= src;
147
12.2G
        }
148
95.7M
    }
149
}
150
151
#[cfg(feature = "zeroize")]
152
impl Zeroize for Block {
153
    fn zeroize(&mut self) {
154
        self.0.zeroize();
155
    }
156
}