suricata
util-base64.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-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 /**
19  * \file
20  *
21  * \author David Abarbanel <david.abarbanel@baesystems.com>
22  *
23  */
24 
25 #include "util-base64.h"
26 #include "util-debug.h"
27 #include "util-validate.h"
28 #include "util-unittest.h"
29 /* Constants */
30 #define BASE64_TABLE_MAX 122
31 
32 /* Base64 character to index conversion table */
33 /* Characters are mapped as "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" */
34 static const int b64table[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
35  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
36  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
37  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
38  -1, -1, -1, 62, -1, -1, -1, 63, 52, 53,
39  54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
40  -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
41  5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
42  15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
43  25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
44  29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
45  39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
46  49, 50, 51 };
47 
48 /**
49  * \brief Gets a base64-decoded value from an encoded character
50  *
51  * \param c The encoded character
52  *
53  * \return The decoded value (0 or above), or -1 if the parameter is invalid
54  */
55 static inline int GetBase64Value(uint8_t c)
56 {
57  int val = -1;
58 
59  /* Pull from conversion table */
60  if (c <= BASE64_TABLE_MAX) {
61  val = b64table[(int) c];
62  }
63 
64  return val;
65 }
66 
67 /**
68  * \brief Checks if the given char in a byte array is Base64 alphabet
69  *
70  * \param Char that needs to be checked
71  *
72  * \return True if the char was Base64 alphabet, False otherwise
73  */
74 bool IsBase64Alphabet(uint8_t encoded_byte)
75 {
76  if (GetBase64Value(encoded_byte) < 0 && encoded_byte != '=') {
77  return false;
78  }
79  return true;
80 }
81 
82 /**
83  * \brief Decodes a 4-byte base64-encoded block into a 3-byte ascii-encoded block
84  *
85  * \param ascii the 3-byte ascii output block
86  * \param b64 the 4-byte base64 input block
87  *
88  * \return none
89  */
90 static inline void DecodeBase64Block(uint8_t ascii[ASCII_BLOCK], uint8_t b64[B64_BLOCK])
91 {
92  ascii[0] = (uint8_t) (b64[0] << 2) | (b64[1] >> 4);
93  ascii[1] = (uint8_t) (b64[1] << 4) | (b64[2] >> 2);
94  ascii[2] = (uint8_t) (b64[2] << 6) | (b64[3]);
95 }
96 
97 /**
98  * \brief Decode a base64 encoded string as per RFC 2045.
99  * RFC 2045 states that any characters that do not fall under the Base64
100  * alphabet must be skipped by the decoding software.
101  * Following are some important considerations:
102  * 1. This Decoding algorithm is used by MIME parser currently.
103  * 2. The number of decoded bytes are constrained by the destination buffer size.
104  * 3. The leftover bytes are not handled by the decoder but the caller.
105  *
106  * \param dest destination buffer
107  * \param dest_size destination buffer size
108  * \param src base64 encoded string
109  * \param len length of the base64 encoded string
110  * \param consumed_bytes number of bytes successfully consumed by the decoder
111  * \param decoded_bytes number of bytes successfully decoded by the decoder
112  *
113  * \return Base64Ecode BASE64_ECODE_OK if all went well
114  * BASE64_ECODE_BUF if destination buffer got full before all could be decoded
115  */
116 static inline Base64Ecode DecodeBase64RFC2045(uint8_t *dest, uint32_t dest_size, const uint8_t *src,
117  uint32_t len, uint32_t *consumed_bytes, uint32_t *decoded_bytes)
118 {
119  int val;
120  uint32_t padding = 0, bbidx = 0, non_b64_chars = 0;
121  uint8_t *dptr = dest;
122  uint8_t b64[B64_BLOCK] = { 0, 0, 0, 0 };
123 
124  for (uint32_t i = 0; i < len; i++) {
125  val = GetBase64Value(src[i]);
126  if (val < 0) {
127  if (src[i] != '=') {
128  non_b64_chars++;
129  continue;
130  } else {
131  padding++;
132  }
133  }
134 
135  /* For each alpha-numeric letter in the source array, find the numeric value */
136  b64[bbidx++] = val > 0 ? (uint8_t)val : 0;
137 
138  /* Decode every 4 base64 bytes into 3 ascii bytes */
139  if (bbidx == B64_BLOCK) {
140  /* For every 4 bytes, add 3 bytes but deduct the '=' padded blocks */
141  uint32_t numDecoded_blk = ASCII_BLOCK - (padding < B64_BLOCK ? padding : ASCII_BLOCK);
142  if (dest_size - *decoded_bytes < ASCII_BLOCK)
143  return BASE64_ECODE_BUF;
144  /* Decode base-64 block into ascii block and move pointer */
145  DecodeBase64Block(dptr, b64);
146  dptr += numDecoded_blk;
147  *decoded_bytes += numDecoded_blk;
148  /* Reset base-64 block and index */
149  bbidx = 0;
150  padding = 0;
151  *consumed_bytes += B64_BLOCK + non_b64_chars;
152  non_b64_chars = 0;
153  memset(&b64, 0, sizeof(b64));
154  }
155  }
156 
157  DEBUG_VALIDATE_BUG_ON(*consumed_bytes > len);
159  /* Any leftover bytes must be handled by the caller */
160  return BASE64_ECODE_OK;
161 }
162 
163 /**
164  * \brief Decode a base64 encoded string as per RFC 4648.
165  * RFC 4648 states that if a character is encountered that does not fall under
166  * the Base64 alphabet, the decoding software should stop processing the string further.
167  * Following are some important considerations:
168  * 1. This Decoding algorithm is used by base64_decode keyword currently.
169  * 2. This Decoding algorithm in strict mode is used by datasets currently.
170  * 3. The number of decoded bytes are constrained by the destination buffer size.
171  * 4. The leftover bytes are handled by the decoder.
172  *
173  * \param dest destination buffer
174  * \param dest_size destination buffer size
175  * \param src base64 encoded string
176  * \param len length of the base64 encoded string
177  * \param consumed_bytes number of bytes successfully consumed by the decoder
178  * \param decoded_bytes number of bytes successfully decoded by the decoder
179  * \param strict whether an invalid base64 encoding should be strictly rejected
180  *
181  * \return Base64Ecode BASE64_ECODE_OK if all went well
182  * BASE64_ECODE_BUF if destination buffer got full before all could be decoded
183  * BASE64_ECODE_ERR if an invalid char was found in strict mode or nothing was
184  * decoded
185  */
186 static inline Base64Ecode DecodeBase64RFC4648(uint8_t *dest, uint32_t dest_size, const uint8_t *src,
187  uint32_t len, uint32_t *consumed_bytes, uint32_t *decoded_bytes, bool strict)
188 {
189  int val;
190  uint32_t padding = 0, bbidx = 0;
191  uint8_t *dptr = dest;
192  uint8_t b64[B64_BLOCK] = { 0, 0, 0, 0 };
193 
194  for (uint32_t i = 0; i < len; i++) {
195  val = GetBase64Value(src[i]);
196  if (val < 0) {
197  if (src[i] != '=') {
198  if (strict) {
199  *decoded_bytes = 0;
200  return BASE64_ECODE_ERR;
201  }
202  break;
203  }
204  padding++;
205  }
206  /* For each alpha-numeric letter in the source array, find the numeric value */
207  b64[bbidx++] = (val > 0 ? (uint8_t)val : 0);
208 
209  /* Decode every 4 base64 bytes into 3 ascii bytes */
210  if (bbidx == B64_BLOCK) {
211  /* For every 4 bytes, add 3 bytes but deduct the '=' padded blocks */
212  uint32_t numDecoded_blk = ASCII_BLOCK - (padding < B64_BLOCK ? padding : ASCII_BLOCK);
213  if (dest_size - *decoded_bytes < ASCII_BLOCK)
214  return BASE64_ECODE_BUF;
215 
216  /* Decode base-64 block into ascii block and move pointer */
217  DecodeBase64Block(dptr, b64);
218  dptr += numDecoded_blk;
219  *decoded_bytes += numDecoded_blk;
220  /* Reset base-64 block and index */
221  bbidx = 0;
222  padding = 0;
223  *consumed_bytes += B64_BLOCK;
224  memset(&b64, 0, sizeof(b64));
225  }
226  }
227 
229 
230  /* Handle any leftover bytes by adding padding to them as long as they do not
231  * violate the destination buffer size */
232  if (bbidx > 0) {
233  /*
234  * --------------------
235  * | bbidx | padding |
236  * --------------------
237  * | 1 | 2 |
238  * | 2 | 2 |
239  * | 3 | 1 |
240  * --------------------
241  * Note: Padding for 1 byte is set to 2 to have at least one
242  * decoded byte while calculating numDecoded_blk
243  * This does not affect the decoding as the b64 array is already
244  * populated with all padding bytes unless overwritten.
245  * */
246  padding = bbidx > 1 ? B64_BLOCK - bbidx : 2;
247  uint32_t numDecoded_blk = ASCII_BLOCK - padding;
248  if (dest_size - *decoded_bytes < ASCII_BLOCK)
249  return BASE64_ECODE_BUF;
250  /* Decode base-64 block into ascii block and move pointer */
251  DecodeBase64Block(dptr, b64);
252  *decoded_bytes += numDecoded_blk;
253  /* Consumed bytes should not have the padding bytes added by us */
254  *consumed_bytes += bbidx;
255  }
256  if (*decoded_bytes == 0)
257  return BASE64_ECODE_ERR;
258 
259  DEBUG_VALIDATE_BUG_ON(*consumed_bytes > len);
260  return BASE64_ECODE_OK;
261 }
262 
263 /**
264  * \brief Decodes a base64-encoded string buffer into an ascii-encoded byte buffer
265  *
266  * \param dest The destination byte buffer
267  * \param dest_size The destination byte buffer size
268  * \param src The source string
269  * \param len The length of the source string
270  * \param consumed_bytes The bytes that were actually processed/consumed
271  * \param decoded_bytes The bytes that were decoded
272  * \param mode The mode in which decoding should happen
273  *
274  * \return Error code indicating success or failures with parsing
275  */
276 Base64Ecode DecodeBase64(uint8_t *dest, uint32_t dest_size, const uint8_t *src, uint32_t len,
277  uint32_t *consumed_bytes, uint32_t *decoded_bytes, DetectBase64Mode mode)
278 {
279  *decoded_bytes = 0;
281  switch (mode) {
282  case Base64ModeRFC4648:
283  ret = DecodeBase64RFC4648(
284  dest, dest_size, src, len, consumed_bytes, decoded_bytes, false);
285  break;
286  case Base64ModeRFC2045:
287  ret = DecodeBase64RFC2045(dest, dest_size, src, len, consumed_bytes, decoded_bytes);
288  break;
289  case Base64ModeStrict:
290  ret = DecodeBase64RFC4648(
291  dest, dest_size, src, len, consumed_bytes, decoded_bytes, true);
292  break;
293  default:
294  return BASE64_ECODE_ERR;
295  }
296  return ret;
297 }
298 
299 #ifdef UNITTESTS
300 
301 #define TEST_RFC2045(src, fin_str, dest_size, exp_decoded, exp_consumed, ecode) \
302  { \
303  uint32_t consumed_bytes = 0, num_decoded = 0; \
304  uint8_t dst[dest_size]; \
305  Base64Ecode code = DecodeBase64(dst, dest_size, (const uint8_t *)src, strlen(src), \
306  &consumed_bytes, &num_decoded, Base64ModeRFC2045); \
307  FAIL_IF(code != ecode); \
308  FAIL_IF(memcmp(dst, fin_str, strlen(fin_str)) != 0); \
309  FAIL_IF(num_decoded != exp_decoded); \
310  FAIL_IF(consumed_bytes != exp_consumed); \
311  }
312 
313 #define TEST_RFC4648(src, fin_str, dest_size, exp_decoded, exp_consumed, ecode) \
314  { \
315  uint32_t consumed_bytes = 0, num_decoded = 0; \
316  uint8_t dst[dest_size]; \
317  Base64Ecode code = DecodeBase64(dst, dest_size, (const uint8_t *)src, strlen(src), \
318  &consumed_bytes, &num_decoded, Base64ModeRFC4648); \
319  FAIL_IF(code != ecode); \
320  FAIL_IF(memcmp(dst, fin_str, strlen(fin_str)) != 0); \
321  FAIL_IF(num_decoded != exp_decoded); \
322  FAIL_IF(consumed_bytes != exp_consumed); \
323  }
324 
325 static int B64DecodeCompleteString(void)
326 {
327  /*
328  * SGVsbG8gV29ybGR6 : Hello Worldz
329  * */
330  const char *src = "SGVsbG8gV29ybGR6";
331  const char *fin_str = "Hello Worldz";
332  TEST_RFC2045(src, fin_str, 12, 12, 16, BASE64_ECODE_OK);
333  PASS;
334 }
335 
336 static int B64DecodeInCompleteString(void)
337 {
338  /*
339  * SGVsbG8gV29ybGR6 : Hello Worldz
340  * */
341  const char *src = "SGVsbG8gV29ybGR";
342  const char *fin_str = "Hello Wor";
343  TEST_RFC2045(src, fin_str, 9, 9, 12, BASE64_ECODE_OK);
344  PASS;
345 }
346 
347 static int B64DecodeCompleteStringWSp(void)
348 {
349  /*
350  * SGVsbG8gV29ybGQ= : Hello World
351  * */
352 
353  const char *src = "SGVs bG8 gV29y bGQ=";
354  const char *fin_str = "Hello World";
355  TEST_RFC2045(src, fin_str, 14, 11, 19, BASE64_ECODE_OK);
356  PASS;
357 }
358 
359 static int B64DecodeInCompleteStringWSp(void)
360 {
361  /*
362  * SGVsbG8gV29ybGQ= : Hello World
363  * Special handling for this case (sp in remainder) done in ProcessBase64Remainder
364  * */
365 
366  const char *src = "SGVs bG8 gV29y bGQ";
367  const char *fin_str = "Hello Wor";
368  TEST_RFC2045(src, fin_str, 9, 9, 14, BASE64_ECODE_OK);
369  PASS;
370 }
371 
372 static int B64DecodeStringBiggerThanBuffer(void)
373 {
374  /*
375  * SGVsbG8gV29ybGQ= : Hello World
376  * */
377 
378  const char *src = "SGVs bG8 gV29y bGQ=";
379  const char *fin_str = "Hello Wor";
380  TEST_RFC2045(src, fin_str, 10, 9, 14, BASE64_ECODE_BUF);
381  PASS;
382 }
383 
384 static int B64DecodeStringEndingSpaces(void)
385 {
386  const char *src = "0YPhA d H";
387  uint32_t consumed_bytes = 0, num_decoded = 0;
388  uint8_t dst[10];
389  Base64Ecode code = DecodeBase64(dst, sizeof(dst), (const uint8_t *)src, 9, &consumed_bytes,
390  &num_decoded, Base64ModeRFC2045);
391  FAIL_IF(code != BASE64_ECODE_OK);
392  FAIL_IF(num_decoded != 3);
393  FAIL_IF(consumed_bytes != 4);
394  PASS;
395 }
396 
397 static int B64TestVectorsRFC2045(void)
398 {
399  const char *src1 = "";
400  const char *fin_str1 = "";
401 
402  const char *src2 = "Zg==";
403  const char *fin_str2 = "f";
404 
405  const char *src3 = "Zm8=";
406  const char *fin_str3 = "fo";
407 
408  const char *src4 = "Zm9v";
409  const char *fin_str4 = "foo";
410 
411  const char *src5 = "Zm9vYg==";
412  const char *fin_str5 = "foob";
413 
414  const char *src6 = "Zm9vYmE=";
415  const char *fin_str6 = "fooba";
416 
417  const char *src7 = "Zm9vYmFy";
418  const char *fin_str7 = "foobar";
419 
420  const char *src8 = "Zm 9v Ym Fy";
421  const char *fin_str8 = "foobar";
422 
423  const char *src9 = "Zm$9vYm.Fy";
424  const char *fin_str9 = "foobar";
425 
426  const char *src10 = "Y21Wd2IzSjBaVzFoYVd4bWNtRjFaRUJoZEc4dVoyOTJMbUYxOmpqcHh4b3Rhb2w%5";
427  const char *fin_str10 = "cmVwb3J0ZW1haWxmcmF1ZEBhdG8uZ292LmF1:jjpxxotaol9";
428 
429  const char *src11 = "Zm 9v Ym Fy 7fy";
430  const char *fin_str11 = "foobar";
431 
432  TEST_RFC2045(src1, fin_str1, ASCII_BLOCK * 2, strlen(fin_str1), strlen(src1), BASE64_ECODE_OK);
433  TEST_RFC2045(src2, fin_str2, ASCII_BLOCK * 2, strlen(fin_str2), strlen(src2), BASE64_ECODE_OK);
434  TEST_RFC2045(src3, fin_str3, ASCII_BLOCK * 2, strlen(fin_str3), strlen(src3), BASE64_ECODE_OK);
435  TEST_RFC2045(src4, fin_str4, ASCII_BLOCK * 2, strlen(fin_str4), strlen(src4), BASE64_ECODE_OK);
436  TEST_RFC2045(src5, fin_str5, ASCII_BLOCK * 2, strlen(fin_str5), strlen(src5), BASE64_ECODE_OK);
437  TEST_RFC2045(src6, fin_str6, ASCII_BLOCK * 2, strlen(fin_str6), strlen(src6), BASE64_ECODE_OK);
438  TEST_RFC2045(src7, fin_str7, ASCII_BLOCK * 2, strlen(fin_str7), strlen(src7), BASE64_ECODE_OK);
439  TEST_RFC2045(src8, fin_str8, ASCII_BLOCK * 2, strlen(fin_str8), strlen(src8), BASE64_ECODE_OK);
440  TEST_RFC2045(src9, fin_str9, ASCII_BLOCK * 2, strlen(fin_str9), strlen(src9), BASE64_ECODE_OK);
441  TEST_RFC2045(src10, fin_str10, 50, 48, 65, BASE64_ECODE_OK);
442  TEST_RFC2045(src11, fin_str11, ASCII_BLOCK * 2, 6, 11, BASE64_ECODE_OK);
443  PASS;
444 }
445 
446 static int B64TestVectorsRFC4648(void)
447 {
448  const char *src1 = "";
449  const char *fin_str1 = "";
450 
451  const char *src2 = "Zg==";
452  const char *fin_str2 = "f";
453 
454  const char *src3 = "Zm8=";
455  const char *fin_str3 = "fo";
456 
457  const char *src4 = "Zm9v";
458  const char *fin_str4 = "foo";
459 
460  const char *src5 = "Zm9vYg==";
461  const char *fin_str5 = "foob";
462 
463  const char *src6 = "Zm9vYmE=";
464  const char *fin_str6 = "fooba";
465 
466  const char *src7 = "Zm9vYmFy";
467  const char *fin_str7 = "foobar";
468 
469  const char *src8 = "Zm 9v Ym Fy";
470  const char *fin_str8 = "f";
471 
472  const char *src9 = "Zm$9vYm.Fy";
473  const char *fin_str9 = "f";
474 
475  const char *src10 = "Y21Wd2IzSjBaVzFoYVd4bWNtRjFaRUJoZEc4dVoyOTJMbUYxOmpqcHh4b3Rhb2w%3D";
476  const char *fin_str10 = "cmVwb3J0ZW1haWxmcmF1ZEBhdG8uZ292LmF1:jjpxxotaol";
477 
478  const char *src11 = "Zm9vYg==";
479  const char *fin_str11 = "foo";
480 
481  TEST_RFC4648(src1, fin_str1, ASCII_BLOCK * 2, strlen(fin_str1), strlen(src1), BASE64_ECODE_ERR);
482  TEST_RFC4648(src2, fin_str2, ASCII_BLOCK * 2, strlen(fin_str2), strlen(src2), BASE64_ECODE_OK);
483  TEST_RFC4648(src3, fin_str3, ASCII_BLOCK * 2, strlen(fin_str3), strlen(src3), BASE64_ECODE_OK);
484  TEST_RFC4648(src4, fin_str4, ASCII_BLOCK * 2, strlen(fin_str4), strlen(src4), BASE64_ECODE_OK);
485  TEST_RFC4648(src5, fin_str5, ASCII_BLOCK * 2, strlen(fin_str5), strlen(src5), BASE64_ECODE_OK);
486  TEST_RFC4648(src6, fin_str6, ASCII_BLOCK * 2, strlen(fin_str6), strlen(src6), BASE64_ECODE_OK);
487  TEST_RFC4648(src7, fin_str7, ASCII_BLOCK * 2, strlen(fin_str7), strlen(src7), BASE64_ECODE_OK);
488  TEST_RFC4648(src8, fin_str8, ASCII_BLOCK * 2, 1 /* f */, 2 /* Zm */, BASE64_ECODE_OK);
489  TEST_RFC4648(src9, fin_str9, ASCII_BLOCK * 2, 1 /* f */, 2 /* Zm */, BASE64_ECODE_OK);
490  TEST_RFC4648(src10, fin_str10, 48, 47, 63, BASE64_ECODE_OK);
491  TEST_RFC4648(src11, fin_str11, 3, 3, 4, BASE64_ECODE_BUF);
492  PASS;
493 }
494 
496 {
497  UtRegisterTest("B64DecodeCompleteStringWSp", B64DecodeCompleteStringWSp);
498  UtRegisterTest("B64DecodeInCompleteStringWSp", B64DecodeInCompleteStringWSp);
499  UtRegisterTest("B64DecodeCompleteString", B64DecodeCompleteString);
500  UtRegisterTest("B64DecodeInCompleteString", B64DecodeInCompleteString);
501  UtRegisterTest("B64DecodeStringBiggerThanBuffer", B64DecodeStringBiggerThanBuffer);
502  UtRegisterTest("B64DecodeStringEndingSpaces", B64DecodeStringEndingSpaces);
503  UtRegisterTest("B64TestVectorsRFC2045", B64TestVectorsRFC2045);
504  UtRegisterTest("B64TestVectorsRFC4648", B64TestVectorsRFC4648);
505 }
506 #endif
BASE64_ECODE_BUF
@ BASE64_ECODE_BUF
Definition: util-base64.h:38
len
uint8_t len
Definition: app-layer-dnp3.h:2
TEST_RFC4648
#define TEST_RFC4648(src, fin_str, dest_size, exp_decoded, exp_consumed, ecode)
Definition: util-base64.c:313
BASE64_TABLE_MAX
#define BASE64_TABLE_MAX
Definition: util-base64.c:30
BASE64_ECODE_ERR
@ BASE64_ECODE_ERR
Definition: util-base64.h:36
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
util-base64.h
util-unittest.h
util-debug.h
DecodeBase64
Base64Ecode DecodeBase64(uint8_t *dest, uint32_t dest_size, const uint8_t *src, uint32_t len, uint32_t *consumed_bytes, uint32_t *decoded_bytes, DetectBase64Mode mode)
Decodes a base64-encoded string buffer into an ascii-encoded byte buffer.
Definition: util-base64.c:276
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
padding
uint32_t padding
Definition: decode-erspan.h:2
IsBase64Alphabet
bool IsBase64Alphabet(uint8_t encoded_byte)
Checks if the given char in a byte array is Base64 alphabet.
Definition: util-base64.c:74
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
Base64RegisterTests
void Base64RegisterTests(void)
Definition: util-base64.c:495
BASE64_ECODE_OK
@ BASE64_ECODE_OK
Definition: util-base64.h:37
util-validate.h
TEST_RFC2045
#define TEST_RFC2045(src, fin_str, dest_size, exp_decoded, exp_consumed, ecode)
Definition: util-base64.c:301
src
uint16_t src
Definition: app-layer-dnp3.h:5
B64_BLOCK
#define B64_BLOCK
Definition: util-base64.h:33
ASCII_BLOCK
#define ASCII_BLOCK
Definition: util-base64.h:32
dst
uint16_t dst
Definition: app-layer-dnp3.h:4
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
Base64Ecode
Base64Ecode
Definition: util-base64.h:35