Coverage Report

Created: 2024-02-25 07:20

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