Branch data Line data Source code
1 : : /**
2 : : ***********************************************************************************************************************
3 : : * @file base64.c
4 : : * @author Diego Martínez García (dmg0345@gmail.com)
5 : : * @date 06-03-2024 22:23:23 (UTC)
6 : : * @version 1.0.3
7 : : * @copyright github.com/dmg0345/bde/blob/master/LICENSE
8 : : ***********************************************************************************************************************
9 : : */
10 : :
11 : : /* Includes ----------------------------------------------------------------------------------------------------------*/
12 : : #include "bde/bde.h"
13 : :
14 : : /* Private types -----------------------------------------------------------------------------------------------------*/
15 : : /**
16 : : * @addtogroup bde_base64_iapi_impl
17 : : * @{
18 : : */
19 : :
20 : : /**
21 : : * @}
22 : : */
23 : :
24 : : /* Private define ----------------------------------------------------------------------------------------------------*/
25 : : /**
26 : : * @addtogroup bde_base64_iapi_impl
27 : : * @{
28 : : */
29 : :
30 : : #define BDE_MODE_BASE64 (0U) /**< Base64 mode for specified operation. */
31 : : #define BDE_MODE_BASE64URL (1U) /**< Base64URL mode for specified operation. */
32 : :
33 : : /**
34 : : * @}
35 : : */
36 : :
37 : : /* Private macro -----------------------------------------------------------------------------------------------------*/
38 : : /**
39 : : * @addtogroup bde_base64_iapi_impl
40 : : * @{
41 : : */
42 : :
43 : : /**
44 : : * @}
45 : : */
46 : :
47 : : /* Private variables -------------------------------------------------------------------------------------------------*/
48 : : /**
49 : : * @addtogroup bde_base64_iapi_impl
50 : : * @{
51 : : */
52 : :
53 : : static const bde_enc_t bde_base64_padding_char = '='; /**< Base64 padding character. */
54 : :
55 : : /** Base64URL alphabet for encoding. */
56 : : static const bde_enc_t bde_base64_encode_alphabet_lut[64U] = {
57 : : [0U] = 'A', [1U] = 'B', [2U] = 'C', [3U] = 'D', [4U] = 'E', [5U] = 'F', [6U] = 'G', [7U] = 'H',
58 : : [8U] = 'I', [9U] = 'J', [10U] = 'K', [11U] = 'L', [12U] = 'M', [13U] = 'N', [14U] = 'O', [15U] = 'P',
59 : : [16U] = 'Q', [17U] = 'R', [18U] = 'S', [19U] = 'T', [20U] = 'U', [21U] = 'V', [22U] = 'W', [23U] = 'X',
60 : : [24U] = 'Y', [25U] = 'Z', [26U] = 'a', [27U] = 'b', [28U] = 'c', [29U] = 'd', [30U] = 'e', [31U] = 'f',
61 : : [32U] = 'g', [33U] = 'h', [34U] = 'i', [35U] = 'j', [36U] = 'k', [37U] = 'l', [38U] = 'm', [39U] = 'n',
62 : : [40U] = 'o', [41U] = 'p', [42U] = 'q', [43U] = 'r', [44U] = 's', [45U] = 't', [46U] = 'u', [47U] = 'v',
63 : : [48U] = 'w', [49U] = 'x', [50U] = 'y', [51U] = 'z', [52U] = '0', [53U] = '1', [54U] = '2', [55U] = '3',
64 : : [56U] = '4', [57U] = '5', [58U] = '6', [59U] = '7', [60U] = '8', [61U] = '9', [62U] = '-', [63U] = '_',
65 : : };
66 : :
67 : : /** Base64URL alphabet for decoding, note it contains relevant range of [43, 122]. */
68 : : static const bde_dec_t bde_base64_decode_alphabet_lut[80U] = {
69 : : [43U - 43U] = 0xFFU, [44U - 43U] = 0xFFU, ['-' - 43U] = 0x3EU, [46U - 43U] = 0xFFU, [47U - 43U] = 0xFFU,
70 : : ['0' - 43U] = 0x34U, ['1' - 43U] = 0x35U, ['2' - 43U] = 0x36U, ['3' - 43U] = 0x37U, ['4' - 43U] = 0x38U,
71 : : ['5' - 43U] = 0x39U, ['6' - 43U] = 0x3AU, ['7' - 43U] = 0x3BU, ['8' - 43U] = 0x3CU, ['9' - 43U] = 0x3DU,
72 : : [58U - 43U] = 0xFFU, [59U - 43U] = 0xFFU, [60U - 43U] = 0xFFU, [61U - 43U] = 0xFFU, [62U - 43U] = 0xFFU,
73 : : [63U - 43U] = 0xFFU, [64U - 43U] = 0xFFU, ['A' - 43U] = 0x00U, ['B' - 43U] = 0x01U, ['C' - 43U] = 0x02U,
74 : : ['D' - 43U] = 0x03U, ['E' - 43U] = 0x04U, ['F' - 43U] = 0x05U, ['G' - 43U] = 0x06U, ['H' - 43U] = 0x07U,
75 : : ['I' - 43U] = 0x08U, ['J' - 43U] = 0x09U, ['K' - 43U] = 0x0AU, ['L' - 43U] = 0x0BU, ['M' - 43U] = 0x0CU,
76 : : ['N' - 43U] = 0x0DU, ['O' - 43U] = 0x0EU, ['P' - 43U] = 0x0FU, ['Q' - 43U] = 0x10U, ['R' - 43U] = 0x11U,
77 : : ['S' - 43U] = 0x12U, ['T' - 43U] = 0x13U, ['U' - 43U] = 0x14U, ['V' - 43U] = 0x15U, ['W' - 43U] = 0x16U,
78 : : ['X' - 43U] = 0x17U, ['Y' - 43U] = 0x18U, ['Z' - 43U] = 0x19U, [91U - 43U] = 0xFFU, [92U - 43U] = 0xFFU,
79 : : [93U - 43U] = 0xFFU, [94U - 43U] = 0xFFU, ['_' - 43U] = 0x3FU, [96U - 43U] = 0xFFU, ['a' - 43U] = 0x1AU,
80 : : ['b' - 43U] = 0x1BU, ['c' - 43U] = 0x1CU, ['d' - 43U] = 0x1DU, ['e' - 43U] = 0x1EU, ['f' - 43U] = 0x1FU,
81 : : ['g' - 43U] = 0x20U, ['h' - 43U] = 0x21U, ['i' - 43U] = 0x22U, ['j' - 43U] = 0x23U, ['k' - 43U] = 0x24U,
82 : : ['l' - 43U] = 0x25U, ['m' - 43U] = 0x26U, ['n' - 43U] = 0x27U, ['o' - 43U] = 0x28U, ['p' - 43U] = 0x29U,
83 : : ['q' - 43U] = 0x2AU, ['r' - 43U] = 0x2BU, ['s' - 43U] = 0x2CU, ['t' - 43U] = 0x2DU, ['u' - 43U] = 0x2EU,
84 : : ['v' - 43U] = 0x2FU, ['w' - 43U] = 0x30U, ['x' - 43U] = 0x31U, ['y' - 43U] = 0x32U, ['z' - 43U] = 0x33U,
85 : : };
86 : :
87 : : /**
88 : : * @}
89 : : */
90 : :
91 : : /* Private function prototypes ---------------------------------------------------------------------------------------*/
92 : : /**
93 : : * @addtogroup bde_base64_iapi_impl
94 : : * @{
95 : : */
96 : :
97 : : /**
98 : : * @brief Gets relevant number of octets related to the encoding of the decoded data.
99 : : * @param[in] decoded_len Length of the decoded data.
100 : : * @param[in] mode Operation mode, one of @ref BDE_MODE_BASE64 or @ref BDE_MODE_BASE64URL.
101 : : * @param[out] decoded_octets_cbl Number of decoded octets that generate complete encoded blocks.
102 : : * @param[out] decoded_octets_lbl Number of octets in the last uncomplete decoded block, if any.
103 : : * @param[out] encoded_octets Number of octets in the resulting encoded string, not including the @c NULL terminator.
104 : : * @retval ::bde_error_ok Success.
105 : : * @note There are three octets in a decoded block, there are four octets in a encoded block.
106 : : * @note The output arguments are calculated in the order in which they appear in the parameter list of the function.
107 : : */
108 : : static bde_error_t bde_encode_lengths(const size_t decoded_len,
109 : : const size_t mode,
110 : : size_t * const decoded_octets_cbl,
111 : : size_t * const decoded_octets_lbl,
112 : : size_t * const encoded_octets);
113 : :
114 : : /**
115 : : * @brief Encodes the given element.
116 : : * @param[in] decoded The decoded element to encode.
117 : : * @param[in] mode Operation mode, one of @ref BDE_MODE_BASE64 or @ref BDE_MODE_BASE64URL.
118 : : * @return The encoded element.
119 : : */
120 : : static bde_enc_t bde_encode_elem(const bde_dec_t decoded, const size_t mode);
121 : :
122 : : /**
123 : : * @brief Encodes the given decoded data.
124 : : * @param[in] decoded The decoded data to encode.
125 : : * @param[in] decoded_len The length of the decoded data.
126 : : * @param[in] mode Operation mode, one of @ref BDE_MODE_BASE64 or @ref BDE_MODE_BASE64URL.
127 : : * @param[in] encoded_max_len The length of the encoded buffer.
128 : : * @param[out] encoded The buffer where the encoded string will be written.
129 : : * @param[out] encoded_len The length of the encoded string written, not including the @c NULL terminator. Can
130 : : * be @c NULL if not required.
131 : : * @retval ::bde_error_ok Success.
132 : : * @retval ::bde_error_buffer_length The buffer is not long enough for the encoded string.
133 : : */
134 : : static bde_error_t bde_encode(const bde_dec_t * const decoded,
135 : : const size_t decoded_len,
136 : : const size_t mode,
137 : : const size_t encoded_max_len,
138 : : bde_enc_t * const encoded,
139 : : size_t * const encoded_len);
140 : :
141 : : /**
142 : : * @brief Gets relevant number of octets related to the decoding of the encoded string.
143 : : * @param[in] encoded Encoded string.
144 : : * @param[in] encoded_len Length of the encoded string, not including the @c NULL terminator.
145 : : * @param[in] mode Operation mode, one of @ref BDE_MODE_BASE64 or @ref BDE_MODE_BASE64URL.
146 : : * @param[out] encoded_octets_cbl Number of encoded octets that generate complete decoded blocks, not including padding.
147 : : * @param[out] encoded_octets_lbl Number of octets in the last uncomplete decoded block, including padding.
148 : : * @param[out] encoded_octets_pad Number of padding characters in the encoded string.
149 : : * @param[out] decoded_octets Number of octets in the resulting decoded data.
150 : : * @retval ::bde_error_ok Success.
151 : : * @retval ::bde_error_encoded_string The encoded string provided is not a valid encoded string in terms of form.
152 : : * @note There are three octets in a decoded block, there are four octets in a encoded block.
153 : : * @note The value returned in @p encoded_octets_lbl must be zero for a valid Base64 encoded string, as the length
154 : : * of a valid Base64 encoded string is always a multiple of four.
155 : : * @note The value returned in @p encoded_octets_pad must be two or less for a valid Base64 encoded string, as it is not
156 : : * possible for a decoded block to have more than two padding characters to make a complete decoded block.
157 : : * @note The decoded octets length is only valid if the two conditions above for @p encoded_octets_lbl and
158 : : * @p encoded_octets_pad are met, this calculation is already performed by the function.
159 : : */
160 : : static bde_error_t bde_decode_lengths(const size_t encoded_len,
161 : : const bde_enc_t * const encoded,
162 : : const size_t mode,
163 : : size_t * const encoded_octets_cbl,
164 : : size_t * const encoded_octets_lbl,
165 : : size_t * const encoded_octets_pad,
166 : : size_t * const decoded_octets);
167 : :
168 : : /**
169 : : * @brief Decodes the given encoded elem.
170 : : * @param[in] encoded The decoded element to encode.
171 : : * @param[in] mode Operation mode, one of @ref BDE_MODE_BASE64 or @ref BDE_MODE_BASE64URL.
172 : : * @return The decoded element, or 0xFF if the encoded data is invalid.
173 : : */
174 : : static bde_dec_t bde_decode_elem(const bde_enc_t encoded, const size_t mode);
175 : :
176 : : /**
177 : : * @brief Decodes the given encoded string.
178 : : * @param[in] encoded The encoded string.
179 : : * @param[in] encoded_len The length of the encoded string, not including the @c NULL terminator.
180 : : * @param[in] mode Operation mode, one of @ref BDE_MODE_BASE64 or @ref BDE_MODE_BASE64URL.
181 : : * @param[in] decoded_max_len The length of the decoded buffer.
182 : : * @param[out] decoded The buffer where the decoded data will be written to.
183 : : * @param[out] decoded_len The length of the decoded data written to the decoded buffer, can be @c NULL if not required.
184 : : * @retval ::bde_error_ok Success.
185 : : * @retval ::bde_error_buffer_length The length of the decoded buffer is not enough for the decoded data.
186 : : * @retval ::bde_error_encoded_string The encoded string is invalid, it has invalid characters.
187 : : */
188 : : static bde_error_t bde_decode(const bde_enc_t * const encoded,
189 : : const size_t encoded_len,
190 : : const size_t mode,
191 : : const size_t decoded_max_len,
192 : : bde_dec_t * const decoded,
193 : : size_t * const decoded_len);
194 : :
195 : : /**
196 : : * @}
197 : : */
198 : :
199 : : /* Private functions -------------------------------------------------------------------------------------------------*/
200 : : /**
201 : : * @addtogroup bde_base64_iapi_impl
202 : : * @{
203 : : */
204 : :
205 : : /*--------------------------------------------------------------------------------------------------------------------*/
206 : 82 : static bde_error_t bde_encode_lengths(const size_t decoded_len,
207 : : const size_t mode,
208 : : size_t * const decoded_octets_cbl,
209 : : size_t * const decoded_octets_lbl,
210 : : size_t * const encoded_octets)
211 : : {
212 : : // Calculate the number of complete decoded blocks.
213 : 82 : size_t complete_decoded_blocks = decoded_len / 3U;
214 : :
215 : : // Calculate number of encoded octets that make complete decoded blocks.
216 : 82 : *decoded_octets_cbl = complete_decoded_blocks * 3U;
217 : :
218 : : // Calculate number of decoded octets that make the last block.
219 : 82 : *decoded_octets_lbl = decoded_len - (*decoded_octets_cbl);
220 : :
221 [ + + ]: 82 : if (mode == BDE_MODE_BASE64)
222 : : {
223 : : // Calculate length of the resultant Base64 encoded string, not including the terminator.
224 [ + + ]: 55 : *encoded_octets = (complete_decoded_blocks + (((*decoded_octets_lbl) > 0U) ? 1U : 0U)) * 4U;
225 : : }
226 : : else
227 : : {
228 : : // Calculate length of the resultant Base64URL encoded string, not including the terminator.
229 : 82 : *encoded_octets =
230 [ + + ]: 55 : (complete_decoded_blocks * 4U) + ((((*decoded_octets_lbl) > 0U) ? 1U : 0U) * ((*decoded_octets_lbl) + 1U));
231 : : }
232 : :
233 : 82 : return bde_error_ok;
234 : : }
235 : :
236 : : /*--------------------------------------------------------------------------------------------------------------------*/
237 : 456 : static bde_enc_t bde_encode_elem(const bde_dec_t decoded, const size_t mode)
238 : : {
239 : 456 : bde_enc_t encoded = 0U;
240 : :
241 : : // If using Base64, handle distinct characters in the alphabet.
242 [ + + ]: 456 : if (mode == BDE_MODE_BASE64)
243 : : {
244 [ + + ][ + ]: 228 : switch (decoded)
245 : : {
246 : : case 62U:
247 : : {
248 : : encoded = '+';
249 : : }
250 : : break;
251 : :
252 : 10 : case 63U:
253 : : {
254 : 10 : encoded = '/';
255 : : }
256 : 10 : break;
257 : :
258 : 210 : default:
259 : : {
260 : 210 : encoded = bde_base64_encode_alphabet_lut[decoded];
261 : : }
262 : 210 : break;
263 : : }
264 : : }
265 : : else
266 : : {
267 : 228 : encoded = bde_base64_encode_alphabet_lut[decoded];
268 : : }
269 : :
270 : 456 : return encoded;
271 : : }
272 : :
273 : : /*--------------------------------------------------------------------------------------------------------------------*/
274 : 56 : static bde_error_t bde_encode(const bde_dec_t * const decoded,
275 : : const size_t decoded_len,
276 : : const size_t mode,
277 : : const size_t encoded_max_len,
278 : : bde_enc_t * const encoded,
279 : : size_t * const encoded_len)
280 : : {
281 : : // Ensure the encoded string buffer given is big enough.
282 : 56 : size_t noct = 0U;
283 : 56 : size_t loct = 0U;
284 : 56 : size_t ooct = 0U;
285 [ + - ][ + + ]: 56 : if ((bde_encode_lengths(decoded_len, mode, &noct, &loct, &ooct) != bde_error_ok) || (encoded_max_len < (ooct + 1U)))
286 : : {
287 : : return bde_error_buffer_length;
288 : : }
289 : :
290 : : // Set pointers and others for reverse encoding.
291 : 54 : bde_enc_t * encoded_r = encoded + ooct;
292 : 54 : const bde_dec_t * decoded_r = decoded + decoded_len - 1U;
293 : :
294 : : // Write terminator character.
295 : 54 : *(encoded_r--) = '\0';
296 : :
297 : : // Handle last decoded block, if any, it can be one or two octets of data.
298 [ + + ][ + ]: 54 : switch (loct)
299 : : {
300 : 16 : case 2U:
301 : : {
302 [ + + ]: 16 : if (mode == BDE_MODE_BASE64)
303 : : {
304 : : // Write 4th encoded character of current encoded block.
305 : 8 : *(encoded_r--) = bde_base64_padding_char;
306 : : }
307 : : // Move backwards.
308 : 16 : decoded_r -= 2U;
309 : : // Write 3rd encoded character of current encoded block.
310 : 16 : *(encoded_r--) = bde_encode_elem((bde_dec_t)((decoded_r[2U] & 0x0FU) << 2U), mode);
311 : : // Write 2nd encoded character of current encoded block.
312 : 16 : *(encoded_r--) =
313 : 16 : bde_encode_elem((bde_dec_t)(((decoded_r[2U] & 0xF0U) >> 4U) | ((decoded_r[1U] & 0x03U) << 4U)), mode);
314 : : // Write 1st encoded character of current encoded block.
315 : 16 : *(encoded_r--) = bde_encode_elem((decoded_r[1U] & 0xFCU) >> 2U, mode);
316 : : }
317 : 16 : break;
318 : :
319 : 20 : case 1U:
320 : : {
321 [ + + ]: 20 : if (mode == BDE_MODE_BASE64)
322 : : {
323 : : // Write 4th encoded character of current encoded block.
324 : 10 : *(encoded_r--) = bde_base64_padding_char;
325 : : // Write 3rd encoded character of current encoded block.
326 : 10 : *(encoded_r--) = bde_base64_padding_char;
327 : : }
328 : : // Move backwards.
329 : 20 : decoded_r -= 1U;
330 : : // Write 2nd encoded character of current encoded block.
331 : 20 : *(encoded_r--) = bde_encode_elem((bde_dec_t)((decoded_r[1U] & 0x03U) << 4U), mode);
332 : : // Write 1st encoded character of current encoded block.
333 : 20 : *(encoded_r--) = bde_encode_elem((decoded_r[1U] & 0xFCU) >> 2U, mode);
334 : : }
335 : 20 : break;
336 : :
337 : : default:
338 : : {
339 : : // Will never get here, only present for MISRA compliance.
340 : : }
341 : : break;
342 : : }
343 : :
344 : : // Handle remaining decoded blocks, if any, all of which are three octets in size.
345 [ + + ]: 146 : while (decoded_r > decoded)
346 : : {
347 : : // Move backwards.
348 : 92 : decoded_r -= 3U;
349 : : // Write 4th encoded character of current encoded block.
350 : 92 : *(encoded_r--) = bde_encode_elem(decoded_r[3U] & 0x3FU, mode);
351 : : // Write 3rd encoded character of current encoded block.
352 : 92 : *(encoded_r--) =
353 : 92 : bde_encode_elem((bde_dec_t)(((decoded_r[3U] & 0xC0U) >> 6U) | ((decoded_r[2U] & 0x0FU) << 2U)), mode);
354 : : // Write 2nd encoded character of current encoded block.
355 : 92 : *(encoded_r--) =
356 : 92 : bde_encode_elem((bde_dec_t)(((decoded_r[2U] & 0xF0U) >> 4U) | ((decoded_r[1U] & 0x03U) << 4U)), mode);
357 : : // Write 1st encoded character of current encoded block.
358 : 92 : *(encoded_r--) = bde_encode_elem((decoded_r[1U] & 0xFCU) >> 2U, mode);
359 : : }
360 : :
361 : : // Return encoded string length if requested.
362 [ + + ]: 54 : if (encoded_len != NULL)
363 : : {
364 : 52 : *encoded_len = ooct;
365 : : }
366 : :
367 : : return bde_error_ok;
368 : : }
369 : :
370 : : /*--------------------------------------------------------------------------------------------------------------------*/
371 : 148 : static bde_error_t bde_decode_lengths(const size_t encoded_len,
372 : : const bde_enc_t * const encoded,
373 : : const size_t mode,
374 : : size_t * const encoded_octets_cbl,
375 : : size_t * const encoded_octets_lbl,
376 : : size_t * const encoded_octets_pad,
377 : : size_t * const decoded_octets)
378 : : {
379 : : // Calculate number of complete encoded blocks.
380 : 148 : size_t complete_encoded_blocks = encoded_len / 4U;
381 : :
382 : : // Calculate number of octets that create complete blocks.
383 : 148 : *encoded_octets_cbl = complete_encoded_blocks * 4U;
384 : :
385 : : // Calculate number of characters in last incomplete block, if any.
386 : 148 : *encoded_octets_lbl = encoded_len - (*encoded_octets_cbl);
387 : :
388 : 148 : *encoded_octets_pad = 0U;
389 [ + + ]: 148 : if (mode == BDE_MODE_BASE64)
390 : : {
391 : : // Get number of padding characters in the Base64 string, if the encoded string was given.
392 : : // Otherwise assume worst case in terms of decoded length, thus no padding characters.
393 [ + + ]: 85 : if (encoded != NULL)
394 : : {
395 [ + + ][ + + ]: 170 : for (size_t el = encoded_len - 1U; (el > 0U) && (encoded[el] == bde_base64_padding_char); el--)
396 : : {
397 : 89 : (*encoded_octets_pad)++;
398 : : }
399 : : }
400 : :
401 : : // The number of characters in the last block in a Base64 string can only be zero.
402 : : // The number of padding characters in the last block in a Base64 string can be zero, one or two.
403 [ + + ][ + + ]: 85 : if ((*encoded_octets_lbl != 0U) || (*encoded_octets_pad > 2U))
404 : : {
405 : : return bde_error_encoded_string;
406 : : }
407 : :
408 : : // Remove padding from number of useful octets in the encoded Base64 string.
409 : 55 : *encoded_octets_cbl -= *encoded_octets_pad;
410 : :
411 : : // Calculate number of octets in the decoded output.
412 : 55 : *decoded_octets = (complete_encoded_blocks * 3U) - (*encoded_octets_pad);
413 : : }
414 : : else
415 : : {
416 : : // Set the number of decoded octets from the complete encoded blocks.
417 : 63 : *decoded_octets = complete_encoded_blocks * 3U;
418 : :
419 [ + + ]: 63 : if (*encoded_octets_lbl > 0U)
420 : : {
421 : : // The number of characters in the last block of a Base64URL string can be zero, two or three.
422 [ + + ]: 39 : if (*encoded_octets_lbl == 1U)
423 : : {
424 : : return bde_error_encoded_string;
425 : : }
426 : :
427 : : // Calculate number of padding characters in the Base64URL string.
428 : 31 : *encoded_octets_pad = 4U - *encoded_octets_lbl;
429 : :
430 : : // Add characters in last block to number of useful octets in the encoded Base64URL string.
431 : 31 : *encoded_octets_cbl += *encoded_octets_lbl;
432 : :
433 : : // Add number of decodec octets from the last complete encoded block.
434 : 31 : *decoded_octets += *encoded_octets_lbl - 1U;
435 : : }
436 : : }
437 : :
438 : : return bde_error_ok;
439 : : }
440 : :
441 : : /*--------------------------------------------------------------------------------------------------------------------*/
442 : 588 : static bde_dec_t bde_decode_elem(const bde_enc_t encoded, const size_t mode)
443 : : {
444 : 588 : const uint8_t encoded_r = (const uint8_t)encoded;
445 : 588 : bde_dec_t decoded = 0U;
446 : :
447 : : // Check that the encoded data is within range.
448 [ + + ]: 588 : if ((encoded_r < 43U) || (encoded_r > 122U))
449 : : {
450 : : return 0xFFU;
451 : : }
452 : :
453 : : // If using Base64, handle distinct characters in the alphabet.
454 [ + + ]: 580 : if (mode == BDE_MODE_BASE64)
455 : : {
456 [ + + ][ + + ]: 270 : switch (encoded_r)
457 : : {
458 : : case '+':
459 : : {
460 : : decoded = 62U;
461 : : }
462 : : break;
463 : :
464 : 10 : case '/':
465 : : {
466 : 10 : decoded = 63U;
467 : : }
468 : 10 : break;
469 : :
470 : 6 : case '_':
471 : : case '-':
472 : : {
473 : 6 : decoded = 0xFFU;
474 : : }
475 : 6 : break;
476 : :
477 : 246 : default:
478 : : {
479 : 246 : decoded = bde_base64_decode_alphabet_lut[encoded_r - 43U];
480 : : }
481 : 246 : break;
482 : : }
483 : : }
484 : : else
485 : : {
486 : 310 : decoded = bde_base64_decode_alphabet_lut[encoded_r - 43U];
487 : : }
488 : :
489 : : return decoded;
490 : : }
491 : :
492 : : /*--------------------------------------------------------------------------------------------------------------------*/
493 : 96 : static bde_error_t bde_decode(const bde_enc_t * const encoded,
494 : : const size_t encoded_len,
495 : : const size_t mode,
496 : : const size_t decoded_max_len,
497 : : bde_dec_t * const decoded,
498 : : size_t * const decoded_len)
499 : : {
500 : : // Get lengths.
501 : 96 : size_t noct = 0U;
502 : 96 : size_t loct = 0U;
503 : 96 : size_t ooct = 0U;
504 : 96 : size_t poct = 0U;
505 : 96 : bde_error_t res = bde_decode_lengths(encoded_len, encoded, mode, &noct, &loct, &poct, &ooct);
506 [ + + ]: 96 : if (res != bde_error_ok)
507 : : {
508 : : return res;
509 : : }
510 : :
511 : : // Ensure the decoded data buffer given is big enough for the encoded string.
512 [ + + ]: 77 : if (ooct > decoded_max_len)
513 : : {
514 : : return bde_error_buffer_length;
515 : : }
516 : :
517 : : // Decode complete blocks, if any.
518 : 75 : const bde_enc_t * encoded_r = encoded;
519 : 75 : bde_dec_t * decoded_r = decoded;
520 : 75 : const bde_enc_t * const encoded_e = encoded + noct;
521 [ + + ]: 182 : while ((encoded_e - encoded_r) >= 4U)
522 : : {
523 : 120 : uint32_t enc =
524 : 120 : (uint32_t)((bde_decode_elem(encoded_r[0U], mode) << 24U) | (bde_decode_elem(encoded_r[1U], mode) << 16U) |
525 : 120 : (bde_decode_elem(encoded_r[2U], mode) << 8U) | (bde_decode_elem(encoded_r[3U], mode)));
526 [ + + ]: 120 : if ((enc & 0x80808080U) > 0U)
527 : : {
528 : : return bde_error_encoded_string;
529 : : }
530 : :
531 : : // Handle 1st octet of current decoded block.
532 : 107 : *(decoded_r++) = ((enc & 0x3F000000U) >> 22U) | ((enc & 0x00300000U) >> 20U);
533 : : // Handle 2nd octet of current decoded block.
534 : 107 : *(decoded_r++) = ((enc & 0x000F0000U) >> 12U) | ((enc & 0x0003C00U) >> 10U);
535 : : // Handle 3rd octet of current decoded block.
536 : 107 : *(decoded_r++) = ((enc & 0x00000300U) >> 2U) | (enc & 0x000003FU);
537 : : // Move pointer forwards.
538 : 107 : encoded_r += 4U;
539 : : }
540 : :
541 : : // Handle last block with the padding, if it exists.
542 [ + + ][ + ]: 62 : switch (poct)
543 : : {
544 : 24 : case 2U:
545 : : {
546 : 24 : uint16_t enc =
547 : 24 : (uint16_t)((bde_decode_elem(encoded_r[0U], mode) << 8U) | (bde_decode_elem(encoded_r[1U], mode)));
548 [ + + ]: 24 : if ((enc & 0x8080U) > 0U)
549 : : {
550 : : return bde_error_encoded_string;
551 : : }
552 : :
553 : : // Handle 1st octet of current decoded block.
554 : 20 : *(decoded_r++) = ((enc & 0x3F00U) >> 6U) | ((enc & 0x0030U) >> 4U);
555 : : // Do not move pointer forwards as it will never be read at this point.
556 : : }
557 : 20 : break;
558 : :
559 : 20 : case 1U:
560 : : {
561 : 20 : uint32_t enc =
562 : 20 : (uint32_t)((bde_decode_elem(encoded_r[0U], mode) << 16U) |
563 : 20 : (bde_decode_elem(encoded_r[1U], mode) << 8U) | (bde_decode_elem(encoded_r[2U], mode)));
564 [ + + ]: 20 : if ((enc & 0x808080U) > 0U)
565 : : {
566 : : return bde_error_encoded_string;
567 : : }
568 : :
569 : : // Handle 1st octet of current decoded block.
570 : 16 : *(decoded_r++) = ((enc & 0x003F0000U) >> 14U) | ((enc & 0x00003000U) >> 12U);
571 : : // Handle 2st octet of current decoded block.
572 : 16 : *(decoded_r++) = ((enc & 0x00000F00U) >> 4U) | ((enc & 0x0000003CU) >> 2U);
573 : : // Do not move pointer forwards as it will never be read at this point.
574 : : }
575 : 16 : break;
576 : :
577 : : default:
578 : : {
579 : : // Will never get here, present for MISRA compliance.
580 : : }
581 : : break;
582 : : }
583 : :
584 : : // Store length of decoded data if requested.
585 [ + + ]: 54 : if (decoded_len != NULL)
586 : : {
587 : 52 : *decoded_len = ooct;
588 : : }
589 : :
590 : : return bde_error_ok;
591 : : }
592 : :
593 : : /**
594 : : * @}
595 : : */
596 : :
597 : : /* Exported functions ------------------------------------------------------------------------------------------------*/
598 : : /**
599 : : * @addtogroup bde_base64_papi_impl
600 : : * @{
601 : : */
602 : :
603 : : /*--------------------------------------------------------------------------------------------------------------------*/
604 : 15 : bde_error_t bde_base64_encode_length(const size_t decoded_len, size_t * const encoded_len)
605 : : {
606 [ + + ]: 15 : if ((decoded_len == 0U) || (encoded_len == NULL))
607 : : {
608 : : return bde_error_args;
609 : : }
610 : :
611 : 13 : return bde_encode_lengths(decoded_len, BDE_MODE_BASE64, encoded_len, encoded_len, encoded_len);
612 : : }
613 : :
614 : : /*--------------------------------------------------------------------------------------------------------------------*/
615 : 32 : bde_error_t bde_base64_encode(const bde_dec_t * const decoded,
616 : : const size_t decoded_len,
617 : : const size_t encoded_max_len,
618 : : bde_enc_t * const encoded,
619 : : size_t * const encoded_len)
620 : : {
621 [ + + ][ + + ]: 32 : if ((decoded == NULL) || (decoded_len == 0U) || (encoded_max_len == 0U) || (encoded == NULL))
622 : : {
623 : : return bde_error_args;
624 : : }
625 : :
626 : 28 : return bde_encode(decoded, decoded_len, BDE_MODE_BASE64, encoded_max_len, encoded, encoded_len);
627 : : }
628 : :
629 : : /*--------------------------------------------------------------------------------------------------------------------*/
630 : : bde_error_t
631 : 37 : bde_base64_decode_length(const bde_enc_t * const encoded, const size_t encoded_len, size_t * const decoded_len)
632 : : {
633 [ + + ]: 37 : if ((encoded_len == 0U) || (decoded_len == NULL))
634 : : {
635 : : return bde_error_args;
636 : : }
637 : :
638 : 35 : size_t un0 = 0U;
639 : 35 : size_t un1 = 0U;
640 : 35 : size_t un2 = 0U;
641 : 35 : return bde_decode_lengths(encoded_len, encoded, BDE_MODE_BASE64, &un0, &un1, &un2, decoded_len);
642 : : }
643 : :
644 : : /*--------------------------------------------------------------------------------------------------------------------*/
645 : 54 : bde_error_t bde_base64_decode(const bde_enc_t * const encoded,
646 : : const size_t encoded_len,
647 : : const size_t decoded_max_len,
648 : : bde_dec_t * const decoded,
649 : : size_t * const decoded_len)
650 : : {
651 [ + + ][ + + ]: 54 : if ((encoded == NULL) || (encoded_len == 0U) || (decoded_max_len == 0U) || (decoded == NULL))
652 : : {
653 : : return bde_error_args;
654 : : }
655 : :
656 : 50 : return bde_decode(encoded, encoded_len, BDE_MODE_BASE64, decoded_max_len, decoded, decoded_len);
657 : : }
658 : :
659 : : /*--------------------------------------------------------------------------------------------------------------------*/
660 : 15 : bde_error_t bde_base64url_encode_length(const size_t decoded_len, size_t * const encoded_len)
661 : : {
662 [ + + ]: 15 : if ((decoded_len == 0U) || (encoded_len == NULL))
663 : : {
664 : : return bde_error_args;
665 : : }
666 : :
667 : 13 : return bde_encode_lengths(decoded_len, BDE_MODE_BASE64URL, encoded_len, encoded_len, encoded_len);
668 : : }
669 : :
670 : : /*--------------------------------------------------------------------------------------------------------------------*/
671 : 32 : bde_error_t bde_base64url_encode(const bde_dec_t * const decoded,
672 : : const size_t decoded_len,
673 : : const size_t encoded_max_len,
674 : : bde_enc_t * const encoded,
675 : : size_t * const encoded_len)
676 : : {
677 [ + + ][ + + ]: 32 : if ((decoded == NULL) || (decoded_len == 0U) || (encoded_max_len == 0U) || (encoded == NULL))
678 : : {
679 : : return bde_error_args;
680 : : }
681 : :
682 : 28 : return bde_encode(decoded, decoded_len, BDE_MODE_BASE64URL, encoded_max_len, encoded, encoded_len);
683 : : }
684 : :
685 : : /*--------------------------------------------------------------------------------------------------------------------*/
686 : 19 : bde_error_t bde_base64url_decode_length(const size_t encoded_len, size_t * const decoded_len)
687 : : {
688 [ + + ]: 19 : if ((encoded_len == 0U) || (decoded_len == NULL))
689 : : {
690 : : return bde_error_args;
691 : : }
692 : :
693 : 17 : size_t un0 = 0U;
694 : 17 : size_t un1 = 0U;
695 : 17 : size_t un2 = 0U;
696 : 17 : return bde_decode_lengths(encoded_len, NULL, BDE_MODE_BASE64URL, &un0, &un1, &un2, decoded_len);
697 : : }
698 : :
699 : : /*--------------------------------------------------------------------------------------------------------------------*/
700 : 50 : bde_error_t bde_base64url_decode(const bde_enc_t * const encoded,
701 : : const size_t encoded_len,
702 : : const size_t decoded_max_len,
703 : : bde_dec_t * const decoded,
704 : : size_t * const decoded_len)
705 : : {
706 [ + + ][ + + ]: 50 : if ((encoded == NULL) || (encoded_len == 0U) || (decoded_max_len == 0U) || (decoded == NULL))
707 : : {
708 : : return bde_error_args;
709 : : }
710 : :
711 : 46 : return bde_decode(encoded, encoded_len, BDE_MODE_BASE64URL, decoded_max_len, decoded, decoded_len);
712 : : }
713 : :
714 : : /**
715 : : * @}
716 : : */
717 : :
718 : : /******************************************************************************************************END OF FILE*****/
|