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
22pub type BeltCtr<C = BeltBlock> = StreamCipherCoreWrapper<BeltCtrCore<C>>;
24
25pub 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}