1#![no_std]
58#![doc(
59 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg",
60 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg",
61 html_root_url = "https://docs.rs/ofb/0.6.1"
62)]
63#![forbid(unsafe_code)]
64#![cfg_attr(docsrs, feature(doc_cfg))]
65#![warn(missing_docs, rust_2018_idioms)]
66
67pub use cipher;
68
69mod backend;
70
71use cipher::{
72 crypto_common::{InnerUser, IvSizeUser},
73 AlgorithmName, Block, BlockCipher, BlockClosure, BlockDecryptMut, BlockEncryptMut,
74 BlockSizeUser, InnerIvInit, Iv, IvState, StreamCipherCore, StreamCipherCoreWrapper,
75 StreamClosure,
76};
77use core::fmt;
78
79#[cfg(feature = "zeroize")]
80use cipher::zeroize::{Zeroize, ZeroizeOnDrop};
81
82pub type Ofb<C> = StreamCipherCoreWrapper<OfbCore<C>>;
84
85#[derive(Clone)]
87pub struct OfbCore<C>
88where
89 C: BlockEncryptMut + BlockCipher,
90{
91 cipher: C,
92 iv: Block<C>,
93}
94
95impl<C> BlockSizeUser for OfbCore<C>
96where
97 C: BlockEncryptMut + BlockCipher,
98{
99 type BlockSize = C::BlockSize;
100}
101
102impl<C> InnerUser for OfbCore<C>
103where
104 C: BlockEncryptMut + BlockCipher,
105{
106 type Inner = C;
107}
108
109impl<C> IvSizeUser for OfbCore<C>
110where
111 C: BlockEncryptMut + BlockCipher,
112{
113 type IvSize = C::BlockSize;
114}
115
116impl<C> InnerIvInit for OfbCore<C>
117where
118 C: BlockEncryptMut + BlockCipher,
119{
120 #[inline]
121 fn inner_iv_init(cipher: C, iv: &Iv<Self>) -> Self {
122 Self {
123 cipher,
124 iv: iv.clone(),
125 }
126 }
127}
128
129impl<C> IvState for OfbCore<C>
130where
131 C: BlockEncryptMut + BlockCipher,
132{
133 #[inline]
134 fn iv_state(&self) -> Iv<Self> {
135 self.iv.clone()
136 }
137}
138
139impl<C> StreamCipherCore for OfbCore<C>
140where
141 C: BlockEncryptMut + BlockCipher,
142{
143 fn remaining_blocks(&self) -> Option<usize> {
144 None
145 }
146
147 fn process_with_backend(&mut self, f: impl StreamClosure<BlockSize = Self::BlockSize>) {
148 let Self { cipher, iv } = self;
149 cipher.encrypt_with_backend_mut(backend::Closure1 { iv, f });
150 }
151}
152
153impl<C> BlockEncryptMut for OfbCore<C>
154where
155 C: BlockEncryptMut + BlockCipher,
156{
157 #[inline]
158 fn encrypt_with_backend_mut(&mut self, f: impl BlockClosure<BlockSize = Self::BlockSize>) {
159 let Self { cipher, iv } = self;
160 cipher.encrypt_with_backend_mut(backend::Closure2 { iv, f })
161 }
162}
163
164impl<C> BlockDecryptMut for OfbCore<C>
165where
166 C: BlockEncryptMut + BlockCipher,
167{
168 #[inline]
169 fn decrypt_with_backend_mut(&mut self, f: impl BlockClosure<BlockSize = Self::BlockSize>) {
170 let Self { cipher, iv } = self;
171 cipher.encrypt_with_backend_mut(backend::Closure2 { iv, f })
172 }
173}
174
175impl<C> AlgorithmName for OfbCore<C>
176where
177 C: BlockEncryptMut + BlockCipher + AlgorithmName,
178{
179 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 f.write_str("Ofb<")?;
181 <C as AlgorithmName>::write_alg_name(f)?;
182 f.write_str(">")
183 }
184}
185
186impl<C> fmt::Debug for OfbCore<C>
187where
188 C: BlockEncryptMut + BlockCipher + AlgorithmName,
189{
190 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191 f.write_str("OfbCore<")?;
192 <C as AlgorithmName>::write_alg_name(f)?;
193 f.write_str("> { ... }")
194 }
195}
196
197#[cfg(feature = "zeroize")]
198#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
199impl<C: BlockEncryptMut + BlockCipher> Drop for OfbCore<C> {
200 fn drop(&mut self) {
201 self.iv.zeroize();
202 }
203}
204
205#[cfg(feature = "zeroize")]
206#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
207impl<C: BlockEncryptMut + BlockCipher + ZeroizeOnDrop> ZeroizeOnDrop for OfbCore<C> {}