Coverage Report

Created: 2026-08-14 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/chacha20-0.10.0/src/backends/soft.rs
Line
Count
Source
1
//! Portable implementation which does not rely on architecture-specific intrinsics.
2
3
#![allow(clippy::cast_possible_truncation)]
4
5
use crate::{ChaChaCore, Rounds, STATE_WORDS, Variant, quarter_round};
6
7
#[cfg(feature = "cipher")]
8
use crate::chacha::Block;
9
#[cfg(feature = "cipher")]
10
use cipher::{
11
    BlockSizeUser, ParBlocksSizeUser, StreamCipherBackend,
12
    consts::{U1, U64},
13
};
14
15
#[cfg(feature = "rng")]
16
use crate::rng::BLOCK_WORDS;
17
18
pub(crate) struct Backend<'a, R: Rounds, V: Variant>(pub(crate) &'a mut ChaChaCore<R, V>);
19
20
#[cfg(feature = "cipher")]
21
impl<R: Rounds, V: Variant> BlockSizeUser for Backend<'_, R, V> {
22
    type BlockSize = U64;
23
}
24
25
#[cfg(feature = "cipher")]
26
impl<R: Rounds, V: Variant> ParBlocksSizeUser for Backend<'_, R, V> {
27
    type ParBlocksSize = U1;
28
}
29
30
#[cfg(feature = "cipher")]
31
impl<R: Rounds, V: Variant> StreamCipherBackend for Backend<'_, R, V> {
32
    #[inline(always)]
33
    fn gen_ks_block(&mut self, block: &mut Block) {
34
        let res = run_rounds::<R>(&self.0.state);
35
        let mut ctr = (u64::from(self.0.state[13]) << 32) | u64::from(self.0.state[12]);
36
        ctr = ctr.wrapping_add(1);
37
        self.0.state[12] = ctr as u32;
38
        if size_of::<V::Counter>() == 8 {
39
            self.0.state[13] = (ctr >> 32) as u32;
40
        }
41
42
        for (chunk, val) in block.chunks_exact_mut(4).zip(res.iter()) {
43
            chunk.copy_from_slice(&val.to_le_bytes());
44
        }
45
    }
46
}
47
48
#[cfg(feature = "rng")]
49
impl<R: Rounds, V: Variant> Backend<'_, R, V> {
50
    #[inline(always)]
51
0
    pub(crate) fn gen_ks_blocks(&mut self, buffer: &mut [u32; 64]) {
52
0
        for block in 0..4 {
53
0
            let res = run_rounds::<R>(&self.0.state);
54
0
            let mut ctr = (u64::from(self.0.state[13]) << 32) | u64::from(self.0.state[12]);
55
0
            ctr = ctr.wrapping_add(1);
56
0
            self.0.state[12] = ctr as u32;
57
0
            self.0.state[13] = (ctr >> 32) as u32;
58
0
59
0
            buffer[block * BLOCK_WORDS as usize..(block + 1) * BLOCK_WORDS as usize]
60
0
                .copy_from_slice(&res);
61
0
        }
62
0
    }
Unexecuted instantiation: <chacha20::backends::soft::Backend<chacha20::R12, chacha20::variants::Legacy>>::gen_ks_blocks
Unexecuted instantiation: <chacha20::backends::soft::Backend<_, _>>::gen_ks_blocks
63
}
64
65
#[inline(always)]
66
0
fn run_rounds<R: Rounds>(state: &[u32; STATE_WORDS]) -> [u32; STATE_WORDS] {
67
0
    let mut res = *state;
68
69
0
    for _ in 0..R::COUNT {
70
0
        // column rounds
71
0
        quarter_round(0, 4, 8, 12, &mut res);
72
0
        quarter_round(1, 5, 9, 13, &mut res);
73
0
        quarter_round(2, 6, 10, 14, &mut res);
74
0
        quarter_round(3, 7, 11, 15, &mut res);
75
0
76
0
        // diagonal rounds
77
0
        quarter_round(0, 5, 10, 15, &mut res);
78
0
        quarter_round(1, 6, 11, 12, &mut res);
79
0
        quarter_round(2, 7, 8, 13, &mut res);
80
0
        quarter_round(3, 4, 9, 14, &mut res);
81
0
    }
82
83
0
    for (s1, s0) in res.iter_mut().zip(state.iter()) {
84
0
        *s1 = s1.wrapping_add(*s0);
85
0
    }
86
0
    res
87
0
}
Unexecuted instantiation: chacha20::backends::soft::run_rounds::<chacha20::R12>
Unexecuted instantiation: chacha20::backends::soft::run_rounds::<_>