soft_aes/padding/padding_80.rs
1//! 0x80 Padding Module (ISO/IEC 9797-1 Padding Method 2)
2//!
3//! This module provides functionality for applying and removing 0x80 padding
4//! to and from byte arrays, aligning with ISO/IEC 9797-1 padding method 2.
5//! This padding scheme is commonly used in cryptographic protocols and involves
6//! appending a byte with the value 0x80 (binary 1000 0000) followed by as many
7//! zero bytes (0x00) as needed to fill the last block to a specified block size.
8//!
9//! This method ensures that the padded message is always of a length that is a
10//! multiple of the block size, which is crucial for block cipher operations in
11//! cryptographic algorithms. The distinct 0x80 byte guarantees that the padding
12//! is unambiguous, ensuring reliable padding removal.
13//!
14//! # Features
15//!
16//! - `pad_80`: Applies 0x80 padding to a byte array, extending its size to a multiple
17//! of the specified block size.
18//!
19//! - `unpad_80`: Removes 0x80 padding from a byte array, reverting it to its original
20//! unpadded state.
21//!
22//! # Usage
23//!
24//! This padding scheme is particularly useful in cryptographic applications where
25//! the input data size must align with the block size of a block cipher algorithm,
26//! such as AES. It can be employed in various scenarios, including encryption and
27//! message authentication code (MAC) generation.
28//!
29//! # Examples
30//!
31//! Basic usage examples demonstrating padding and unpadding a byte array:
32//!
33//! ```
34//! use soft_aes::padding::{pad_80, unpad_80};
35//!
36//! let mut data = vec![0x01, 0x02, 0x03];
37//! let block_size = 8;
38//! pad_80(&mut data, block_size).expect("Padding failed");
39//!
40//! // Data is now padded according to ISO/IEC 9797-1 Padding Method 2
41//! assert_eq!(data, vec![0x01, 0x02, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00]);
42//!
43//! unpad_80(&mut data).expect("Unpadding failed");
44//!
45//! // Data is back to its original form
46//! assert_eq!(data, vec![0x01, 0x02, 0x03]);
47//! ```
48//!
49//! # References
50//!
51//! - ISO/IEC 9797-1: Information technology – Security techniques – Message Authentication Codes (MACs) –
52//! Part 1: Mechanisms using a block cipher
53//!
54//! # Disclaimer
55//!
56//! - This implementation focuses on clarity and correctness as per ISO/IEC 9797-1 Padding Method 2.
57//! For high-performance requirements, additional optimizations may be necessary.
58
59use std::error::Error;
60
61/// Apply 0x80 padding to a given byte array, in-place.
62///
63/// This function pads the input byte array so that its length is a multiple of
64/// the specified block size. The padding starts with a single 0x80 byte followed
65/// by 0x00 bytes.
66///
67/// # Arguments
68///
69/// * `data` : A mutable reference to the byte array (`Vec<u8>`) to be padded.
70/// * `block_size` : The block size (`usize`) for padding.
71///
72/// # Returns
73///
74/// * `Ok(())` if the padding is successfully applied.
75/// * `Err(Box<dyn Error>)` if the block size is invalid.
76pub fn pad_80(data: &mut Vec<u8>, block_size: usize) -> Result<(), Box<dyn Error>> {
77 if block_size == 0 {
78 return Err("0x80 PADDING ERROR: Block size must be greater than 0".into());
79 }
80
81 data.push(0x80);
82
83 while data.len() % block_size != 0 {
84 data.push(0x00);
85 }
86
87 Ok(())
88}
89
90/// Remove 0x80 padding from a given byte array, in-place.
91///
92/// This function removes the 0x80 padding from the provided byte array.
93/// It checks for the presence of 0x80 followed by 0x00 bytes and removes them.
94///
95/// # Arguments
96///
97/// * `data` : A mutable reference to the byte array (`Vec<u8>`) from which
98/// padding is to be removed.
99///
100/// # Returns
101///
102/// * `Ok(())` if the unpadding is successfully performed.
103/// * `Err(Box<dyn Error>)` if there's an issue with the padding.
104pub fn unpad_80(data: &mut Vec<u8>) -> Result<(), Box<dyn Error>> {
105 if let Some(position) = data.iter().rposition(|&x| x == 0x80) {
106 if data[position + 1..].iter().all(|&x| x == 0x00) {
107 data.truncate(position);
108 Ok(())
109 } else {
110 Err("0x80 UNPADDING ERROR: Invalid padding".into())
111 }
112 } else {
113 Err("0x80 UNPADDING ERROR: Padding byte not found".into())
114 }
115}