1 /*
2 * Base64 stream functions
3 *
4 * Copyright (C) 2008-2021, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include <common.h>
23 #include <byte_stream.h>
24 #include <types.h>
25
26 #include "libuna_base64_stream.h"
27 #include "libuna_definitions.h"
28 #include "libuna_libcerror.h"
29 #include "libuna_types.h"
30
31 static uint8_t libuna_base64_sixtet_to_character_table[ 64 ] = {
32 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
33 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
34 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
35 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
36
37 static uint8_t libuna_base64url_sixtet_to_character_table[ 64 ] = {
38 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
39 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
40 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
41 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' };
42
43 /* Copies a base64 character to a base64 sixtet
44 * Returns 1 if successful, 0 if not a valid base64 character or -1 on error
45 */
libuna_base64_character_copy_to_sixtet(uint32_t base64_character,uint8_t * base64_sixtet,uint32_t base64_variant,libcerror_error_t ** error)46 int libuna_base64_character_copy_to_sixtet(
47 uint32_t base64_character,
48 uint8_t *base64_sixtet,
49 uint32_t base64_variant,
50 libcerror_error_t **error )
51 {
52 static char *function = "libuna_base64_character_copy_to_sixtet";
53 uint32_t safe_base64_sixtet = 0;
54 uint8_t base64_character_62 = 0;
55 uint8_t base64_character_63 = 0;
56
57 if( base64_sixtet == NULL )
58 {
59 libcerror_error_set(
60 error,
61 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
62 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
63 "%s: invalid base64 sixtet.",
64 function );
65
66 return( -1 );
67 }
68 switch( base64_variant & 0x000f0000UL )
69 {
70 case LIBUNA_BASE64_VARIANT_ALPHABET_NORMAL:
71 base64_character_62 = (uint8_t) '+';
72 base64_character_63 = (uint8_t) '/';
73 break;
74
75 case LIBUNA_BASE64_VARIANT_ALPHABET_URL:
76 base64_character_62 = (uint8_t) '-';
77 base64_character_63 = (uint8_t) '_';
78 break;
79
80 default:
81 libcerror_error_set(
82 error,
83 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
84 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
85 "%s: unsupported base64 variant.",
86 function );
87
88 return( -1 );
89 }
90 if( ( base64_character & 0xffffff00UL ) != 0 )
91 {
92 return( 0 );
93 }
94 /* A-Z is not a continous range on an EBCDIC based system
95 * it consists of the ranges: A-I, J-R, S-Z
96 */
97 if( ( base64_character >= (uint32_t) 'A' )
98 && ( base64_character <= (uint32_t) 'I' ) )
99 {
100 safe_base64_sixtet = base64_character - (uint32_t) 'A';
101 }
102 else if( ( base64_character >= (uint32_t) 'J' )
103 && ( base64_character <= (uint32_t) 'R' ) )
104 {
105 safe_base64_sixtet = base64_character - (uint32_t) 'J' + 9;
106 }
107 else if( ( base64_character >= (uint32_t) 'S' )
108 && ( base64_character <= (uint32_t) 'Z' ) )
109 {
110 safe_base64_sixtet = base64_character - (uint32_t) 'S' + 18;
111 }
112 /* a-z is not a continous range on an EBCDIC based system
113 * it consists of the ranges: a-i, j-r, s-z
114 */
115 else if( ( base64_character >= (uint32_t) 'a' )
116 && ( base64_character <= (uint32_t) 'i' ) )
117 {
118 safe_base64_sixtet = base64_character - (uint32_t) 'a' + 26;
119 }
120 else if( ( base64_character >= (uint32_t) 'j' )
121 && ( base64_character <= (uint32_t) 'r' ) )
122 {
123 safe_base64_sixtet = base64_character - (uint32_t) 'j' + 35;
124 }
125 else if( ( base64_character >= (uint32_t) 's' )
126 && ( base64_character <= (uint32_t) 'z' ) )
127 {
128 safe_base64_sixtet = base64_character - (uint32_t) 's' + 44;
129 }
130 else if( ( base64_character >= (uint32_t) '0' )
131 && ( base64_character <= (uint32_t) '9' ) )
132 {
133 safe_base64_sixtet = base64_character - (uint32_t) '0' + 52;
134 }
135 else if( base64_character == base64_character_62 )
136 {
137 safe_base64_sixtet = 62;
138 }
139 else if( base64_character == base64_character_63 )
140 {
141 safe_base64_sixtet = 63;
142 }
143 else
144 {
145 return( 0 );
146 }
147 *base64_sixtet = (uint8_t) ( safe_base64_sixtet & 0xff );
148
149 return( 1 );
150 }
151
152 /* Copies a base64 triplet from a base64 stream
153 *
154 * The padding size will still be set to indicate the number of
155 * sixtets in the triplet
156 *
157 * Returns 1 if successful or -1 on error
158 */
libuna_base64_triplet_copy_from_base64_stream(uint32_t * base64_triplet,const uint8_t * base64_stream,size_t base64_stream_size,size_t * base64_stream_index,uint8_t * padding_size,uint32_t base64_variant,libcerror_error_t ** error)159 int libuna_base64_triplet_copy_from_base64_stream(
160 uint32_t *base64_triplet,
161 const uint8_t *base64_stream,
162 size_t base64_stream_size,
163 size_t *base64_stream_index,
164 uint8_t *padding_size,
165 uint32_t base64_variant,
166 libcerror_error_t **error )
167 {
168 static char *function = "libuna_base64_triplet_copy_from_base64_stream";
169 size_t base64_character_size = 0;
170 size_t safe_base64_stream_index = 0;
171 uint32_t base64_character = 0;
172 uint32_t safe_base64_triplet = 0;
173 uint8_t safe_padding_size = 0;
174 uint8_t sixtet1 = 0;
175 uint8_t sixtet2 = 0;
176 uint8_t sixtet3 = 0;
177 uint8_t sixtet4 = 0;
178 int result = 0;
179
180 if( base64_triplet == NULL )
181 {
182 libcerror_error_set(
183 error,
184 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
185 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
186 "%s: invalid base64 triplet.",
187 function );
188
189 return( -1 );
190 }
191 if( base64_stream == NULL )
192 {
193 libcerror_error_set(
194 error,
195 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
196 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
197 "%s: invalid base64 stream.",
198 function );
199
200 return( -1 );
201 }
202 if( base64_stream_size > (size_t) SSIZE_MAX )
203 {
204 libcerror_error_set(
205 error,
206 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
207 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
208 "%s: invalid base64 stream size value exceeds maximum.",
209 function );
210
211 return( -1 );
212 }
213 if( base64_stream_index == NULL )
214 {
215 libcerror_error_set(
216 error,
217 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
218 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
219 "%s: invalid base64 stream index.",
220 function );
221
222 return( -1 );
223 }
224 if( padding_size == NULL )
225 {
226 libcerror_error_set(
227 error,
228 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
229 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
230 "%s: invalid padding size.",
231 function );
232
233 return( -1 );
234 }
235 switch( base64_variant & 0x0f000000UL )
236 {
237 case LIBUNA_BASE64_VARIANT_PADDING_NONE:
238 case LIBUNA_BASE64_VARIANT_PADDING_OPTIONAL:
239 case LIBUNA_BASE64_VARIANT_PADDING_REQUIRED:
240 case LIBUNA_BASE64_VARIANT_PADDING_INVALID:
241 break;
242
243 default:
244 libcerror_error_set(
245 error,
246 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
247 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
248 "%s: unsupported base64 variant.",
249 function );
250
251 return( -1 );
252 }
253 switch( base64_variant & 0xf0000000UL )
254 {
255 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
256 base64_character_size = 1;
257 break;
258
259 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
260 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
261 base64_character_size = 2;
262 break;
263
264 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
265 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
266 base64_character_size = 4;
267 break;
268
269 default:
270 libcerror_error_set(
271 error,
272 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
273 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
274 "%s: unsupported base64 variant.",
275 function );
276
277 return( -1 );
278 }
279 safe_base64_stream_index = *base64_stream_index;
280
281 if( ( base64_character_size > base64_stream_size )
282 || ( safe_base64_stream_index > ( base64_stream_size - base64_character_size ) ) )
283 {
284 libcerror_error_set(
285 error,
286 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
287 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
288 "%s: base64 stream string too small - missing 1st base64 character.",
289 function );
290
291 return( -1 );
292 }
293 switch( base64_variant & 0xf0000000UL )
294 {
295 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
296 base64_character = base64_stream[ safe_base64_stream_index ];
297 break;
298
299 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
300 byte_stream_copy_to_uint16_big_endian(
301 &( base64_stream[ safe_base64_stream_index ] ),
302 base64_character );
303 break;
304
305 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
306 byte_stream_copy_to_uint16_little_endian(
307 &( base64_stream[ safe_base64_stream_index ] ),
308 base64_character );
309 break;
310
311 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
312 byte_stream_copy_to_uint32_big_endian(
313 &( base64_stream[ safe_base64_stream_index ] ),
314 base64_character );
315 break;
316
317 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
318 byte_stream_copy_to_uint32_little_endian(
319 &( base64_stream[ safe_base64_stream_index ] ),
320 base64_character );
321 break;
322 }
323 safe_base64_stream_index += base64_character_size;
324
325 result = libuna_base64_character_copy_to_sixtet(
326 base64_character,
327 &sixtet1,
328 base64_variant,
329 error );
330
331 if( result == -1 )
332 {
333 libcerror_error_set(
334 error,
335 LIBCERROR_ERROR_DOMAIN_CONVERSION,
336 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
337 "%s: unable to copy base64 character to 1st sixtet.",
338 function );
339
340 return( -1 );
341 }
342 else if( result == 0 )
343 {
344 libcerror_error_set(
345 error,
346 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
347 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
348 "%s: invalid 1st base64 character.",
349 function );
350
351 return( -1 );
352 }
353 if( ( base64_character_size > base64_stream_size )
354 || ( safe_base64_stream_index > ( base64_stream_size - base64_character_size ) ) )
355 {
356 libcerror_error_set(
357 error,
358 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
359 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
360 "%s: base64 stream string too small - missing 2nd base64 character.",
361 function );
362
363 return( -1 );
364 }
365 switch( base64_variant & 0xf0000000UL )
366 {
367 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
368 base64_character = base64_stream[ safe_base64_stream_index ];
369 break;
370
371 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
372 byte_stream_copy_to_uint16_big_endian(
373 &( base64_stream[ safe_base64_stream_index ] ),
374 base64_character );
375 break;
376
377 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
378 byte_stream_copy_to_uint16_little_endian(
379 &( base64_stream[ safe_base64_stream_index ] ),
380 base64_character );
381 break;
382
383 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
384 byte_stream_copy_to_uint32_big_endian(
385 &( base64_stream[ safe_base64_stream_index ] ),
386 base64_character );
387 break;
388
389 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
390 byte_stream_copy_to_uint32_little_endian(
391 &( base64_stream[ safe_base64_stream_index ] ),
392 base64_character );
393 break;
394 }
395 safe_base64_stream_index += base64_character_size;
396
397 result = libuna_base64_character_copy_to_sixtet(
398 base64_character,
399 &sixtet2,
400 base64_variant,
401 error );
402
403 if( result == -1 )
404 {
405 libcerror_error_set(
406 error,
407 LIBCERROR_ERROR_DOMAIN_CONVERSION,
408 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
409 "%s: unable to copy base64 character to 2nd sixtet.",
410 function );
411
412 return( -1 );
413 }
414 else if( result == 0 )
415 {
416 libcerror_error_set(
417 error,
418 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
419 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
420 "%s: invalid 2nd base64 character.",
421 function );
422
423 return( -1 );
424 }
425 safe_padding_size = 2;
426
427 if( ( base64_character_size > base64_stream_size )
428 || ( safe_base64_stream_index > ( base64_stream_size - base64_character_size ) ) )
429 {
430 if( ( base64_variant & 0x0f000000UL ) == LIBUNA_BASE64_VARIANT_PADDING_REQUIRED )
431 {
432 libcerror_error_set(
433 error,
434 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
435 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
436 "%s: base64 stream string too small - missing 3rd base64 character.",
437 function );
438
439 return( -1 );
440 }
441 }
442 else
443 {
444 switch( base64_variant & 0xf0000000UL )
445 {
446 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
447 base64_character = base64_stream[ safe_base64_stream_index ];
448 break;
449
450 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
451 byte_stream_copy_to_uint16_big_endian(
452 &( base64_stream[ safe_base64_stream_index ] ),
453 base64_character );
454 break;
455
456 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
457 byte_stream_copy_to_uint16_little_endian(
458 &( base64_stream[ safe_base64_stream_index ] ),
459 base64_character );
460 break;
461
462 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
463 byte_stream_copy_to_uint32_big_endian(
464 &( base64_stream[ safe_base64_stream_index ] ),
465 base64_character );
466 break;
467
468 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
469 byte_stream_copy_to_uint32_little_endian(
470 &( base64_stream[ safe_base64_stream_index ] ),
471 base64_character );
472 break;
473 }
474 safe_base64_stream_index += base64_character_size;
475
476 if( ( base64_character & 0xffffff00UL ) != 0 )
477 {
478 libcerror_error_set(
479 error,
480 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
481 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
482 "%s: invalid 3rd base64 character.",
483 function );
484
485 return( -1 );
486 }
487 if( base64_character == (uint32_t) '=' )
488 {
489 if( ( base64_variant & 0x0f000000UL ) == LIBUNA_BASE64_VARIANT_PADDING_NONE )
490 {
491 libcerror_error_set(
492 error,
493 LIBCERROR_ERROR_DOMAIN_RUNTIME,
494 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
495 "%s: padding where not supposed to - invalid 3rd base64 character.",
496 function );
497
498 return( -1 );
499 }
500 }
501 else
502 {
503 result = libuna_base64_character_copy_to_sixtet(
504 base64_character,
505 &sixtet3,
506 base64_variant,
507 error );
508
509 if( result == -1 )
510 {
511 libcerror_error_set(
512 error,
513 LIBCERROR_ERROR_DOMAIN_CONVERSION,
514 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
515 "%s: unable to copy base64 character to 3rd sixtet.",
516 function );
517
518 return( -1 );
519 }
520 else if( result == 0 )
521 {
522 if( ( base64_variant & 0x0f000000UL ) != LIBUNA_BASE64_VARIANT_PADDING_INVALID )
523 {
524 libcerror_error_set(
525 error,
526 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
527 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
528 "%s: invalid 3rd base64 sixtet.",
529 function );
530
531 return( -1 );
532 }
533 }
534 else
535 {
536 safe_padding_size -= 1;
537 }
538 }
539 }
540 if( ( base64_character_size > base64_stream_size )
541 || ( safe_base64_stream_index > ( base64_stream_size - base64_character_size ) ) )
542 {
543 if( ( base64_variant & 0x0f000000UL ) == LIBUNA_BASE64_VARIANT_PADDING_REQUIRED )
544 {
545 libcerror_error_set(
546 error,
547 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
548 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
549 "%s: base64 stream string too small - missing 4th base64 character.",
550 function );
551
552 return( -1 );
553 }
554 }
555 else
556 {
557 switch( base64_variant & 0xf0000000UL )
558 {
559 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
560 base64_character = base64_stream[ safe_base64_stream_index ];
561 break;
562
563 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
564 byte_stream_copy_to_uint16_big_endian(
565 &( base64_stream[ safe_base64_stream_index ] ),
566 base64_character );
567 break;
568
569 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
570 byte_stream_copy_to_uint16_little_endian(
571 &( base64_stream[ safe_base64_stream_index ] ),
572 base64_character );
573 break;
574
575 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
576 byte_stream_copy_to_uint32_big_endian(
577 &( base64_stream[ safe_base64_stream_index ] ),
578 base64_character );
579 break;
580
581 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
582 byte_stream_copy_to_uint32_little_endian(
583 &( base64_stream[ safe_base64_stream_index ] ),
584 base64_character );
585 break;
586 }
587 safe_base64_stream_index += base64_character_size;
588
589 if( ( base64_character & 0xffffff00UL ) != 0 )
590 {
591 libcerror_error_set(
592 error,
593 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
594 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
595 "%s: invalid 4th base64 character.",
596 function );
597
598 return( -1 );
599 }
600 if( base64_character == (uint32_t) '=' )
601 {
602 if( ( base64_variant & 0x0f000000UL ) == LIBUNA_BASE64_VARIANT_PADDING_NONE )
603 {
604 libcerror_error_set(
605 error,
606 LIBCERROR_ERROR_DOMAIN_RUNTIME,
607 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
608 "%s: padding where not supposed to - invalid 4th base64 character.",
609 function );
610
611 return( -1 );
612 }
613 }
614 else
615 {
616 result = libuna_base64_character_copy_to_sixtet(
617 base64_character,
618 &sixtet4,
619 base64_variant,
620 error );
621
622 if( result == -1 )
623 {
624 libcerror_error_set(
625 error,
626 LIBCERROR_ERROR_DOMAIN_CONVERSION,
627 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
628 "%s: unable to copy base64 character to 4th sixtet.",
629 function );
630
631 return( -1 );
632 }
633 else if( result == 0 )
634 {
635 if( ( base64_variant & 0x0f000000UL ) != LIBUNA_BASE64_VARIANT_PADDING_INVALID )
636 {
637 libcerror_error_set(
638 error,
639 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
640 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
641 "%s: invalid 4th base64 sixtet.",
642 function );
643
644 return( -1 );
645 }
646 }
647 else
648 {
649 if( safe_padding_size > 1 )
650 {
651 libcerror_error_set(
652 error,
653 LIBCERROR_ERROR_DOMAIN_RUNTIME,
654 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
655 "%s: non-padding where not supposed to - invalid 4th base64 character.",
656 function );
657
658 return( -1 );
659 }
660 safe_padding_size -= 1;
661 }
662 }
663 }
664 safe_base64_triplet = sixtet1;
665 safe_base64_triplet <<= 6;
666 safe_base64_triplet |= sixtet2;
667 safe_base64_triplet <<= 6;
668 safe_base64_triplet |= sixtet3;
669 safe_base64_triplet <<= 6;
670 safe_base64_triplet |= sixtet4;
671
672 *base64_triplet = safe_base64_triplet;
673 *base64_stream_index = safe_base64_stream_index;
674 *padding_size = safe_padding_size;
675
676 return( 1 );
677 }
678
679 /* Copies a base64 triplet to a base64 stream
680 * Returns 1 if successful or -1 on error
681 */
libuna_base64_triplet_copy_to_base64_stream(uint32_t base64_triplet,uint8_t * base64_stream,size_t base64_stream_size,size_t * base64_stream_index,uint8_t padding_size,uint32_t base64_variant,libcerror_error_t ** error)682 int libuna_base64_triplet_copy_to_base64_stream(
683 uint32_t base64_triplet,
684 uint8_t *base64_stream,
685 size_t base64_stream_size,
686 size_t *base64_stream_index,
687 uint8_t padding_size,
688 uint32_t base64_variant,
689 libcerror_error_t **error )
690 {
691 uint8_t *sixtet_to_character_table = NULL;
692 static char *function = "libuna_base64_triplet_copy_to_base64_stream";
693 size_t base64_character_size = 0;
694 size_t safe_base64_stream_index = 0;
695 uint32_t base64_character = 0;
696 uint8_t padding_character = 0;
697 uint8_t sixtet1 = 0;
698 uint8_t sixtet2 = 0;
699 uint8_t sixtet3 = 0;
700 uint8_t sixtet4 = 0;
701
702 if( base64_stream == NULL )
703 {
704 libcerror_error_set(
705 error,
706 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
707 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
708 "%s: invalid base64 stream.",
709 function );
710
711 return( -1 );
712 }
713 if( base64_stream_size > (size_t) SSIZE_MAX )
714 {
715 libcerror_error_set(
716 error,
717 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
718 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
719 "%s: invalid base64 stream size value exceeds maximum.",
720 function );
721
722 return( -1 );
723 }
724 if( base64_stream_index == NULL )
725 {
726 libcerror_error_set(
727 error,
728 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
729 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
730 "%s: invalid base64 stream index.",
731 function );
732
733 return( -1 );
734 }
735 if( *base64_stream_index >= base64_stream_size )
736 {
737 libcerror_error_set(
738 error,
739 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
740 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
741 "%s: base64 stream string too small.",
742 function );
743
744 return( -1 );
745 }
746 if( padding_size > 2 )
747 {
748 libcerror_error_set(
749 error,
750 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
751 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
752 "%s: invalid padding size value out of bounds.",
753 function );
754
755 return( -1 );
756 }
757 switch( base64_variant & 0x000f0000UL )
758 {
759 case LIBUNA_BASE64_VARIANT_ALPHABET_NORMAL:
760 sixtet_to_character_table = libuna_base64_sixtet_to_character_table;
761 break;
762
763 case LIBUNA_BASE64_VARIANT_ALPHABET_URL:
764 sixtet_to_character_table = libuna_base64url_sixtet_to_character_table;
765 break;
766
767 default:
768 libcerror_error_set(
769 error,
770 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
771 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
772 "%s: unsupported base64 variant.",
773 function );
774
775 return( -1 );
776 }
777 switch( base64_variant & 0x0f000000UL )
778 {
779 case LIBUNA_BASE64_VARIANT_PADDING_NONE:
780 case LIBUNA_BASE64_VARIANT_PADDING_OPTIONAL:
781 case LIBUNA_BASE64_VARIANT_PADDING_INVALID:
782 padding_character = 0;
783 break;
784
785
786 case LIBUNA_BASE64_VARIANT_PADDING_REQUIRED:
787 padding_character = (uint8_t) '=';
788 break;
789
790 default:
791 libcerror_error_set(
792 error,
793 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
794 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
795 "%s: unsupported base64 variant.",
796 function );
797
798 return( -1 );
799 }
800 switch( base64_variant & 0xf0000000UL )
801 {
802 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
803 base64_character_size = 1;
804 break;
805
806 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
807 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
808 base64_character_size = 2;
809 break;
810
811 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
812 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
813 base64_character_size = 4;
814 break;
815
816 default:
817 libcerror_error_set(
818 error,
819 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
820 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
821 "%s: unsupported base64 variant.",
822 function );
823
824 return( -1 );
825 }
826 safe_base64_stream_index = *base64_stream_index;
827
828 /* Separate the 3 bytes value into 4 x 6 bit values
829 */
830 sixtet4 = (uint8_t) ( base64_triplet & 0x3f );
831 base64_triplet >>= 6;
832 sixtet3 = (uint8_t) ( base64_triplet & 0x3f );
833 base64_triplet >>= 6;
834 sixtet2 = (uint8_t) ( base64_triplet & 0x3f );
835 base64_triplet >>= 6;
836 sixtet1 = (uint8_t) ( base64_triplet & 0x3f );
837
838 /* Spread the encoding over 2 characters if 1 byte is available
839 */
840 if( ( safe_base64_stream_index + ( base64_character_size * 2 ) ) > base64_stream_size )
841 {
842 libcerror_error_set(
843 error,
844 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
845 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
846 "%s: base64 stream is too small.",
847 function );
848
849 return( -1 );
850 }
851 base64_character = sixtet_to_character_table[ sixtet1 ];
852
853 switch( base64_variant & 0xf0000000UL )
854 {
855 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
856 base64_stream[ safe_base64_stream_index ] = (uint8_t) base64_character;
857 break;
858
859 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
860 byte_stream_copy_from_uint16_big_endian(
861 &( base64_stream[ safe_base64_stream_index ] ),
862 base64_character );
863 break;
864
865 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
866 byte_stream_copy_from_uint16_little_endian(
867 &( base64_stream[ safe_base64_stream_index ] ),
868 base64_character );
869 break;
870
871 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
872 byte_stream_copy_from_uint32_big_endian(
873 &( base64_stream[ safe_base64_stream_index ] ),
874 base64_character );
875 break;
876
877 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
878 byte_stream_copy_from_uint32_little_endian(
879 &( base64_stream[ safe_base64_stream_index ] ),
880 base64_character );
881 break;
882 }
883 safe_base64_stream_index += base64_character_size;
884
885 base64_character = sixtet_to_character_table[ sixtet2 ];
886
887 switch( base64_variant & 0xf0000000UL )
888 {
889 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
890 base64_stream[ safe_base64_stream_index ] = (uint8_t) base64_character;
891 break;
892
893 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
894 byte_stream_copy_from_uint16_big_endian(
895 &( base64_stream[ safe_base64_stream_index ] ),
896 base64_character );
897 break;
898
899 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
900 byte_stream_copy_from_uint16_little_endian(
901 &( base64_stream[ safe_base64_stream_index ] ),
902 base64_character );
903 break;
904
905 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
906 byte_stream_copy_from_uint32_big_endian(
907 &( base64_stream[ safe_base64_stream_index ] ),
908 base64_character );
909 break;
910
911 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
912 byte_stream_copy_from_uint32_little_endian(
913 &( base64_stream[ safe_base64_stream_index ] ),
914 base64_character );
915 break;
916 }
917 safe_base64_stream_index += base64_character_size;
918
919 /* Spread the encoding over 3 characters if 2 bytes are available
920 * Otherwise pad the remaining bytes if required
921 */
922 if( ( safe_base64_stream_index + base64_character_size ) > base64_stream_size )
923 {
924 libcerror_error_set(
925 error,
926 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
927 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
928 "%s: base64 stream is too small.",
929 function );
930
931 return( -1 );
932 }
933 if( ( padding_size < 2 )
934 || ( padding_character != 0 ) )
935 {
936 if( padding_size < 2 )
937 {
938 base64_character = sixtet_to_character_table[ sixtet3 ];
939 }
940 else if( padding_character != 0 )
941 {
942 base64_character = padding_character;
943 }
944 switch( base64_variant & 0xf0000000UL )
945 {
946 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
947 base64_stream[ safe_base64_stream_index ] = (uint8_t) base64_character;
948 break;
949
950 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
951 byte_stream_copy_from_uint16_big_endian(
952 &( base64_stream[ safe_base64_stream_index ] ),
953 base64_character );
954 break;
955
956 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
957 byte_stream_copy_from_uint16_little_endian(
958 &( base64_stream[ safe_base64_stream_index ] ),
959 base64_character );
960 break;
961
962 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
963 byte_stream_copy_from_uint32_big_endian(
964 &( base64_stream[ safe_base64_stream_index ] ),
965 base64_character );
966 break;
967
968 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
969 byte_stream_copy_from_uint32_little_endian(
970 &( base64_stream[ safe_base64_stream_index ] ),
971 base64_character );
972 break;
973 }
974 safe_base64_stream_index += base64_character_size;
975 }
976 /* Spread the encoding over 4 characters if 3 bytes are available
977 * Otherwise pad the remaining bytes if required
978 */
979 if( ( safe_base64_stream_index + base64_character_size ) > base64_stream_size )
980 {
981 libcerror_error_set(
982 error,
983 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
984 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
985 "%s: base64 stream is too small.",
986 function );
987
988 return( -1 );
989 }
990 if( ( padding_size < 1 )
991 || ( padding_character != 0 ) )
992 {
993 if( padding_size < 1 )
994 {
995 base64_character = sixtet_to_character_table[ sixtet4 ];
996 }
997 else if( padding_character != 0 )
998 {
999 base64_character = padding_character;
1000 }
1001 switch( base64_variant & 0xf0000000UL )
1002 {
1003 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
1004 base64_stream[ safe_base64_stream_index ] = (uint8_t) base64_character;
1005 break;
1006
1007 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1008 byte_stream_copy_from_uint16_big_endian(
1009 &( base64_stream[ safe_base64_stream_index ] ),
1010 base64_character );
1011 break;
1012
1013 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1014 byte_stream_copy_from_uint16_little_endian(
1015 &( base64_stream[ safe_base64_stream_index ] ),
1016 base64_character );
1017 break;
1018
1019 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1020 byte_stream_copy_from_uint32_big_endian(
1021 &( base64_stream[ safe_base64_stream_index ] ),
1022 base64_character );
1023 break;
1024
1025 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1026 byte_stream_copy_from_uint32_little_endian(
1027 &( base64_stream[ safe_base64_stream_index ] ),
1028 base64_character );
1029 break;
1030 }
1031 safe_base64_stream_index += base64_character_size;
1032 }
1033 *base64_stream_index = safe_base64_stream_index;
1034
1035 return( 1 );
1036 }
1037
1038 /* Copies a base64 triplet from a byte stream
1039 * Returns 1 if successful or -1 on error
1040 */
libuna_base64_triplet_copy_from_byte_stream(uint32_t * base64_triplet,const uint8_t * byte_stream,size_t byte_stream_size,size_t * byte_stream_index,uint8_t * padding_size,libcerror_error_t ** error)1041 int libuna_base64_triplet_copy_from_byte_stream(
1042 uint32_t *base64_triplet,
1043 const uint8_t *byte_stream,
1044 size_t byte_stream_size,
1045 size_t *byte_stream_index,
1046 uint8_t *padding_size,
1047 libcerror_error_t **error )
1048 {
1049 static char *function = "libuna_base64_triplet_copy_from_byte_stream";
1050 size_t safe_byte_stream_index = 0;
1051 uint32_t safe_base64_triplet = 0;
1052 uint8_t safe_padding_size = 0;
1053
1054 if( base64_triplet == NULL )
1055 {
1056 libcerror_error_set(
1057 error,
1058 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1059 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1060 "%s: invalid base64 triplet.",
1061 function );
1062
1063 return( -1 );
1064 }
1065 if( byte_stream == NULL )
1066 {
1067 libcerror_error_set(
1068 error,
1069 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1070 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1071 "%s: invalid byte stream.",
1072 function );
1073
1074 return( -1 );
1075 }
1076 if( byte_stream_size > (size_t) SSIZE_MAX )
1077 {
1078 libcerror_error_set(
1079 error,
1080 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1081 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1082 "%s: invalid byte stream size value exceeds maximum.",
1083 function );
1084
1085 return( -1 );
1086 }
1087 if( byte_stream_index == NULL )
1088 {
1089 libcerror_error_set(
1090 error,
1091 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1092 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1093 "%s: invalid byte stream index.",
1094 function );
1095
1096 return( -1 );
1097 }
1098 if( *byte_stream_index >= byte_stream_size )
1099 {
1100 libcerror_error_set(
1101 error,
1102 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1103 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1104 "%s: byte stream string too small.",
1105 function );
1106
1107 return( -1 );
1108 }
1109 if( padding_size == NULL )
1110 {
1111 libcerror_error_set(
1112 error,
1113 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1114 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1115 "%s: invalid padding size.",
1116 function );
1117
1118 return( -1 );
1119 }
1120 safe_byte_stream_index = *byte_stream_index;
1121
1122 /* Determine the value of 3 bytes (24 bits)
1123 */
1124 safe_base64_triplet = byte_stream[ safe_byte_stream_index++ ];
1125 safe_padding_size = 2;
1126
1127 safe_base64_triplet <<= 8;
1128
1129 if( safe_byte_stream_index < byte_stream_size )
1130 {
1131 safe_base64_triplet |= byte_stream[ safe_byte_stream_index++ ];
1132 safe_padding_size -= 1;
1133 }
1134 safe_base64_triplet <<= 8;
1135
1136 if( safe_byte_stream_index < byte_stream_size )
1137 {
1138 safe_base64_triplet |= byte_stream[ safe_byte_stream_index++ ];
1139 safe_padding_size -= 1;
1140 }
1141 *base64_triplet = safe_base64_triplet;
1142 *byte_stream_index = safe_byte_stream_index;
1143 *padding_size = safe_padding_size;
1144
1145 return( 1 );
1146 }
1147
1148 /* Copies a base64 triplet to a byte stream
1149 * Returns 1 if successful or -1 on error
1150 */
libuna_base64_triplet_copy_to_byte_stream(uint32_t base64_triplet,uint8_t * byte_stream,size_t byte_stream_size,size_t * byte_stream_index,uint8_t padding_size,libcerror_error_t ** error)1151 int libuna_base64_triplet_copy_to_byte_stream(
1152 uint32_t base64_triplet,
1153 uint8_t *byte_stream,
1154 size_t byte_stream_size,
1155 size_t *byte_stream_index,
1156 uint8_t padding_size,
1157 libcerror_error_t **error )
1158 {
1159 static char *function = "libuna_base64_triplet_copy_to_byte_stream";
1160 size_t safe_byte_stream_index = 0;
1161
1162 if( byte_stream == NULL )
1163 {
1164 libcerror_error_set(
1165 error,
1166 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1167 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1168 "%s: invalid byte stream.",
1169 function );
1170
1171 return( -1 );
1172 }
1173 if( byte_stream_size > (size_t) SSIZE_MAX )
1174 {
1175 libcerror_error_set(
1176 error,
1177 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1178 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1179 "%s: invalid byte stream size value exceeds maximum.",
1180 function );
1181
1182 return( -1 );
1183 }
1184 if( byte_stream_index == NULL )
1185 {
1186 libcerror_error_set(
1187 error,
1188 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1189 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1190 "%s: invalid byte stream index.",
1191 function );
1192
1193 return( -1 );
1194 }
1195 if( *byte_stream_index >= byte_stream_size )
1196 {
1197 libcerror_error_set(
1198 error,
1199 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1200 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1201 "%s: byte stream string too small.",
1202 function );
1203
1204 return( -1 );
1205 }
1206 if( padding_size > 2 )
1207 {
1208 libcerror_error_set(
1209 error,
1210 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1211 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1212 "%s: invalid padding size value out of bounds.",
1213 function );
1214
1215 return( -1 );
1216 }
1217 safe_byte_stream_index = *byte_stream_index;
1218
1219 byte_stream[ safe_byte_stream_index++ ] = (uint8_t) ( ( base64_triplet >> 16 ) & 0xff );
1220
1221 if( padding_size <= 1 )
1222 {
1223 if( safe_byte_stream_index >= byte_stream_size )
1224 {
1225 libcerror_error_set(
1226 error,
1227 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1228 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1229 "%s: byte stream string too small.",
1230 function );
1231
1232 return( -1 );
1233 }
1234 byte_stream[ safe_byte_stream_index++ ] = (uint8_t) ( ( base64_triplet >> 8 ) & 0xff );
1235 }
1236 if( padding_size == 0 )
1237 {
1238 if( safe_byte_stream_index >= byte_stream_size )
1239 {
1240 libcerror_error_set(
1241 error,
1242 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1243 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1244 "%s: byte stream is too small.",
1245 function );
1246
1247 return( -1 );
1248 }
1249 byte_stream[ safe_byte_stream_index++ ] = (uint8_t) ( base64_triplet & 0xff );
1250 }
1251 *byte_stream_index = safe_byte_stream_index;
1252
1253 return( 1 );
1254 }
1255
1256 /* Determines the size of a byte stream from a base64 stream
1257 *
1258 * LIBUNA_BASE64_FLAG_STRIP_WHITESPACE removes leading space and tab characters,
1259 * and trailing space, tab and end of line characters
1260 *
1261 * Returns 1 if successful or -1 on error
1262 */
libuna_base64_stream_size_to_byte_stream(const uint8_t * base64_stream,size_t base64_stream_size,size_t * byte_stream_size,uint32_t base64_variant,uint8_t flags,libcerror_error_t ** error)1263 int libuna_base64_stream_size_to_byte_stream(
1264 const uint8_t *base64_stream,
1265 size_t base64_stream_size,
1266 size_t *byte_stream_size,
1267 uint32_t base64_variant,
1268 uint8_t flags,
1269 libcerror_error_t **error )
1270 {
1271 static char *function = "libuna_base64_stream_size_to_byte_stream";
1272 size_t base64_character_size = 0;
1273 size_t base64_stream_index = 0;
1274 size_t number_of_characters = 0;
1275 size_t safe_byte_stream_size = 0;
1276 size_t whitespace_size = 0;
1277 uint32_t base64_character1 = 0;
1278 uint32_t base64_character2 = 0;
1279 uint8_t base64_character_62 = 0;
1280 uint8_t base64_character_63 = 0;
1281 uint8_t character_limit = 0;
1282 uint8_t padding_size = 0;
1283 uint8_t strip_mode = LIBUNA_STRIP_MODE_LEADING_WHITESPACE;
1284
1285 if( base64_stream == NULL )
1286 {
1287 libcerror_error_set(
1288 error,
1289 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1290 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1291 "%s: invalid base64 stream.",
1292 function );
1293
1294 return( -1 );
1295 }
1296 if( ( base64_stream_size == 0 )
1297 || ( base64_stream_size > (size_t) SSIZE_MAX ) )
1298 {
1299 libcerror_error_set(
1300 error,
1301 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1302 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1303 "%s: invalid base64 stream size value out of bounds.",
1304 function );
1305
1306 return( -1 );
1307 }
1308 if( byte_stream_size == NULL )
1309 {
1310 libcerror_error_set(
1311 error,
1312 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1313 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1314 "%s: invalid byte stream size.",
1315 function );
1316
1317 return( -1 );
1318 }
1319 switch( base64_variant & 0x000000ffUL )
1320 {
1321 case LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_NONE:
1322 character_limit = 0;
1323
1324 break;
1325
1326 case LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_64:
1327 character_limit = 64;
1328
1329 break;
1330
1331 case LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_76:
1332 character_limit = 76;
1333
1334 break;
1335
1336 default:
1337 libcerror_error_set(
1338 error,
1339 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1340 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1341 "%s: unsupported base64 variant.",
1342 function );
1343
1344 return( -1 );
1345 }
1346 switch( base64_variant & 0x000f0000UL )
1347 {
1348 case LIBUNA_BASE64_VARIANT_ALPHABET_NORMAL:
1349 base64_character_62 = (uint8_t) '+';
1350 base64_character_63 = (uint8_t) '/';
1351 break;
1352
1353 case LIBUNA_BASE64_VARIANT_ALPHABET_URL:
1354 base64_character_62 = (uint8_t) '-';
1355 base64_character_63 = (uint8_t) '_';
1356 break;
1357
1358 default:
1359 libcerror_error_set(
1360 error,
1361 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1362 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1363 "%s: unsupported base64 variant.",
1364 function );
1365
1366 return( -1 );
1367 }
1368 switch( base64_variant & 0xf0000000UL )
1369 {
1370 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
1371 base64_character_size = 1;
1372 break;
1373
1374 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1375 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1376 base64_character_size = 2;
1377 break;
1378
1379 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1380 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1381 base64_character_size = 4;
1382 break;
1383
1384 default:
1385 libcerror_error_set(
1386 error,
1387 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1388 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1389 "%s: unsupported base64 variant.",
1390 function );
1391
1392 return( -1 );
1393 }
1394 if( base64_stream_size < base64_character_size )
1395 {
1396 libcerror_error_set(
1397 error,
1398 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1399 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1400 "%s: invalid base64 stream value too small.",
1401 function );
1402
1403 return( -1 );
1404 }
1405 if( ( flags & ~( LIBUNA_BASE64_FLAG_STRIP_WHITESPACE ) ) != 0 )
1406 {
1407 libcerror_error_set(
1408 error,
1409 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1410 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1411 "%s: unsupported flags.",
1412 function );
1413
1414 return( -1 );
1415 }
1416 base64_stream_index = base64_stream_size - base64_character_size;
1417 whitespace_size = 0;
1418
1419 while( base64_stream_index > base64_character_size )
1420 {
1421 switch( base64_variant & 0xf0000000UL )
1422 {
1423 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
1424 base64_character1 = base64_stream[ base64_stream_index ];
1425 break;
1426
1427 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1428 byte_stream_copy_to_uint16_big_endian(
1429 &( base64_stream[ base64_stream_index ] ),
1430 base64_character1 );
1431 break;
1432
1433 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1434 byte_stream_copy_to_uint16_little_endian(
1435 &( base64_stream[ base64_stream_index ] ),
1436 base64_character1 );
1437 break;
1438
1439 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1440 byte_stream_copy_to_uint32_big_endian(
1441 &( base64_stream[ base64_stream_index ] ),
1442 base64_character1 );
1443 break;
1444
1445 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1446 byte_stream_copy_to_uint32_little_endian(
1447 &( base64_stream[ base64_stream_index ] ),
1448 base64_character1 );
1449 break;
1450 }
1451 base64_stream_index -= base64_character_size;
1452
1453 if( ( base64_character1 == (uint32_t) '\n' )
1454 || ( base64_character1 == (uint32_t) '\r' ) )
1455 {
1456 whitespace_size += base64_character_size;
1457 }
1458 else if( ( flags & LIBUNA_BASE64_FLAG_STRIP_WHITESPACE ) == 0 )
1459 {
1460 break;
1461 }
1462 else if( ( base64_character1 == (uint32_t) ' ' )
1463 || ( base64_character1 == (uint32_t) '\t' )
1464 || ( base64_character1 == (uint32_t) '\v' ) )
1465 {
1466 whitespace_size += base64_character_size;
1467 }
1468 else
1469 {
1470 break;
1471 }
1472 }
1473 base64_stream_size -= whitespace_size;
1474 base64_stream_index = base64_stream_size - base64_character_size;
1475
1476 if( base64_stream_size < base64_character_size )
1477 {
1478 libcerror_error_set(
1479 error,
1480 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1481 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1482 "%s: invalid base64 stream value too small.",
1483 function );
1484
1485 return( -1 );
1486 }
1487 if( base64_stream_index > base64_character_size )
1488 {
1489 switch( base64_variant & 0xf0000000UL )
1490 {
1491 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
1492 base64_character1 = base64_stream[ base64_stream_index ];
1493 break;
1494
1495 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1496 byte_stream_copy_to_uint16_big_endian(
1497 &( base64_stream[ base64_stream_index ] ),
1498 base64_character1 );
1499 break;
1500
1501 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1502 byte_stream_copy_to_uint16_little_endian(
1503 &( base64_stream[ base64_stream_index ] ),
1504 base64_character1 );
1505 break;
1506
1507 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1508 byte_stream_copy_to_uint32_big_endian(
1509 &( base64_stream[ base64_stream_index ] ),
1510 base64_character1 );
1511 break;
1512
1513 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1514 byte_stream_copy_to_uint32_little_endian(
1515 &( base64_stream[ base64_stream_index ] ),
1516 base64_character1 );
1517 break;
1518 }
1519 base64_stream_index -= base64_character_size;
1520
1521 if( base64_character1 == (uint32_t) '=' )
1522 {
1523 padding_size += 1;
1524 }
1525 }
1526 if( base64_stream_index > base64_character_size )
1527 {
1528 switch( base64_variant & 0xf0000000UL )
1529 {
1530 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
1531 base64_character1 = base64_stream[ base64_stream_index ];
1532 break;
1533
1534 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1535 byte_stream_copy_to_uint16_big_endian(
1536 &( base64_stream[ base64_stream_index ] ),
1537 base64_character1 );
1538 break;
1539
1540 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1541 byte_stream_copy_to_uint16_little_endian(
1542 &( base64_stream[ base64_stream_index ] ),
1543 base64_character1 );
1544 break;
1545
1546 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1547 byte_stream_copy_to_uint32_big_endian(
1548 &( base64_stream[ base64_stream_index ] ),
1549 base64_character1 );
1550 break;
1551
1552 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1553 byte_stream_copy_to_uint32_little_endian(
1554 &( base64_stream[ base64_stream_index ] ),
1555 base64_character1 );
1556 break;
1557 }
1558 base64_stream_index -= base64_character_size;
1559
1560 if( base64_character1 == (uint32_t) '=' )
1561 {
1562 padding_size += 1;
1563 }
1564 }
1565 if( base64_stream_index > base64_character_size )
1566 {
1567 switch( base64_variant & 0xf0000000UL )
1568 {
1569 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
1570 base64_character1 = base64_stream[ base64_stream_index ];
1571 break;
1572
1573 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1574 byte_stream_copy_to_uint16_big_endian(
1575 &( base64_stream[ base64_stream_index ] ),
1576 base64_character1 );
1577 break;
1578
1579 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1580 byte_stream_copy_to_uint16_little_endian(
1581 &( base64_stream[ base64_stream_index ] ),
1582 base64_character1 );
1583 break;
1584
1585 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1586 byte_stream_copy_to_uint32_big_endian(
1587 &( base64_stream[ base64_stream_index ] ),
1588 base64_character1 );
1589 break;
1590
1591 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1592 byte_stream_copy_to_uint32_little_endian(
1593 &( base64_stream[ base64_stream_index ] ),
1594 base64_character1 );
1595 break;
1596 }
1597 if( base64_character1 == (uint32_t) '=' )
1598 {
1599 libcerror_error_set(
1600 error,
1601 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1602 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1603 "%s: invalid number of padding bytes.",
1604 function );
1605
1606 return( -1 );
1607 }
1608 }
1609 base64_stream_index = 0;
1610 whitespace_size = 0;
1611
1612 while( base64_stream_index < ( base64_stream_size - ( padding_size * base64_character_size ) ) )
1613 {
1614 switch( base64_variant & 0xf0000000UL )
1615 {
1616 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
1617 base64_character1 = base64_stream[ base64_stream_index ];
1618 break;
1619
1620 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1621 byte_stream_copy_to_uint16_big_endian(
1622 &( base64_stream[ base64_stream_index ] ),
1623 base64_character1 );
1624 break;
1625
1626 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1627 byte_stream_copy_to_uint16_little_endian(
1628 &( base64_stream[ base64_stream_index ] ),
1629 base64_character1 );
1630 break;
1631
1632 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1633 byte_stream_copy_to_uint32_big_endian(
1634 &( base64_stream[ base64_stream_index ] ),
1635 base64_character1 );
1636 break;
1637
1638 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1639 byte_stream_copy_to_uint32_little_endian(
1640 &( base64_stream[ base64_stream_index ] ),
1641 base64_character1 );
1642 break;
1643 }
1644 base64_stream_index += base64_character_size;
1645
1646 if( ( base64_character1 == (uint32_t) '\n' )
1647 || ( base64_character1 == (uint32_t) '\r' ) )
1648 {
1649 if( ( strip_mode != LIBUNA_STRIP_MODE_NON_WHITESPACE )
1650 && ( strip_mode != LIBUNA_STRIP_MODE_TRAILING_WHITESPACE ) )
1651 {
1652 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
1653 }
1654 else
1655 {
1656 if( ( base64_stream_index + base64_character_size ) < base64_stream_size )
1657 {
1658 switch( base64_variant & 0xf0000000UL )
1659 {
1660 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
1661 base64_character2 = base64_stream[ base64_stream_index ];
1662 break;
1663
1664 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1665 byte_stream_copy_to_uint16_big_endian(
1666 &( base64_stream[ base64_stream_index ] ),
1667 base64_character2 );
1668 break;
1669
1670 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1671 byte_stream_copy_to_uint16_little_endian(
1672 &( base64_stream[ base64_stream_index ] ),
1673 base64_character2 );
1674 break;
1675
1676 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1677 byte_stream_copy_to_uint32_big_endian(
1678 &( base64_stream[ base64_stream_index ] ),
1679 base64_character2 );
1680 break;
1681
1682 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1683 byte_stream_copy_to_uint32_little_endian(
1684 &( base64_stream[ base64_stream_index ] ),
1685 base64_character2 );
1686 break;
1687 }
1688 if( ( base64_character2 == (uint32_t) '\n' )
1689 || ( base64_character2 == (uint32_t) '\r' ) )
1690 {
1691 base64_stream_index += base64_character_size;
1692
1693 whitespace_size += base64_character_size;
1694 }
1695 }
1696 strip_mode = LIBUNA_STRIP_MODE_LEADING_WHITESPACE;
1697 }
1698 if( ( number_of_characters != 0 )
1699 && ( character_limit != 0 ) )
1700 {
1701 if( number_of_characters != (size_t) character_limit )
1702 {
1703 libcerror_error_set(
1704 error,
1705 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1706 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1707 "%s: number of characters in line does not match character limit.",
1708 function );
1709
1710 return( -1 );
1711 }
1712 number_of_characters = 0;
1713 }
1714 whitespace_size += base64_character_size;
1715 }
1716 else if( ( base64_character1 == (uint32_t) ' ' )
1717 || ( base64_character1 == (uint32_t) '\t' )
1718 || ( base64_character1 == (uint32_t) '\v' ) )
1719 {
1720 if( ( flags & LIBUNA_BASE64_FLAG_STRIP_WHITESPACE ) != 0 )
1721 {
1722 if( strip_mode == LIBUNA_STRIP_MODE_NON_WHITESPACE )
1723 {
1724 strip_mode = LIBUNA_STRIP_MODE_TRAILING_WHITESPACE;
1725 }
1726 if( ( strip_mode != LIBUNA_STRIP_MODE_LEADING_WHITESPACE )
1727 && ( strip_mode != LIBUNA_STRIP_MODE_TRAILING_WHITESPACE ) )
1728 {
1729 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
1730 }
1731 else
1732 {
1733 whitespace_size += base64_character_size;
1734 }
1735 }
1736 else
1737 {
1738 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
1739 }
1740 }
1741 else if( strip_mode == LIBUNA_STRIP_MODE_LEADING_WHITESPACE )
1742 {
1743 strip_mode = LIBUNA_STRIP_MODE_NON_WHITESPACE;
1744 }
1745 else if( strip_mode == LIBUNA_STRIP_MODE_TRAILING_WHITESPACE )
1746 {
1747 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
1748 }
1749 if( strip_mode == LIBUNA_STRIP_MODE_NON_WHITESPACE )
1750 {
1751 /* A-Z is not a continous range on an EBCDIC based system
1752 * it consists of the ranges: A-I, J-R, S-Z
1753 */
1754 if( ( base64_character1 >= (uint32_t) 'A' )
1755 && ( base64_character1 <= (uint32_t) 'I' ) )
1756 {
1757 number_of_characters++;
1758 }
1759 else if( ( base64_character1 >= (uint32_t) 'J' )
1760 && ( base64_character1 <= (uint32_t) 'R' ) )
1761 {
1762 number_of_characters++;
1763 }
1764 else if( ( base64_character1 >= (uint32_t) 'S' )
1765 && ( base64_character1 <= (uint32_t) 'Z' ) )
1766 {
1767 number_of_characters++;
1768 }
1769 /* a-z is not a continous range on an EBCDIC based system
1770 * it consists of the ranges: a-i, j-r, s-z
1771 */
1772 else if( ( base64_character1 >= (uint32_t) 'a' )
1773 && ( base64_character1 <= (uint32_t) 'i' ) )
1774 {
1775 number_of_characters++;
1776 }
1777 else if( ( base64_character1 >= (uint32_t) 'j' )
1778 && ( base64_character1 <= (uint32_t) 'r' ) )
1779 {
1780 number_of_characters++;
1781 }
1782 else if( ( base64_character1 >= (uint32_t) 's' )
1783 && ( base64_character1 <= (uint32_t) 'z' ) )
1784 {
1785 number_of_characters++;
1786 }
1787 else if( ( base64_character1 >= (uint32_t) '0' )
1788 && ( base64_character1 <= (uint32_t) '9' ) )
1789 {
1790 number_of_characters++;
1791 }
1792 else if( ( base64_character1 == (uint32_t) base64_character_62 )
1793 || ( base64_character1 == (uint32_t) base64_character_63 ) )
1794 {
1795 number_of_characters++;
1796 }
1797 else
1798 {
1799 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
1800 }
1801 }
1802 if( strip_mode == LIBUNA_STRIP_MODE_INVALID_CHARACTER )
1803 {
1804 libcerror_error_set(
1805 error,
1806 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1807 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1808 "%s: invalid character in base64 stream at index: %" PRIzd ".",
1809 function,
1810 base64_stream_index - base64_character_size );
1811
1812 return( -1 );
1813 }
1814 }
1815 if( character_limit != 0 )
1816 {
1817 if( number_of_characters > (size_t) character_limit )
1818 {
1819 libcerror_error_set(
1820 error,
1821 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1822 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1823 "%s: number of characters in last line exceed maximum.",
1824 function );
1825
1826 return( -1 );
1827 }
1828 }
1829 base64_stream_size -= whitespace_size;
1830
1831 /* Make sure the byte stream is able to hold
1832 * at least 3 bytes for each 4 base64 characters
1833 */
1834 base64_character_size *= 4;
1835
1836 safe_byte_stream_size = base64_stream_size / base64_character_size;
1837
1838 if( ( base64_stream_size % base64_character_size ) != 0 )
1839 {
1840 safe_byte_stream_size += 1;
1841 }
1842 safe_byte_stream_size *= 3;
1843
1844 /* The padding size contains the number of bytes to correct
1845 */
1846 *byte_stream_size = safe_byte_stream_size - padding_size;
1847
1848 return( 1 );
1849 }
1850
1851 /* Copies a byte stream from a base64 stream
1852 *
1853 * LIBUNA_BASE64_FLAG_STRIP_WHITESPACE removes leading space and tab characters,
1854 * and trailing space, tab and end of line characters
1855 *
1856 * Returns 1 if successful or -1 on error
1857 */
libuna_base64_stream_copy_to_byte_stream(const uint8_t * base64_stream,size_t base64_stream_size,uint8_t * byte_stream,size_t byte_stream_size,uint32_t base64_variant,uint8_t flags,libcerror_error_t ** error)1858 int libuna_base64_stream_copy_to_byte_stream(
1859 const uint8_t *base64_stream,
1860 size_t base64_stream_size,
1861 uint8_t *byte_stream,
1862 size_t byte_stream_size,
1863 uint32_t base64_variant,
1864 uint8_t flags,
1865 libcerror_error_t **error )
1866 {
1867 static char *function = "libuna_base64_stream_copy_to_byte_stream";
1868 size_t base64_character_size = 0;
1869 size_t base64_stream_index = 0;
1870 size_t byte_stream_index = 0;
1871 size_t number_of_characters = 0;
1872 size_t whitespace_size = 0;
1873 uint32_t base64_character1 = 0;
1874 uint32_t base64_character2 = 0;
1875 uint32_t base64_triplet = 0;
1876 uint8_t character_limit = 0;
1877 uint8_t padding_size = 0;
1878 uint8_t strip_mode = LIBUNA_STRIP_MODE_LEADING_WHITESPACE;
1879
1880 if( base64_stream == NULL )
1881 {
1882 libcerror_error_set(
1883 error,
1884 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1885 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1886 "%s: invalid base64 stream.",
1887 function );
1888
1889 return( -1 );
1890 }
1891 if( base64_stream_size > (size_t) SSIZE_MAX )
1892 {
1893 libcerror_error_set(
1894 error,
1895 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1896 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1897 "%s: invalid base64 stream size value exceeds maximum.",
1898 function );
1899
1900 return( -1 );
1901 }
1902 if( byte_stream == NULL )
1903 {
1904 libcerror_error_set(
1905 error,
1906 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1907 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1908 "%s: invalid byte stream.",
1909 function );
1910
1911 return( -1 );
1912 }
1913 if( byte_stream_size > (size_t) SSIZE_MAX )
1914 {
1915 libcerror_error_set(
1916 error,
1917 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1918 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1919 "%s: invalid byte stream size value exceeds maximum.",
1920 function );
1921
1922 return( -1 );
1923 }
1924 switch( base64_variant & 0x000000ffUL )
1925 {
1926 case LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_NONE:
1927 character_limit = 0;
1928
1929 break;
1930
1931 case LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_64:
1932 character_limit = 64;
1933
1934 break;
1935
1936 case LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_76:
1937 character_limit = 76;
1938
1939 break;
1940
1941 default:
1942 libcerror_error_set(
1943 error,
1944 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1945 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1946 "%s: unsupported base64 variant.",
1947 function );
1948
1949 return( -1 );
1950 }
1951 switch( base64_variant & 0xf0000000UL )
1952 {
1953 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
1954 base64_character_size = 1;
1955 break;
1956
1957 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1958 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1959 base64_character_size = 2;
1960 break;
1961
1962 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1963 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1964 base64_character_size = 4;
1965 break;
1966
1967 default:
1968 libcerror_error_set(
1969 error,
1970 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1971 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1972 "%s: unsupported base64 variant.",
1973 function );
1974
1975 return( -1 );
1976 }
1977 if( base64_stream_size < base64_character_size )
1978 {
1979 libcerror_error_set(
1980 error,
1981 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1982 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1983 "%s: invalid base64 stream value too small.",
1984 function );
1985
1986 return( -1 );
1987 }
1988 if( ( flags & ~( LIBUNA_BASE64_FLAG_STRIP_WHITESPACE ) ) != 0 )
1989 {
1990 libcerror_error_set(
1991 error,
1992 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1993 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1994 "%s: unsupported flags.",
1995 function );
1996
1997 return( -1 );
1998 }
1999 base64_stream_index = base64_stream_size - base64_character_size;
2000 whitespace_size = 0;
2001
2002 while( base64_stream_index > base64_character_size )
2003 {
2004 switch( base64_variant & 0xf0000000UL )
2005 {
2006 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
2007 base64_character1 = base64_stream[ base64_stream_index ];
2008 break;
2009
2010 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
2011 byte_stream_copy_to_uint16_big_endian(
2012 &( base64_stream[ base64_stream_index ] ),
2013 base64_character1 );
2014 break;
2015
2016 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
2017 byte_stream_copy_to_uint16_little_endian(
2018 &( base64_stream[ base64_stream_index ] ),
2019 base64_character1 );
2020 break;
2021
2022 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
2023 byte_stream_copy_to_uint32_big_endian(
2024 &( base64_stream[ base64_stream_index ] ),
2025 base64_character1 );
2026 break;
2027
2028 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
2029 byte_stream_copy_to_uint32_little_endian(
2030 &( base64_stream[ base64_stream_index ] ),
2031 base64_character1 );
2032 break;
2033 }
2034 base64_stream_index -= base64_character_size;
2035
2036 if( ( base64_character1 == (uint32_t) '\n' )
2037 || ( base64_character1 == (uint32_t) '\r' ) )
2038 {
2039 whitespace_size += base64_character_size;
2040 }
2041 else if( ( flags & LIBUNA_BASE64_FLAG_STRIP_WHITESPACE ) == 0 )
2042 {
2043 break;
2044 }
2045 else if( ( base64_character1 == (uint32_t) ' ' )
2046 || ( base64_character1 == (uint32_t) '\t' )
2047 || ( base64_character1 == (uint32_t) '\v' ) )
2048 {
2049 whitespace_size += base64_character_size;
2050 }
2051 else
2052 {
2053 break;
2054 }
2055 }
2056 base64_stream_size -= whitespace_size;
2057 base64_stream_index = 0;
2058
2059 if( ( flags & LIBUNA_BASE64_FLAG_STRIP_WHITESPACE ) == 0 )
2060 {
2061 strip_mode = LIBUNA_STRIP_MODE_NON_WHITESPACE;
2062 }
2063 while( base64_stream_index < base64_stream_size )
2064 {
2065 switch( base64_variant & 0xf0000000UL )
2066 {
2067 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
2068 base64_character1 = base64_stream[ base64_stream_index ];
2069 break;
2070
2071 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
2072 byte_stream_copy_to_uint16_big_endian(
2073 &( base64_stream[ base64_stream_index ] ),
2074 base64_character1 );
2075 break;
2076
2077 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
2078 byte_stream_copy_to_uint16_little_endian(
2079 &( base64_stream[ base64_stream_index ] ),
2080 base64_character1 );
2081 break;
2082
2083 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
2084 byte_stream_copy_to_uint32_big_endian(
2085 &( base64_stream[ base64_stream_index ] ),
2086 base64_character1 );
2087 break;
2088
2089 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
2090 byte_stream_copy_to_uint32_little_endian(
2091 &( base64_stream[ base64_stream_index ] ),
2092 base64_character1 );
2093 break;
2094 }
2095 base64_stream_index += base64_character_size;
2096
2097 if( ( base64_character1 == (uint32_t) '\n' )
2098 || ( base64_character1 == (uint32_t) '\r' ) )
2099 {
2100 if( ( strip_mode != LIBUNA_STRIP_MODE_NON_WHITESPACE )
2101 && ( strip_mode != LIBUNA_STRIP_MODE_TRAILING_WHITESPACE ) )
2102 {
2103 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
2104 }
2105 else
2106 {
2107 if( ( base64_stream_index + base64_character_size ) < base64_stream_size )
2108 {
2109 switch( base64_variant & 0xf0000000UL )
2110 {
2111 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
2112 base64_character2 = base64_stream[ base64_stream_index ];
2113 break;
2114
2115 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
2116 byte_stream_copy_to_uint16_big_endian(
2117 &( base64_stream[ base64_stream_index ] ),
2118 base64_character2 );
2119 break;
2120
2121 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
2122 byte_stream_copy_to_uint16_little_endian(
2123 &( base64_stream[ base64_stream_index ] ),
2124 base64_character2 );
2125 break;
2126
2127 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
2128 byte_stream_copy_to_uint32_big_endian(
2129 &( base64_stream[ base64_stream_index ] ),
2130 base64_character2 );
2131 break;
2132
2133 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
2134 byte_stream_copy_to_uint32_little_endian(
2135 &( base64_stream[ base64_stream_index ] ),
2136 base64_character2 );
2137 break;
2138 }
2139 if( ( base64_character2 == (uint32_t) '\n' )
2140 || ( base64_character2 == (uint32_t) '\r' ) )
2141 {
2142 base64_stream_index += base64_character_size;
2143 }
2144 }
2145 strip_mode = LIBUNA_STRIP_MODE_LEADING_WHITESPACE;
2146 }
2147 if( character_limit != 0 )
2148 {
2149 if( number_of_characters != (size_t) character_limit )
2150 {
2151 libcerror_error_set(
2152 error,
2153 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2154 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2155 "%s: number of characters in line does not match character limit.",
2156 function );
2157
2158 return( -1 );
2159 }
2160 number_of_characters = 0;
2161 }
2162 }
2163 else if( ( base64_character1 == (uint32_t) ' ' )
2164 || ( base64_character1 == (uint32_t) '\t' )
2165 || ( base64_character1 == (uint32_t) '\v' ) )
2166 {
2167 if( ( flags & LIBUNA_BASE64_FLAG_STRIP_WHITESPACE ) != 0 )
2168 {
2169 if( strip_mode == LIBUNA_STRIP_MODE_NON_WHITESPACE )
2170 {
2171 strip_mode = LIBUNA_STRIP_MODE_TRAILING_WHITESPACE;
2172 }
2173 if( ( strip_mode != LIBUNA_STRIP_MODE_LEADING_WHITESPACE )
2174 && ( strip_mode != LIBUNA_STRIP_MODE_TRAILING_WHITESPACE ) )
2175 {
2176 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
2177 }
2178 }
2179 else
2180 {
2181 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
2182 }
2183 }
2184 else if( strip_mode == LIBUNA_STRIP_MODE_LEADING_WHITESPACE )
2185 {
2186 strip_mode = LIBUNA_STRIP_MODE_NON_WHITESPACE;
2187 }
2188 else if( strip_mode == LIBUNA_STRIP_MODE_TRAILING_WHITESPACE )
2189 {
2190 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
2191 }
2192 if( strip_mode == LIBUNA_STRIP_MODE_INVALID_CHARACTER )
2193 {
2194 libcerror_error_set(
2195 error,
2196 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2197 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2198 "%s: invalid character in base64 stream at index: %" PRIzd ".",
2199 function,
2200 base64_stream_index - base64_character_size );
2201
2202 return( -1 );
2203 }
2204 if( strip_mode == LIBUNA_STRIP_MODE_NON_WHITESPACE )
2205 {
2206 if( padding_size > 0 )
2207 {
2208 libcerror_error_set(
2209 error,
2210 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2211 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2212 "%s: invalid 1st base64 sixtet.",
2213 function );
2214
2215 return( -1 );
2216 }
2217 base64_stream_index -= base64_character_size;
2218
2219 /* Convert the base64 stream into a base64 triplet
2220 */
2221 if( libuna_base64_triplet_copy_from_base64_stream(
2222 &base64_triplet,
2223 base64_stream,
2224 base64_stream_size,
2225 &base64_stream_index,
2226 &padding_size,
2227 base64_variant,
2228 error ) != 1 )
2229 {
2230 libcerror_error_set(
2231 error,
2232 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2233 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2234 "%s: unable to copy base64 triplet from base64 stream.",
2235 function );
2236
2237 return( -1 );
2238 }
2239 /* Convert the base64 triplet into a byte stream
2240 */
2241 if( libuna_base64_triplet_copy_to_byte_stream(
2242 base64_triplet,
2243 byte_stream,
2244 byte_stream_size,
2245 &byte_stream_index,
2246 padding_size,
2247 error ) != 1 )
2248 {
2249 libcerror_error_set(
2250 error,
2251 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2252 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2253 "%s: unable to copy base64 triplet to byte stream.",
2254 function );
2255
2256 return( -1 );
2257 }
2258 number_of_characters += 4 - padding_size;
2259 }
2260 }
2261 if( character_limit != 0 )
2262 {
2263 if( number_of_characters > (size_t) character_limit )
2264 {
2265 libcerror_error_set(
2266 error,
2267 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2268 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2269 "%s: number of characters in last line exceed maximum.",
2270 function );
2271
2272 return( -1 );
2273 }
2274 }
2275 return( 1 );
2276 }
2277
2278 /* Determines the size of a base64 stream from a byte stream
2279 * Returns 1 if successful or -1 on error
2280 */
libuna_base64_stream_size_from_byte_stream(const uint8_t * byte_stream,size_t byte_stream_size,size_t * base64_stream_size,uint32_t base64_variant,libcerror_error_t ** error)2281 int libuna_base64_stream_size_from_byte_stream(
2282 const uint8_t *byte_stream,
2283 size_t byte_stream_size,
2284 size_t *base64_stream_size,
2285 uint32_t base64_variant,
2286 libcerror_error_t **error )
2287 {
2288 static char *function = "libuna_base64_stream_size_from_byte_stream";
2289 size_t base64_character_size = 0;
2290 size_t calculated_base64_stream_size = 0;
2291 size_t remaining_size = 0;
2292 size_t whitespace_size = 0;
2293 uint8_t character_limit = 0;
2294 uint8_t padding_character = 0;
2295
2296 if( byte_stream == NULL )
2297 {
2298 libcerror_error_set(
2299 error,
2300 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2301 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2302 "%s: invalid byte stream.",
2303 function );
2304
2305 return( -1 );
2306 }
2307 if( byte_stream_size > (size_t) SSIZE_MAX )
2308 {
2309 libcerror_error_set(
2310 error,
2311 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2312 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2313 "%s: invalid byte stream size value exceeds maximum.",
2314 function );
2315
2316 return( -1 );
2317 }
2318 if( base64_stream_size == NULL )
2319 {
2320 libcerror_error_set(
2321 error,
2322 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2323 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2324 "%s: invalid base64 stream size.",
2325 function );
2326
2327 return( -1 );
2328 }
2329 switch( base64_variant & 0x000000ffUL )
2330 {
2331 case LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_NONE:
2332 character_limit = 0;
2333
2334 break;
2335
2336 case LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_64:
2337 character_limit = 64;
2338
2339 break;
2340
2341 case LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_76:
2342 character_limit = 76;
2343
2344 break;
2345
2346 default:
2347 libcerror_error_set(
2348 error,
2349 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2350 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2351 "%s: unsupported base64 variant.",
2352 function );
2353
2354 return( -1 );
2355 }
2356 switch( base64_variant & 0x0f000000UL )
2357 {
2358 case LIBUNA_BASE64_VARIANT_PADDING_NONE:
2359 padding_character = 0;
2360 break;
2361
2362 case LIBUNA_BASE64_VARIANT_PADDING_OPTIONAL:
2363 padding_character = (uint8_t) '=';
2364 break;
2365
2366 case LIBUNA_BASE64_VARIANT_PADDING_REQUIRED:
2367 padding_character = (uint8_t) '=';
2368 break;
2369
2370 default:
2371 libcerror_error_set(
2372 error,
2373 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2374 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2375 "%s: unsupported base64 variant.",
2376 function );
2377
2378 return( -1 );
2379 }
2380 switch( base64_variant & 0xf0000000UL )
2381 {
2382 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
2383 base64_character_size = 1;
2384 break;
2385
2386 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
2387 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
2388 base64_character_size = 2;
2389 break;
2390
2391 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
2392 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
2393 base64_character_size = 4;
2394 break;
2395
2396 default:
2397 libcerror_error_set(
2398 error,
2399 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2400 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2401 "%s: unsupported base64 variant.",
2402 function );
2403
2404 return( -1 );
2405 }
2406 /* Make sure the base64 stream is able to hold
2407 * at least 4 base64 characters for each 3 bytes
2408 */
2409 calculated_base64_stream_size = ( byte_stream_size / 3 ) * 4;
2410
2411 remaining_size = byte_stream_size % 3;
2412
2413 if( remaining_size != 0 )
2414 {
2415 if( padding_character != 0 )
2416 {
2417 calculated_base64_stream_size += 4;
2418 }
2419 else if( remaining_size == 1 )
2420 {
2421 calculated_base64_stream_size += 2;
2422 }
2423 else if( remaining_size == 2 )
2424 {
2425 calculated_base64_stream_size += 3;
2426 }
2427 }
2428 if( character_limit != 0 )
2429 {
2430 if( calculated_base64_stream_size > character_limit )
2431 {
2432 whitespace_size = calculated_base64_stream_size / character_limit;
2433
2434 if( ( calculated_base64_stream_size % character_limit ) != 0 )
2435 {
2436 whitespace_size += 1;
2437 }
2438 calculated_base64_stream_size += whitespace_size;
2439 }
2440 calculated_base64_stream_size += 1;
2441 }
2442 calculated_base64_stream_size *= base64_character_size;
2443
2444 *base64_stream_size = calculated_base64_stream_size;
2445
2446 return( 1 );
2447 }
2448
2449 /* Copies a base64 stream from a byte stream
2450 * Returns 1 if successful or -1 on error
2451 */
libuna_base64_stream_copy_from_byte_stream(uint8_t * base64_stream,size_t base64_stream_size,const uint8_t * byte_stream,size_t byte_stream_size,uint32_t base64_variant,libcerror_error_t ** error)2452 int libuna_base64_stream_copy_from_byte_stream(
2453 uint8_t *base64_stream,
2454 size_t base64_stream_size,
2455 const uint8_t *byte_stream,
2456 size_t byte_stream_size,
2457 uint32_t base64_variant,
2458 libcerror_error_t **error )
2459 {
2460 static char *function = "libuna_base64_stream_copy_from_byte_stream";
2461 size_t base64_stream_index = 0;
2462
2463 if( libuna_base64_stream_with_index_copy_from_byte_stream(
2464 base64_stream,
2465 base64_stream_size,
2466 &base64_stream_index,
2467 byte_stream,
2468 byte_stream_size,
2469 base64_variant,
2470 error ) != 1 )
2471 {
2472 libcerror_error_set(
2473 error,
2474 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2475 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
2476 "%s: unable to copy base64 stream from byte stream.",
2477 function );
2478
2479 return( -1 );
2480 }
2481 return( 1 );
2482 }
2483
2484 /* Copies a base64 stream from a byte stream
2485 * Returns 1 if successful or -1 on error
2486 */
libuna_base64_stream_with_index_copy_from_byte_stream(uint8_t * base64_stream,size_t base64_stream_size,size_t * base64_stream_index,const uint8_t * byte_stream,size_t byte_stream_size,uint32_t base64_variant,libcerror_error_t ** error)2487 int libuna_base64_stream_with_index_copy_from_byte_stream(
2488 uint8_t *base64_stream,
2489 size_t base64_stream_size,
2490 size_t *base64_stream_index,
2491 const uint8_t *byte_stream,
2492 size_t byte_stream_size,
2493 uint32_t base64_variant,
2494 libcerror_error_t **error )
2495 {
2496 static char *function = "libuna_base64_stream_with_index_copy_from_byte_stream";
2497 size_t base64_character_size = 0;
2498 size_t calculated_base64_stream_size = 0;
2499 size_t byte_stream_index = 0;
2500 size_t number_of_characters = 0;
2501 size_t remaining_size = 0;
2502 size_t safe_base64_stream_index = 0;
2503 size_t whitespace_size = 0;
2504 uint32_t base64_character = 0;
2505 uint32_t base64_triplet = 0;
2506 uint8_t character_limit = 0;
2507 uint8_t padding_character = 0;
2508 uint8_t padding_size = 0;
2509
2510 if( base64_stream == NULL )
2511 {
2512 libcerror_error_set(
2513 error,
2514 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2515 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2516 "%s: invalid base64 stream.",
2517 function );
2518
2519 return( -1 );
2520 }
2521 if( base64_stream_size > (size_t) SSIZE_MAX )
2522 {
2523 libcerror_error_set(
2524 error,
2525 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2526 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2527 "%s: invalid base64 stream size value exceeds maximum.",
2528 function );
2529
2530 return( -1 );
2531 }
2532 if( base64_stream_index == NULL )
2533 {
2534 libcerror_error_set(
2535 error,
2536 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2537 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2538 "%s: invalid base64 stream index.",
2539 function );
2540
2541 return( -1 );
2542 }
2543 if( *base64_stream_index >= base64_stream_size )
2544 {
2545 libcerror_error_set(
2546 error,
2547 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2548 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2549 "%s: base64 stream string too small.",
2550 function );
2551
2552 return( -1 );
2553 }
2554 if( byte_stream == NULL )
2555 {
2556 libcerror_error_set(
2557 error,
2558 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2559 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2560 "%s: invalid byte stream.",
2561 function );
2562
2563 return( -1 );
2564 }
2565 if( byte_stream_size > (size_t) SSIZE_MAX )
2566 {
2567 libcerror_error_set(
2568 error,
2569 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2570 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2571 "%s: invalid byte stream size value exceeds maximum.",
2572 function );
2573
2574 return( -1 );
2575 }
2576 switch( base64_variant & 0x000000ffUL )
2577 {
2578 case LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_NONE:
2579 character_limit = 0;
2580
2581 break;
2582
2583 case LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_64:
2584 character_limit = 64;
2585
2586 break;
2587
2588 case LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_76:
2589 character_limit = 76;
2590
2591 break;
2592
2593 default:
2594 libcerror_error_set(
2595 error,
2596 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2597 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2598 "%s: unsupported base64 variant.",
2599 function );
2600
2601 return( -1 );
2602 }
2603 switch( base64_variant & 0x0f000000UL )
2604 {
2605 case LIBUNA_BASE64_VARIANT_PADDING_NONE:
2606 padding_character = 0;
2607 break;
2608
2609 case LIBUNA_BASE64_VARIANT_PADDING_OPTIONAL:
2610 padding_character = (uint8_t) '=';
2611 break;
2612
2613 case LIBUNA_BASE64_VARIANT_PADDING_REQUIRED:
2614 padding_character = (uint8_t) '=';
2615 break;
2616
2617 default:
2618 libcerror_error_set(
2619 error,
2620 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2621 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2622 "%s: unsupported base64 variant.",
2623 function );
2624
2625 return( -1 );
2626 }
2627 switch( base64_variant & 0xf0000000UL )
2628 {
2629 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
2630 base64_character_size = 1;
2631 break;
2632
2633 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
2634 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
2635 base64_character_size = 2;
2636 break;
2637
2638 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
2639 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
2640 base64_character_size = 4;
2641 break;
2642
2643 default:
2644 libcerror_error_set(
2645 error,
2646 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2647 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2648 "%s: unsupported base64 variant.",
2649 function );
2650
2651 return( -1 );
2652 }
2653 safe_base64_stream_index = *base64_stream_index;
2654
2655 /* Make sure the base64 stream is able to hold
2656 * at least 4 base64 characters for each 3 bytes
2657 */
2658 calculated_base64_stream_size = ( byte_stream_size / 3 ) * 4;
2659
2660 remaining_size = byte_stream_size % 3;
2661
2662 if( remaining_size != 0 )
2663 {
2664 if( padding_character != 0 )
2665 {
2666 calculated_base64_stream_size += 4;
2667 }
2668 else if( remaining_size == 1 )
2669 {
2670 calculated_base64_stream_size += 2;
2671 }
2672 else if( remaining_size == 2 )
2673 {
2674 calculated_base64_stream_size += 3;
2675 }
2676 }
2677 if( character_limit != 0 )
2678 {
2679 if( calculated_base64_stream_size > character_limit )
2680 {
2681 whitespace_size = calculated_base64_stream_size / character_limit;
2682
2683 if( ( calculated_base64_stream_size % character_limit ) != 0 )
2684 {
2685 whitespace_size += 1;
2686 }
2687 calculated_base64_stream_size += whitespace_size;
2688 }
2689 calculated_base64_stream_size += 1;
2690 }
2691 calculated_base64_stream_size *= base64_character_size;
2692
2693 if( base64_stream_size < calculated_base64_stream_size )
2694 {
2695 libcerror_error_set(
2696 error,
2697 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2698 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2699 "%s: base64 stream is too small.",
2700 function );
2701
2702 return( -1 );
2703 }
2704 while( byte_stream_index < byte_stream_size )
2705 {
2706 /* Convert the byte stream into a base64 triplet
2707 */
2708 if( libuna_base64_triplet_copy_from_byte_stream(
2709 &base64_triplet,
2710 byte_stream,
2711 byte_stream_size,
2712 &byte_stream_index,
2713 &padding_size,
2714 error ) != 1 )
2715 {
2716 libcerror_error_set(
2717 error,
2718 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2719 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2720 "%s: unable to copy base64 triplet from byte stream.",
2721 function );
2722
2723 return( -1 );
2724 }
2725 /* Convert the base64 triplet into a base64 stream
2726 */
2727 if( libuna_base64_triplet_copy_to_base64_stream(
2728 base64_triplet,
2729 base64_stream,
2730 base64_stream_size,
2731 &safe_base64_stream_index,
2732 padding_size,
2733 base64_variant,
2734 error ) != 1 )
2735 {
2736 libcerror_error_set(
2737 error,
2738 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2739 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2740 "%s: unable to copy base64 triplet to base64 stream.",
2741 function );
2742
2743 return( -1 );
2744 }
2745 if( character_limit != 0 )
2746 {
2747 number_of_characters += 4;
2748
2749 if( number_of_characters >= (size_t) character_limit )
2750 {
2751 base64_character = (uint32_t) '\n';
2752
2753 switch( base64_variant & 0xf0000000UL )
2754 {
2755 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
2756 base64_stream[ safe_base64_stream_index ] = (uint8_t) base64_character;
2757 break;
2758
2759 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
2760 byte_stream_copy_from_uint16_big_endian(
2761 &( base64_stream[ safe_base64_stream_index ] ),
2762 base64_character );
2763 break;
2764
2765 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
2766 byte_stream_copy_from_uint16_little_endian(
2767 &( base64_stream[ safe_base64_stream_index ] ),
2768 base64_character );
2769 break;
2770
2771 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
2772 byte_stream_copy_from_uint32_big_endian(
2773 &( base64_stream[ safe_base64_stream_index ] ),
2774 base64_character );
2775 break;
2776
2777 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
2778 byte_stream_copy_from_uint32_little_endian(
2779 &( base64_stream[ safe_base64_stream_index ] ),
2780 base64_character );
2781 break;
2782 }
2783 safe_base64_stream_index += base64_character_size;
2784
2785 number_of_characters = 0;
2786 }
2787 }
2788 }
2789 if( character_limit != 0 )
2790 {
2791 if( number_of_characters != 0 )
2792 {
2793 base64_character = (uint32_t) '\n';
2794
2795 switch( base64_variant & 0xf0000000UL )
2796 {
2797 case LIBUNA_BASE64_VARIANT_ENCODING_BYTE_STREAM:
2798 base64_stream[ safe_base64_stream_index ] = (uint8_t) base64_character;
2799 break;
2800
2801 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
2802 byte_stream_copy_from_uint16_big_endian(
2803 &( base64_stream[ safe_base64_stream_index ] ),
2804 base64_character );
2805 break;
2806
2807 case LIBUNA_BASE64_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
2808 byte_stream_copy_from_uint16_little_endian(
2809 &( base64_stream[ safe_base64_stream_index ] ),
2810 base64_character );
2811 break;
2812
2813 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
2814 byte_stream_copy_from_uint32_big_endian(
2815 &( base64_stream[ safe_base64_stream_index ] ),
2816 base64_character );
2817 break;
2818
2819 case LIBUNA_BASE64_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
2820 byte_stream_copy_from_uint32_little_endian(
2821 &( base64_stream[ safe_base64_stream_index ] ),
2822 base64_character );
2823 break;
2824 }
2825 safe_base64_stream_index += base64_character_size;
2826 }
2827 }
2828 *base64_stream_index = safe_base64_stream_index;
2829
2830 return( 1 );
2831 }
2832
2833