belt_block/
cipher_impl.rs1use crate::{belt_block_raw, from_u32, g5, g13, g21, key_idx, to_u32};
2use cipher::{
3 AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt,
4 BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, Key,
5 KeyInit, KeySizeUser, ParBlocksSizeUser,
6 consts::{U1, U16, U32},
7};
8use core::{fmt, mem::swap, num::Wrapping};
9
10#[cfg(feature = "zeroize")]
11use cipher::zeroize::{Zeroize, ZeroizeOnDrop};
12
13#[derive(Clone)]
15pub struct BeltBlock {
16 key: [u32; 8],
17}
18
19impl KeySizeUser for BeltBlock {
20 type KeySize = U32;
21}
22
23impl KeyInit for BeltBlock {
24 fn new(key: &Key<Self>) -> Self {
25 Self { key: to_u32(key) }
26 }
27}
28
29impl BlockSizeUser for BeltBlock {
30 type BlockSize = U16;
31}
32
33impl ParBlocksSizeUser for BeltBlock {
34 type ParBlocksSize = U1;
35}
36
37impl BlockCipherEncrypt for BeltBlock {
38 #[inline]
39 fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure<BlockSize = Self::BlockSize>) {
40 f.call(self)
41 }
42}
43
44impl BlockCipherEncBackend for BeltBlock {
45 #[inline]
46 fn encrypt_block(&self, mut block: InOut<'_, '_, Block<Self>>) {
47 let x = to_u32(block.get_in());
50 let y = belt_block_raw(x, &self.key);
51
52 let block_out = block.get_out();
53 *block_out = from_u32(&y).into();
55 }
56}
57
58impl BlockCipherDecrypt for BeltBlock {
59 #[inline]
60 fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure<BlockSize = Self::BlockSize>) {
61 f.call(self)
62 }
63}
64
65impl BlockCipherDecBackend for BeltBlock {
66 #[inline]
67 fn decrypt_block(&self, mut block: InOut<'_, '_, Block<Self>>) {
68 let key = &self.key;
69 let block_in: [u32; 4] = to_u32(block.get_in());
70 let mut a = Wrapping(block_in[0]);
72 let mut b = Wrapping(block_in[1]);
73 let mut c = Wrapping(block_in[2]);
74 let mut d = Wrapping(block_in[3]);
75
76 for i in (1..9).rev() {
78 b ^= g5(a + key_idx(key, i, 0));
80 c ^= g21(d + key_idx(key, i, 1));
82 a -= g13(b + key_idx(key, i, 2));
84 let e = g21(b + c + key_idx(key, i, 3)) ^ Wrapping(i as u32);
86 b += e;
88 c -= e;
90 d += g13(c + key_idx(key, i, 4));
92 b ^= g21(a + key_idx(key, i, 5));
94 c ^= g5(d + key_idx(key, i, 6));
96 swap(&mut a, &mut b);
98 swap(&mut c, &mut d);
100 swap(&mut a, &mut d);
102 }
103
104 let block_out = block.get_out();
105 let x = [c.0, a.0, d.0, b.0];
107 *block_out = from_u32(&x).into();
108 }
109}
110
111impl AlgorithmName for BeltBlock {
112 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 f.write_str("BeltBlock")
114 }
115}
116
117impl Drop for BeltBlock {
118 fn drop(&mut self) {
119 #[cfg(feature = "zeroize")]
120 self.key.zeroize();
121 }
122}
123
124#[cfg(feature = "zeroize")]
125impl ZeroizeOnDrop for BeltBlock {}