ctr/
ctr_core.rs

1use crate::{backend::Closure, CtrFlavor};
2use cipher::{
3    crypto_common::{InnerUser, IvSizeUser},
4    AlgorithmName, BlockCipher, BlockEncryptMut, BlockSizeUser, InnerIvInit, Iv, IvState,
5    StreamCipherCore, StreamCipherSeekCore, StreamClosure,
6};
7use core::fmt;
8
9#[cfg(feature = "zeroize")]
10use cipher::zeroize::ZeroizeOnDrop;
11
12/// Generic CTR block mode instance.
13pub struct CtrCore<C, F>
14where
15    C: BlockEncryptMut + BlockCipher,
16    F: CtrFlavor<C::BlockSize>,
17{
18    cipher: C,
19    ctr_nonce: F::CtrNonce,
20}
21
22impl<C, F> BlockSizeUser for CtrCore<C, F>
23where
24    C: BlockEncryptMut + BlockCipher,
25    F: CtrFlavor<C::BlockSize>,
26{
27    type BlockSize = C::BlockSize;
28}
29
30impl<C, F> StreamCipherCore for CtrCore<C, F>
31where
32    C: BlockEncryptMut + BlockCipher,
33    F: CtrFlavor<C::BlockSize>,
34{
35    #[inline]
36    fn remaining_blocks(&self) -> Option<usize> {
37        F::remaining(&self.ctr_nonce)
38    }
39
40    #[inline]
41    fn process_with_backend(&mut self, f: impl StreamClosure<BlockSize = Self::BlockSize>) {
42        let Self { cipher, ctr_nonce } = self;
43        cipher.encrypt_with_backend_mut(Closure::<F, _, _> { ctr_nonce, f });
44    }
45}
46
47impl<C, F> StreamCipherSeekCore for CtrCore<C, F>
48where
49    C: BlockEncryptMut + BlockCipher,
50    F: CtrFlavor<C::BlockSize>,
51{
52    type Counter = F::Backend;
53
54    #[inline]
55    fn get_block_pos(&self) -> Self::Counter {
56        F::as_backend(&self.ctr_nonce)
57    }
58
59    #[inline]
60    fn set_block_pos(&mut self, pos: Self::Counter) {
61        F::set_from_backend(&mut self.ctr_nonce, pos);
62    }
63}
64
65impl<C, F> InnerUser for CtrCore<C, F>
66where
67    C: BlockEncryptMut + BlockCipher,
68    F: CtrFlavor<C::BlockSize>,
69{
70    type Inner = C;
71}
72
73impl<C, F> IvSizeUser for CtrCore<C, F>
74where
75    C: BlockEncryptMut + BlockCipher,
76    F: CtrFlavor<C::BlockSize>,
77{
78    type IvSize = C::BlockSize;
79}
80
81impl<C, F> InnerIvInit for CtrCore<C, F>
82where
83    C: BlockEncryptMut + BlockCipher,
84    F: CtrFlavor<C::BlockSize>,
85{
86    #[inline]
87    fn inner_iv_init(cipher: C, iv: &Iv<Self>) -> Self {
88        Self {
89            cipher,
90            ctr_nonce: F::from_nonce(iv),
91        }
92    }
93}
94
95impl<C, F> IvState for CtrCore<C, F>
96where
97    C: BlockEncryptMut + BlockCipher,
98    F: CtrFlavor<C::BlockSize>,
99{
100    #[inline]
101    fn iv_state(&self) -> Iv<Self> {
102        F::current_block(&self.ctr_nonce)
103    }
104}
105
106impl<C, F> AlgorithmName for CtrCore<C, F>
107where
108    C: BlockEncryptMut + BlockCipher + AlgorithmName,
109    F: CtrFlavor<C::BlockSize>,
110{
111    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        f.write_str("Ctr")?;
113        f.write_str(F::NAME)?;
114        f.write_str("<")?;
115        <C as AlgorithmName>::write_alg_name(f)?;
116        f.write_str(">")
117    }
118}
119
120impl<C, F> Clone for CtrCore<C, F>
121where
122    C: BlockEncryptMut + BlockCipher + Clone,
123    F: CtrFlavor<C::BlockSize>,
124{
125    #[inline]
126    fn clone(&self) -> Self {
127        Self {
128            cipher: self.cipher.clone(),
129            ctr_nonce: self.ctr_nonce.clone(),
130        }
131    }
132}
133
134impl<C, F> fmt::Debug for CtrCore<C, F>
135where
136    C: BlockEncryptMut + BlockCipher + AlgorithmName,
137    F: CtrFlavor<C::BlockSize>,
138{
139    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140        f.write_str("Ctr")?;
141        f.write_str(F::NAME)?;
142        f.write_str("<")?;
143        <C as AlgorithmName>::write_alg_name(f)?;
144        f.write_str("> { ... }")
145    }
146}
147
148#[cfg(feature = "zeroize")]
149#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
150impl<C, F> ZeroizeOnDrop for CtrCore<C, F>
151where
152    C: BlockEncryptMut + BlockCipher + ZeroizeOnDrop,
153    F: CtrFlavor<C::BlockSize>,
154    F::CtrNonce: ZeroizeOnDrop,
155{
156}