webrtc_dtls/crypto/
padding.rs1use cbc::cipher::block_padding::{PadType, RawPadding, UnpadError};
2use core::panic;
3
4pub enum DtlsPadding {}
5impl RawPadding for DtlsPadding {
7 const TYPE: PadType = PadType::Reversible;
8
9 fn raw_pad(block: &mut [u8], pos: usize) {
10 if pos >= block.len() {
11 panic!("`pos` is bigger or equal to block size");
12 }
13
14 let padding_length = block.len() - pos - 1;
15 if padding_length > 255 {
16 panic!("block size is too big for DTLS");
17 }
18
19 set(&mut block[pos..], padding_length as u8);
20 }
21
22 fn raw_unpad(data: &[u8]) -> Result<&[u8], UnpadError> {
23 let padding_length = data.last().copied().unwrap_or(1) as usize;
24 if padding_length + 1 > data.len() {
25 return Err(UnpadError);
26 }
27
28 let padding_begin = data.len() - padding_length - 1;
29
30 if data[padding_begin..data.len() - 1]
31 .iter()
32 .any(|&byte| byte as usize != padding_length)
33 {
34 return Err(UnpadError);
35 }
36
37 Ok(&data[0..padding_begin])
38 }
39}
40
41#[inline(always)]
43fn set(dst: &mut [u8], value: u8) {
44 unsafe {
48 core::ptr::write_bytes(dst.as_mut_ptr(), value, dst.len());
49 }
50}
51
52#[cfg(test)]
53pub mod tests {
54 use rand::Rng;
55
56 use super::*;
57
58 #[test]
59 fn padding_length_is_amount_of_bytes_excluding_the_padding_length_itself() -> Result<(), ()> {
60 for original_length in 0..128 {
61 for padding_length in 0..(256 - original_length) {
62 let mut block = vec![0; original_length + padding_length + 1];
63 rand::thread_rng().fill(&mut block[0..original_length]);
64 let original = block[0..original_length].to_vec();
65 DtlsPadding::raw_pad(&mut block, original_length);
66
67 for byte in block[original_length..].iter() {
68 assert_eq!(*byte as usize, padding_length);
69 }
70 assert_eq!(block[0..original_length], original);
71 }
72 }
73
74 Ok(())
75 }
76
77 #[test]
78 #[should_panic]
79 fn full_block_is_padding_error() {
80 for original_length in 0..256 {
81 let mut block = vec![0; original_length];
82 DtlsPadding::raw_pad(&mut block, original_length);
83 }
84 }
85
86 #[test]
87 #[should_panic]
88 fn padding_length_bigger_than_255_is_a_pad_error() {
89 let padding_length = 256;
90 for original_length in 0..128 {
91 let mut block = vec![0; original_length + padding_length + 1];
92 DtlsPadding::raw_pad(&mut block, original_length);
93 }
94 }
95
96 #[test]
97 fn empty_block_is_unpadding_error() {
98 let r = DtlsPadding::raw_unpad(&[]);
99 assert!(r.is_err());
100 }
101
102 #[test]
103 fn padding_too_big_for_block_is_unpadding_error() {
104 let r = DtlsPadding::raw_unpad(&[1]);
105 assert!(r.is_err());
106 }
107
108 #[test]
109 fn one_of_the_padding_bytes_with_value_different_than_padding_length_is_unpadding_error() {
110 for padding_length in 0..16 {
111 for invalid_byte in 0..padding_length {
112 let mut block = vec![0; padding_length + 1];
113 DtlsPadding::raw_pad(&mut block, 0);
114
115 assert_eq!(DtlsPadding::raw_unpad(&block).ok(), Some(&[][..]));
116 block[invalid_byte] = (padding_length - 1) as u8;
117 let r = DtlsPadding::raw_unpad(&block);
118 assert!(r.is_err());
119 }
120 }
121 }
122}