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
12pub 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}