1#![allow(clippy::needless_range_loop)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
19pub enum PaddingError {
20 InvalidPadding,
22 InvalidSize,
25 InvalidPaddedSize,
27 NonePadding,
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub enum PaddingTypes {
34 PKCS7,
38 ISO78164,
43 X923,
48 None,
51}
52
53
54
55
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
61pub struct Padding {
62 padding_type: PaddingTypes,
64}
65
66impl Padding {
68 pub fn new(padding_type: PaddingTypes) -> Self {
69 Self {
74 padding_type,
75 }
76 }
77
78 pub fn padding_type(&self) -> PaddingTypes {
79 self.padding_type
84 }
85
86 pub fn set_padding_type(&mut self, padding_type: PaddingTypes) {
87 self.padding_type = padding_type;
92 }
93
94 pub fn pad(&self, input: &[u8]) -> Result<[u8; 16], PaddingError> {
95 if self.padding_type == PaddingTypes::None {
105 return Err(PaddingError::NonePadding);
106 }
107
108 if input.len() >= 16 {
109 return Err(PaddingError::InvalidSize);
110 }
111
112 let mut output: [u8; 16] = [0; 16];
113 output[..input.len()].copy_from_slice(input);
114
115 match self.padding_type {
116 PaddingTypes::PKCS7 => {
117 output[input.len()..16].fill((16 - input.len()) as u8);
118 }
119 PaddingTypes::ISO78164 => {
120 output[input.len()] = 0x80;
121 output[(input.len() + 1)..16].fill(0);
122 }
123 PaddingTypes::X923 => {
124 output[15] = (16 - input.len()) as u8;
125 output[input.len()..15].fill(0);
126 }
127 PaddingTypes::None => panic!("This should not be possible to reach."),
128 }
129
130 Ok(output)
131 }
132
133 pub fn de_pad<'a>(&self, input: &'a [u8]) -> Result<&'a [u8], PaddingError> {
134 if self.padding_type == PaddingTypes::None {
145 return Err(PaddingError::NonePadding);
146 }
147
148 if input.len() != 16 {
149 return Err(PaddingError::InvalidPaddedSize);
150 }
151
152 let upper_bound = match self.padding_type {
153 PaddingTypes::PKCS7 => {
154 let padding_length = input[input.len() - 1];
155
156 if padding_length > 16 || padding_length as usize > input.len() {
157 return Err(PaddingError::InvalidPadding);
158 }
159
160 for i in (input.len() - padding_length as usize)..(input.len() - 1) {
161 if input[i] != padding_length {
162 return Err(PaddingError::InvalidPadding);
163 }
164 }
165
166 input.len() - padding_length as usize
167 }
168 PaddingTypes::ISO78164 => {
169 let mut curr_index: usize = input.len() - 1;
170
171 while input[curr_index] == 0 {
172 curr_index -= 1;
173 }
174
175 if input[curr_index] != 0x80 || input.len() - curr_index > 16{
176 return Err(PaddingError::InvalidPadding);
177 }
178
179 curr_index
180 }
181 PaddingTypes::X923 => {
182 let padding_length = input[input.len() - 1] as usize;
183 if padding_length > 16 {
184 return Err(PaddingError::InvalidPadding);
185 }
186
187 for i in (input.len() - padding_length)..(input.len() - 1) {
188 if input[i] != 0 {
189 return Err(PaddingError::InvalidPadding);
190 }
191 }
192
193 input.len() - padding_length
194 }
195 PaddingTypes::None => panic!("This should not be possible to reach."),
196 };
197
198 Ok(&input[..upper_bound])
199 }
200}
201
202
203
204
205
206#[cfg(test)]
209mod tests {
210 use super::*;
211
212 #[test]
213 fn new() {
214 let padding = Padding::new(PaddingTypes::PKCS7);
215
216 assert_eq!(padding.padding_type, PaddingTypes::PKCS7);
217 }
218
219 #[test]
220 fn set_padding_type() {
221 let mut padding = Padding::new(PaddingTypes::X923);
222
223 assert_eq!(padding.padding_type, PaddingTypes::X923);
224 assert_eq!(padding.padding_type(), PaddingTypes::X923);
225
226 padding.set_padding_type(PaddingTypes::PKCS7);
227
228 assert_eq!(padding.padding_type, PaddingTypes::PKCS7);
229 assert_eq!(padding.padding_type(), PaddingTypes::PKCS7);
230 }
231
232 #[test]
233 fn pkcs7_padding() {
234 let padding: Padding = Padding::new(PaddingTypes::PKCS7);
237
238 let input1: [u8; 2] = [0b10100001, 0b10100000];
239 let output1: [u8; 16] = padding.pad(&input1).unwrap();
240 let wanted1: [u8; 16] = [0b10100001, 0b10100000, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e];
241 assert_eq!(output1, wanted1);
242
243 let input2: [u8; 0] = [];
244 let output2: [u8; 16] = padding.pad(&input2).unwrap();
245 let wanted2: [u8; 16] = [0x10; 16];
246 assert_eq!(output2, wanted2);
247
248 let input3: [u8; 15] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F];
249 let output3: [u8; 16] = padding.pad(&input3).unwrap();
250 let wanted3: [u8; 16] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0b00000001];
251 assert_eq!(output3, wanted3);
252 }
253
254 #[test]
255 fn pkcs7_de_padding() {
256 let padding: Padding = Padding::new(PaddingTypes::PKCS7);
259
260 let input1: [u8; 16] = [0b10100001, 0b10100000, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e];
261 let output1: &[u8] = padding.de_pad(&input1).unwrap();
262 let wanted1: [u8; 2] = [0b10100001, 0b10100000];
263 assert_eq!(output1, wanted1);
264
265 let input2: [u8; 16] = [0x10; 16];
266 let output2: &[u8] = padding.de_pad(&input2).unwrap();
267 let wanted2: [u8; 0] = [];
268 assert_eq!(output2, wanted2);
269
270 let input3: [u8; 16] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0b00000001];
271 let output3: &[u8] = padding.de_pad(&input3).unwrap();
272 let wanted3: [u8; 15] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F];
273 assert_eq!(output3, wanted3);
274 }
275
276 #[test]
277 fn iso78164_padding() {
278 let padding: Padding = Padding::new(PaddingTypes::ISO78164);
281
282 let input1: [u8; 2] = [0b10100001, 0b10100000];
283 let output1: [u8; 16] = padding.pad(&input1).unwrap();
284 let wanted1: [u8; 16] = [0b10100001, 0b10100000, 0b10000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
285 assert_eq!(output1, wanted1);
286
287 let input2: [u8; 0] = [];
288 let output2: [u8; 16] = padding.pad(&input2).unwrap();
289 let wanted2: [u8; 16] = [0b10000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
290 assert_eq!(output2, wanted2);
291
292 let input3: [u8; 15] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F];
293 let output3: [u8; 16] = padding.pad(&input3).unwrap();
294 let wanted3: [u8; 16] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0b10000000];
295 assert_eq!(output3, wanted3);
296 }
297
298 #[test]
299 fn iso78164_de_padding() {
300 let padding: Padding = Padding::new(PaddingTypes::ISO78164);
303
304 let input1: [u8; 16] = [0b10100001, 0b10100000, 0b10000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
305 let output1: &[u8] = padding.de_pad(&input1).unwrap();
306 let wanted1: [u8; 2] = [0b10100001, 0b10100000];
307 assert_eq!(output1, wanted1);
308
309 let input2: [u8; 16] = [0b10000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
310 let output2: &[u8] = padding.de_pad(&input2).unwrap();
311 let wanted2: [u8; 0] = [];
312 assert_eq!(output2, wanted2);
313
314 let input3: [u8; 16] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0b10000000];
315 let output3: &[u8] = padding.de_pad(&input3).unwrap();
316 let wanted3: [u8; 15] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F];
317 assert_eq!(output3, wanted3);
318 }
319
320 #[test]
321 fn x923_padding() {
322 let padding: Padding = Padding::new(PaddingTypes::X923);
325
326 let input1: [u8; 2] = [0b10100001, 0b10100000];
327 let output1: [u8; 16] = padding.pad(&input1).unwrap();
328 let wanted1: [u8; 16] = [0b10100001, 0b10100000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0e];
329 assert_eq!(output1, wanted1);
330
331 let input2: [u8; 0] = [];
332 let output2: [u8; 16] = padding.pad(&input2).unwrap();
333 let mut wanted2: [u8; 16] = [0; 16];
334 wanted2[15] = 0x10;
335 assert_eq!(output2, wanted2);
336
337 let input3: [u8; 15] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F];
338 let output3: [u8; 16] = padding.pad(&input3).unwrap();
339 let wanted3: [u8; 16] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0b00000001];
340 assert_eq!(output3, wanted3);
341 }
342
343 #[test]
344 fn x923_de_padding() {
345 let padding: Padding = Padding::new(PaddingTypes::X923);
348
349 let input1: [u8; 16] = [0b10100001, 0b10100000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0e];
350 let output1: &[u8] = padding.de_pad(&input1).unwrap();
351 let wanted1: [u8; 2] = [0b10100001, 0b10100000];
352 assert_eq!(output1, wanted1);
353
354 let mut input2: [u8; 16] = [0; 16];
355 input2[15] = 0x10;
356 let output2: &[u8] = padding.de_pad(&input2).unwrap();
357 let wanted2: [u8; 0] = [];
358 assert_eq!(output2, wanted2);
359
360 let input3: [u8; 16] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0b00000001];
361 let output3: &[u8] = padding.de_pad(&input3).unwrap();
362 let wanted3: [u8; 15] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F];
363 assert_eq!(output3, wanted3);
364 }
365
366 #[test]
367 fn padding_errors() {
368 let padding_type = PaddingTypes::PKCS7;
369 let input = [
370 0x01, 0x02, 0x03, 0x04,
371 0x05, 0x06, 0x07, 0x08,
372 0x09, 0x0A, 0x0B, 0x0C,
373 ];
374 let mut padded_input = [
375 0x01, 0x02, 0x03, 0x04,
376 0x05, 0x06, 0x07, 0x08,
377 0x09, 0x0A, 0x0B, 0x0C,
378 0x04, 0x04, 0x04, 0x04,
379 ];
380 let padding = Padding::new(padding_type);
381
382 assert_eq!(padding.pad(&input).unwrap(), padded_input);
383 assert_eq!(padding.pad(&[0; 16]), Err(PaddingError::InvalidSize));
384 assert_eq!(padding.pad(&[0; 17]), Err(PaddingError::InvalidSize));
385
386 assert_eq!(padding.de_pad(&padded_input).unwrap(), input);
387 assert_eq!(padding.de_pad(&[0; 15]), Err(PaddingError::InvalidPaddedSize));
388 assert_eq!(padding.de_pad(&[0; 17]), Err(PaddingError::InvalidPaddedSize));
389
390 padded_input[15] = 0x05;
391 assert_eq!(padding.de_pad(&padded_input), Err(PaddingError::InvalidPadding));
392
393 let new_padding = Padding::new(PaddingTypes::None);
394 assert_eq!(new_padding.pad(&input), Err(PaddingError::NonePadding));
395 assert_eq!(new_padding.de_pad(&padded_input), Err(PaddingError::NonePadding));
396 }
397}