belt_ctr/
lib.rs

1#![no_std]
2#![doc = include_str!("../README.md")]
3#![doc(
4    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
5    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
6)]
7#![forbid(unsafe_code)]
8#![cfg_attr(docsrs, feature(doc_cfg))]
9#![warn(missing_docs, rust_2018_idioms)]
10
11pub use cipher;
12
13use belt_block::BeltBlock;
14use cipher::{
15    consts::U16, crypto_common::InnerUser, generic_array::GenericArray, BlockDecrypt, BlockEncrypt,
16    BlockSizeUser, InnerIvInit, Iv, IvSizeUser, IvState, StreamCipherCore, StreamCipherCoreWrapper,
17    StreamCipherSeekCore, StreamClosure,
18};
19
20mod backend;
21
22/// Byte-level BelT CTR
23pub type BeltCtr<C = BeltBlock> = StreamCipherCoreWrapper<BeltCtrCore<C>>;
24
25/// Block-level BelT CTR
26pub struct BeltCtrCore<C = BeltBlock>
27where
28    C: BlockEncrypt + BlockSizeUser<BlockSize = U16>,
29{
30    cipher: C,
31    s: u128,
32    s_init: u128,
33}
34
35impl<C> StreamCipherCore for BeltCtrCore<C>
36where
37    C: BlockEncrypt + BlockSizeUser<BlockSize = U16>,
38{
39    fn remaining_blocks(&self) -> Option<usize> {
40        let used = self.s.wrapping_sub(self.s_init);
41        (u128::MAX - used).try_into().ok()
42    }
43
44    fn process_with_backend(&mut self, f: impl StreamClosure<BlockSize = Self::BlockSize>) {
45        let Self { cipher, s, .. } = self;
46        cipher.encrypt_with_backend(backend::Closure { s, f });
47    }
48}
49
50impl<C> StreamCipherSeekCore for BeltCtrCore<C>
51where
52    C: BlockEncrypt + BlockSizeUser<BlockSize = U16>,
53{
54    type Counter = u128;
55
56    fn get_block_pos(&self) -> Self::Counter {
57        self.s.wrapping_sub(self.s_init)
58    }
59
60    fn set_block_pos(&mut self, pos: Self::Counter) {
61        self.s = self.s_init.wrapping_add(pos);
62    }
63}
64
65impl<C> BlockSizeUser for BeltCtrCore<C>
66where
67    C: BlockEncrypt + BlockSizeUser<BlockSize = U16>,
68{
69    type BlockSize = C::BlockSize;
70}
71
72impl<C> IvSizeUser for BeltCtrCore<C>
73where
74    C: BlockEncrypt + BlockSizeUser<BlockSize = U16>,
75{
76    type IvSize = C::BlockSize;
77}
78
79impl<C> InnerUser for BeltCtrCore<C>
80where
81    C: BlockEncrypt + BlockSizeUser<BlockSize = U16>,
82{
83    type Inner = C;
84}
85
86impl<C> InnerIvInit for BeltCtrCore<C>
87where
88    C: BlockEncrypt + BlockSizeUser<BlockSize = U16>,
89{
90    #[inline]
91    fn inner_iv_init(cipher: C, iv: &Iv<Self>) -> Self {
92        let mut t = GenericArray::default();
93        cipher.encrypt_block_b2b(iv, &mut t);
94        let s = u128::from_le_bytes(t.into());
95        Self {
96            cipher,
97            s,
98            s_init: s,
99        }
100    }
101}
102
103impl<C> IvState for BeltCtrCore<C>
104where
105    C: BlockEncrypt + BlockDecrypt + BlockSizeUser<BlockSize = U16>,
106{
107    fn iv_state(&self) -> Iv<Self> {
108        let mut t = self.s.to_le_bytes().into();
109        self.cipher.decrypt_block(&mut t);
110        t
111    }
112}