ofb/
lib.rs

1//! [Output feedback][1] (OFB) mode.
2//!
3//! <img src="https://raw.githubusercontent.com/RustCrypto/media/26acc39f/img/block-modes/ofb_enc.svg" width="49%" />
4//! <img src="https://raw.githubusercontent.com/RustCrypto/media/26acc39f/img/block-modes/ofb_dec.svg" width="49%"/>
5//!
6//! Mode functionality is accessed using traits from re-exported [`cipher`] crate.
7//!
8//! # ⚠️ Security Warning: Hazmat!
9//!
10//! This crate does not ensure ciphertexts are authentic! Thus ciphertext integrity
11//! is not verified, which can lead to serious vulnerabilities!
12//!
13//! # Example
14//! ```
15//! use aes::cipher::{KeyIvInit, StreamCipher};
16//! use hex_literal::hex;
17//!
18//! type Aes128Ofb = ofb::Ofb<aes::Aes128>;
19//!
20//! let key = [0x42; 16];
21//! let iv = [0x24; 16];
22//! let plaintext = *b"hello world! this is my plaintext.";
23//! let ciphertext = hex!(
24//!     "3357121ebb5a29468bd861467596ce3dc6ba5df50e536a2443b8ee16c2f7cd0869c9"
25//! );
26//!
27//! // encrypt in-place
28//! let mut buf = plaintext.to_vec();
29//! let mut cipher = Aes128Ofb::new(&key.into(), &iv.into());
30//! cipher.apply_keystream(&mut buf);
31//! assert_eq!(buf[..], ciphertext[..]);
32//!
33//! // OFB mode can be used with streaming messages
34//! let mut cipher = Aes128Ofb::new(&key.into(), &iv.into());
35//! for chunk in buf.chunks_mut(3) {
36//!     cipher.apply_keystream(chunk);
37//! }
38//! assert_eq!(buf[..], plaintext[..]);
39//!
40//! // encrypt/decrypt from buffer to buffer
41//! // buffer length must be equal to input length
42//! let mut buf1 = [0u8; 34];
43//! let mut cipher = Aes128Ofb::new(&key.into(), &iv.into());
44//! cipher
45//!     .apply_keystream_b2b(&plaintext, &mut buf1)
46//!     .unwrap();
47//! assert_eq!(buf1[..], ciphertext[..]);
48//!
49//! let mut buf2 = [0u8; 34];
50//! let mut cipher = Aes128Ofb::new(&key.into(), &iv.into());
51//! cipher.apply_keystream_b2b(&buf1, &mut buf2).unwrap();
52//! assert_eq!(buf2[..], plaintext[..]);
53//! ```
54//!
55//! [1]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Output_feedback_(OFB)
56
57#![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
82/// Buffered Output feedback (OFB) mode.
83pub type Ofb<C> = StreamCipherCoreWrapper<OfbCore<C>>;
84
85/// Output feedback (OFB) mode.
86#[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> {}