gift_cipher/
lib.rs

1//! Pure Rust implementation of the [Gift] block cipher.
2//!
3//! # ⚠️ Security Warning: Hazmat!
4//!
5//! This crate implements only the low-level block cipher function, and is intended
6//! for use for implementing higher-level constructions *only*. It is NOT
7//! intended for direct use in applications.
8//!
9//! USE AT YOUR OWN RISK!
10//!
11//! # Examples
12//! ```
13//! use gift_cipher::cipher::{Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit};
14//! use gift_cipher::Gift128;
15//!
16//! let key = Array::from([0u8; 16]);
17//! let mut block = Array::from([0u8; 16]);
18//!
19//! // Initialize cipher
20//! let cipher = Gift128::new(&key);
21//!
22//! let block_copy = block;
23//!
24//! // Encrypt block in-place
25//! cipher.encrypt_block(&mut block);
26//!
27//! // And decrypt it back
28//! cipher.decrypt_block(&mut block);
29//!
30//! assert_eq!(block, block_copy);
31//! ```
32//!
33//! [Gift]: https://eprint.iacr.org/2017/622.pdf
34
35#![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/// Gift-128 block cipher instance.
65#[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 {}