/src/suricata8/rust/src/utils/base64.rs
Line | Count | Source |
1 | | /* Copyright (C) 2024 Open Information Security Foundation |
2 | | * |
3 | | * You can copy, redistribute or modify this Program under the terms of |
4 | | * the GNU General Public License version 2 as published by the Free |
5 | | * Software Foundation. |
6 | | * |
7 | | * This program is distributed in the hope that it will be useful, |
8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | | * GNU General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU General Public License |
13 | | * version 2 along with this program; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
15 | | * 02110-1301, USA. |
16 | | */ |
17 | | |
18 | | // Author: Shivani Bhardwaj <shivani@oisf.net> |
19 | | |
20 | | use std::io::{Error, ErrorKind, Result}; |
21 | | |
22 | 34.9M | fn base64_map(input: u8) -> Result<u8> { |
23 | 34.9M | match input { |
24 | 4.00k | 43 => Ok(62), // + |
25 | 66.9k | 47 => Ok(63), // / |
26 | 8.17M | 48 => Ok(52), // 0 |
27 | 207k | 49 => Ok(53), // 1 |
28 | 182k | 50 => Ok(54), // 2 |
29 | 104k | 51 => Ok(55), // 3 |
30 | 112k | 52 => Ok(56), // 4 |
31 | 104k | 53 => Ok(57), // 5 |
32 | 103k | 54 => Ok(58), // 6 |
33 | 108k | 55 => Ok(59), // 7 |
34 | 165k | 56 => Ok(60), // 8 |
35 | 103k | 57 => Ok(61), // 9 |
36 | 199k | 65 => Ok(0), // A |
37 | 24.1k | 66 => Ok(1), // B |
38 | 257k | 67 => Ok(2), // C |
39 | 14.7k | 68 => Ok(3), // D |
40 | 44.2k | 69 => Ok(4), // E |
41 | 191k | 70 => Ok(5), // F |
42 | 403k | 71 => Ok(6), // G |
43 | 4.76k | 72 => Ok(7), // H |
44 | 9.42k | 73 => Ok(8), // I |
45 | 43.8k | 74 => Ok(9), // J |
46 | 252k | 75 => Ok(10), // K |
47 | 13.7k | 76 => Ok(11), // L |
48 | 1.22M | 77 => Ok(12), // M |
49 | 1.04k | 78 => Ok(13), // N |
50 | 255k | 79 => Ok(14), // O |
51 | 249k | 80 => Ok(15), // P |
52 | 1.46k | 81 => Ok(16), // Q |
53 | 35.6k | 82 => Ok(17), // R |
54 | 28.3k | 83 => Ok(18), // S |
55 | 190k | 84 => Ok(19), // T |
56 | 1.22M | 85 => Ok(20), // U |
57 | 123k | 86 => Ok(21), // V |
58 | 916 | 87 => Ok(22), // W |
59 | 16.8k | 88 => Ok(23), // X |
60 | 936 | 89 => Ok(24), // Y |
61 | 362k | 90 => Ok(25), // Z |
62 | 9.69M | 97 => Ok(26), // a |
63 | 51.3k | 98 => Ok(27), // b |
64 | 63.9k | 99 => Ok(28), // c |
65 | 35.8k | 100 => Ok(29), // d |
66 | 42.9k | 101 => Ok(30), // e |
67 | 725k | 102 => Ok(31), // f |
68 | 22.9k | 103 => Ok(32), // g |
69 | 4.75k | 104 => Ok(33), // h |
70 | 54.5k | 105 => Ok(34), // i |
71 | 5.86k | 106 => Ok(35), // j |
72 | 901 | 107 => Ok(36), // k |
73 | 300k | 108 => Ok(37), // l |
74 | 21.9k | 109 => Ok(38), // m |
75 | 51.3k | 110 => Ok(39), // n |
76 | 603k | 111 => Ok(40), // o |
77 | 259k | 112 => Ok(41), // p |
78 | 10.3k | 113 => Ok(42), // q |
79 | 27.7k | 114 => Ok(43), // r |
80 | 22.0k | 115 => Ok(44), // s |
81 | 1.16M | 116 => Ok(45), // t |
82 | 1.77k | 117 => Ok(46), // u |
83 | 8.18k | 118 => Ok(47), // v |
84 | 42.3k | 119 => Ok(48), // w |
85 | 33.7k | 120 => Ok(49), // x |
86 | 4.19k | 121 => Ok(50), // y |
87 | 7.85k | 122 => Ok(51), // z |
88 | 7.04M | _ => Err(Error::new(ErrorKind::InvalidData, "invalid base64")), |
89 | | } |
90 | 34.9M | } |
91 | | |
92 | | #[derive(Debug)] |
93 | | pub struct Decoder { |
94 | | tmp: [u8; 4], |
95 | | pub nb: u8, |
96 | | } |
97 | | |
98 | | impl Decoder { |
99 | 2.02k | pub fn new() -> Decoder { |
100 | 2.02k | Decoder { tmp: [0; 4], nb: 0 } |
101 | 2.02k | } |
102 | | } |
103 | | |
104 | | impl Default for Decoder { |
105 | 0 | fn default() -> Self { |
106 | 0 | Self::new() |
107 | 0 | } |
108 | | } |
109 | | |
110 | 1.01k | pub fn get_decoded_buffer_size(encoded_len: u32) -> u32 { |
111 | 1.01k | return ((encoded_len * 3) + (encoded_len % 4)) / 4; |
112 | 1.01k | } |
113 | | |
114 | 0 | pub fn decode_rfc4648(decoder: &mut Decoder, input: &[u8], output: &mut [u8], decoded_bytes: &mut u32) -> Result<()> |
115 | | { |
116 | 0 | let mut i = input; |
117 | 0 | let mut offset = 0; |
118 | 0 | let mut stop = false; |
119 | 0 | while !i.is_empty() { |
120 | 0 | while decoder.nb < 4 { |
121 | 0 | if !i.is_empty() && (base64_map(i[0]).is_ok() || i[0] == b'=') { |
122 | 0 | decoder.tmp[decoder.nb as usize] = i[0]; |
123 | 0 | decoder.nb += 1; |
124 | 0 | } else { |
125 | 0 | while decoder.nb > 0 |
126 | 0 | && decoder.nb < 4 |
127 | 0 | { |
128 | 0 | decoder.tmp[decoder.nb as usize] = b'='; |
129 | 0 | decoder.nb += 1; |
130 | 0 | } |
131 | 0 | stop = true; |
132 | 0 | break; |
133 | | } |
134 | 0 | i = &i[1..]; |
135 | | } |
136 | 0 | if decoder.nb == 4 { |
137 | 0 | decoder.tmp[0] = base64_map(decoder.tmp[0])?; |
138 | 0 | decoder.tmp[1] = base64_map(decoder.tmp[1])?; |
139 | 0 | if decoder.tmp[2] == b'=' { |
140 | 0 | output[offset] = (decoder.tmp[0] << 2) | (decoder.tmp[1] >> 4); |
141 | 0 | offset += 1; |
142 | 0 | } else { |
143 | 0 | decoder.tmp[2] = base64_map(decoder.tmp[2])?; |
144 | 0 | if decoder.tmp[3] == b'=' { |
145 | 0 | output[offset] = (decoder.tmp[0] << 2) | (decoder.tmp[1] >> 4); |
146 | 0 | output[offset + 1] = (decoder.tmp[1] << 4) | (decoder.tmp[2] >> 2); |
147 | 0 | offset += 2; |
148 | 0 | } else { |
149 | 0 | decoder.tmp[3] = base64_map(decoder.tmp[3])?; |
150 | 0 | output[offset] = (decoder.tmp[0] << 2) | (decoder.tmp[1] >> 4); |
151 | 0 | output[offset + 1] = (decoder.tmp[1] << 4) | (decoder.tmp[2] >> 2); |
152 | 0 | output[offset + 2] = (decoder.tmp[2] << 6) | decoder.tmp[3]; |
153 | 0 | offset += 3; |
154 | | } |
155 | | } |
156 | 0 | decoder.nb = 0; |
157 | 0 | } |
158 | 0 | if stop { |
159 | 0 | break; |
160 | 0 | } |
161 | | } |
162 | | |
163 | 0 | *decoded_bytes = offset as u32; |
164 | | |
165 | 0 | return Ok(()); |
166 | 0 | } |
167 | | |
168 | 1.01k | pub fn decode_rfc2045(decoder: &mut Decoder, input: &[u8], output: &mut [u8], decoded_bytes: &mut u32) -> Result<()> |
169 | | { |
170 | 1.01k | let mut i = input; |
171 | 1.01k | let mut offset = 0; |
172 | | |
173 | 3.48M | while !i.is_empty() { |
174 | 24.4M | while decoder.nb < 4 && !i.is_empty() { |
175 | 20.9M | if base64_map(i[0]).is_ok() || i[0] == b'=' { |
176 | 13.9M | decoder.tmp[decoder.nb as usize] = i[0]; |
177 | 13.9M | decoder.nb += 1; |
178 | 13.9M | } |
179 | 20.9M | i = &i[1..]; |
180 | | } |
181 | 3.48M | if decoder.nb == 4 { |
182 | 3.48M | decoder.tmp[0] = base64_map(decoder.tmp[0])?; |
183 | 3.48M | decoder.tmp[1] = base64_map(decoder.tmp[1])?; |
184 | 3.48M | if decoder.tmp[2] == b'=' { |
185 | 2.55k | output[offset] = (decoder.tmp[0] << 2) | (decoder.tmp[1] >> 4); |
186 | 2.55k | offset += 1; |
187 | 2.55k | } else { |
188 | 3.48M | decoder.tmp[2] = base64_map(decoder.tmp[2])?; |
189 | 3.48M | if decoder.tmp[3] == b'=' { |
190 | 2.25k | output[offset] = (decoder.tmp[0] << 2) | (decoder.tmp[1] >> 4); |
191 | 2.25k | output[offset + 1] = (decoder.tmp[1] << 4) | (decoder.tmp[2] >> 2); |
192 | 2.25k | offset += 2; |
193 | 2.25k | } else { |
194 | 3.48M | decoder.tmp[3] = base64_map(decoder.tmp[3])?; |
195 | 3.48M | output[offset] = (decoder.tmp[0] << 2) | (decoder.tmp[1] >> 4); |
196 | 3.48M | output[offset + 1] = (decoder.tmp[1] << 4) | (decoder.tmp[2] >> 2); |
197 | 3.48M | output[offset + 2] = (decoder.tmp[2] << 6) | decoder.tmp[3]; |
198 | 3.48M | offset += 3; |
199 | | } |
200 | | } |
201 | 3.48M | decoder.nb = 0; |
202 | 392 | } |
203 | | } |
204 | 935 | *decoded_bytes = offset as u32; |
205 | | |
206 | 935 | return Ok(()); |
207 | 1.01k | } |