1#![no_std]
36#![doc(
37 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg",
38 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg"
39)]
40#![deny(unsafe_code)]
41#![cfg_attr(docsrs, feature(doc_cfg))]
42#![warn(missing_docs, rust_2018_idioms)]
43
44use cipher::{
45 AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt,
46 BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, Key,
47 KeyInit, KeySizeUser, ParBlocksSizeUser,
48 consts::{U1, U16},
49};
50use core::fmt;
51
52#[cfg(feature = "zeroize")]
53use cipher::zeroize::{Zeroize, ZeroizeOnDrop};
54
55pub use cipher;
56
57mod consts;
58mod key_schedule;
59mod primitives;
60
61use consts::GIFT_RC;
62use primitives::{inv_quintuple_round, packing, quintuple_round, unpacking};
63
64#[derive(Clone)]
66pub struct Gift128 {
67 k: [u32; 80],
68}
69
70impl KeySizeUser for Gift128 {
71 type KeySize = U16;
72}
73
74impl KeyInit for Gift128 {
75 fn new(key: &Key<Self>) -> Self {
76 Self {
77 k: key_schedule::precompute_rkeys(key.into()),
78 }
79 }
80}
81
82impl BlockSizeUser for Gift128 {
83 type BlockSize = U16;
84}
85
86impl ParBlocksSizeUser for Gift128 {
87 type ParBlocksSize = U1;
88}
89
90impl BlockCipherEncrypt for Gift128 {
91 #[inline]
92 fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure<BlockSize = Self::BlockSize>) {
93 f.call(self)
94 }
95}
96
97impl BlockCipherEncBackend for Gift128 {
98 #[inline]
99 fn encrypt_block(&self, mut block: InOut<'_, '_, Block<Self>>) {
100 let b = block.get_in();
101 let mut state = [0u32; 4];
102 packing(&mut state, b.into());
103 for i in (0..40).step_by(5) {
104 quintuple_round(&mut state, &self.k[i * 2..], &GIFT_RC[i..]);
105 }
106 unpacking(&state, block.get_out().into());
107 }
108}
109
110impl BlockCipherDecrypt for Gift128 {
111 #[inline]
112 fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure<BlockSize = Self::BlockSize>) {
113 f.call(self)
114 }
115}
116
117impl BlockCipherDecBackend for Gift128 {
118 #[inline]
119 fn decrypt_block(&self, mut block: InOut<'_, '_, Block<Self>>) {
120 let b = block.get_in();
121 let mut state = [0u32; 4];
122 packing(&mut state, b.into());
123 let mut i: usize = 35;
124 while i > 0 {
125 inv_quintuple_round(&mut state, &self.k[i * 2..], &GIFT_RC[i..]);
126 i -= 5;
127 }
128 inv_quintuple_round(&mut state, &self.k[i * 2..], &GIFT_RC[i..]);
129 unpacking(&state, block.get_out().into());
130 }
131}
132
133impl AlgorithmName for Gift128 {
134 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 f.write_str("Gift128")
136 }
137}
138
139impl fmt::Debug for Gift128 {
140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141 f.write_str("Gift128 { ... }")
142 }
143}
144
145impl Drop for Gift128 {
146 fn drop(&mut self) {
147 #[cfg(feature = "zeroize")]
148 self.k.zeroize();
149 }
150}
151
152#[cfg(feature = "zeroize")]
153impl ZeroizeOnDrop for Gift128 {}