Coverage Report

Created: 2026-08-31 07:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libpff/libpff/libpff_data_array.c
Line
Count
Source
1
/*
2
 * Data array functions
3
 *
4
 * Copyright (C) 2008-2026, 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 <memory.h>
24
#include <types.h>
25
26
#include "libpff_data_array.h"
27
#include "libpff_data_array_entry.h"
28
#include "libpff_data_block.h"
29
#include "libpff_definitions.h"
30
#include "libpff_encryption.h"
31
#include "libpff_index_value.h"
32
#include "libpff_io_handle.h"
33
#include "libpff_libbfio.h"
34
#include "libpff_libcdata.h"
35
#include "libpff_libcerror.h"
36
#include "libpff_libcnotify.h"
37
#include "libpff_libfcache.h"
38
#include "libpff_libfdata.h"
39
#include "libpff_unused.h"
40
41
#include "pff_array.h"
42
43
/* Creates a data array
44
 * Make sure the value data_array is referencing, is set to NULL
45
 * Returns 1 if successful or -1 on error
46
 */
47
int libpff_data_array_initialize(
48
     libpff_data_array_t **data_array,
49
     libpff_io_handle_t *io_handle,
50
     uint32_t descriptor_identifier,
51
     uint64_t data_identifier,
52
     libcerror_error_t **error )
53
6.35k
{
54
6.35k
  static char *function = "libpff_data_array_initialize";
55
56
6.35k
  if( data_array == NULL )
57
0
  {
58
0
    libcerror_error_set(
59
0
     error,
60
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
61
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
62
0
     "%s: invalid data array.",
63
0
     function );
64
65
0
    return( -1 );
66
0
  }
67
6.35k
  if( *data_array != NULL )
68
0
  {
69
0
    libcerror_error_set(
70
0
     error,
71
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
72
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
73
0
     "%s: invalid data array value already set.",
74
0
     function );
75
76
0
    return( -1 );
77
0
  }
78
6.35k
  if( io_handle == NULL )
79
0
  {
80
0
    libcerror_error_set(
81
0
     error,
82
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
83
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
84
0
     "%s: invalid IO handle.",
85
0
     function );
86
87
0
    return( -1 );
88
0
  }
89
6.35k
  *data_array = memory_allocate_structure(
90
6.35k
                 libpff_data_array_t );
91
92
6.35k
  if( *data_array == NULL )
93
0
  {
94
0
    libcerror_error_set(
95
0
     error,
96
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
97
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
98
0
     "%s: unable to create data array.",
99
0
     function );
100
101
0
    goto on_error;
102
0
  }
103
6.35k
  if( memory_set(
104
6.35k
       *data_array,
105
6.35k
       0,
106
6.35k
       sizeof( libpff_data_array_t ) ) == NULL )
107
0
  {
108
0
    libcerror_error_set(
109
0
     error,
110
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
111
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
112
0
     "%s: unable to clear data array.",
113
0
     function );
114
115
0
    goto on_error;
116
0
  }
117
6.35k
  if( libcdata_array_initialize(
118
6.35k
       &( ( *data_array )->entries ),
119
6.35k
       0,
120
6.35k
       error ) != 1 )
121
0
  {
122
0
    libcerror_error_set(
123
0
     error,
124
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
125
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
126
0
     "%s: unable to create data array entries array.",
127
0
     function );
128
129
0
    goto on_error;
130
0
  }
131
6.35k
  ( *data_array )->descriptor_identifier = descriptor_identifier;
132
6.35k
  ( *data_array )->data_identifier       = data_identifier;
133
6.35k
  ( *data_array )->io_handle             = io_handle;
134
135
6.35k
  return( 1 );
136
137
0
on_error:
138
0
  if( *data_array != NULL )
139
0
  {
140
0
    memory_free(
141
0
     *data_array );
142
143
0
    *data_array = NULL;
144
0
  }
145
0
  return( -1 );
146
6.35k
}
147
148
/* Frees a data array
149
 * Returns 1 if successful or -1 on error
150
 */
151
int libpff_data_array_free(
152
     libpff_data_array_t **data_array,
153
     libcerror_error_t **error )
154
6.35k
{
155
6.35k
  static char *function = "libpff_data_array_free";
156
6.35k
  int result            = 1;
157
158
6.35k
  if( data_array == NULL )
159
0
  {
160
0
    libcerror_error_set(
161
0
     error,
162
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
163
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
164
0
     "%s: invalid data array.",
165
0
     function );
166
167
0
    return( -1 );
168
0
  }
169
6.35k
  if( *data_array != NULL )
170
6.35k
  {
171
6.35k
    if( libcdata_array_free(
172
6.35k
         &( ( *data_array )->entries ),
173
6.35k
         (int (*)(intptr_t **, libcerror_error_t **)) &libpff_data_array_entry_free,
174
6.35k
         error ) != 1 )
175
0
    {
176
0
      libcerror_error_set(
177
0
       error,
178
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
179
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
180
0
       "%s: unable to free the data array entries array.",
181
0
       function );
182
183
0
      result = -1;
184
0
    }
185
6.35k
    memory_free(
186
6.35k
     *data_array );
187
188
6.35k
    *data_array = NULL;
189
6.35k
  }
190
6.35k
  return( result );
191
6.35k
}
192
193
/* Clones the data array
194
 * Returns 1 if successful or -1 on error
195
 */
196
int libpff_data_array_clone(
197
     libpff_data_array_t **destination_data_array,
198
     libpff_data_array_t *source_data_array,
199
     libcerror_error_t **error )
200
0
{
201
0
  static char *function = "libpff_data_array_clone";
202
203
0
  if( destination_data_array == NULL )
204
0
  {
205
0
    libcerror_error_set(
206
0
     error,
207
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
208
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
209
0
     "%s: invalid destination data array.",
210
0
     function );
211
212
0
    return( -1 );
213
0
  }
214
0
  if( *destination_data_array != NULL )
215
0
  {
216
0
    libcerror_error_set(
217
0
     error,
218
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
219
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
220
0
     "%s: invalid destination data array already set.",
221
0
     function );
222
223
0
    return( -1 );
224
0
  }
225
0
  if( source_data_array == NULL )
226
0
  {
227
0
    *destination_data_array = NULL;
228
229
0
    return( 1 );
230
0
  }
231
0
  *destination_data_array = memory_allocate_structure(
232
0
                             libpff_data_array_t );
233
234
0
  if( *destination_data_array == NULL )
235
0
  {
236
0
    libcerror_error_set(
237
0
     error,
238
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
239
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
240
0
     "%s: unable to create destination data array.",
241
0
     function );
242
243
0
    goto on_error;
244
0
  }
245
0
  if( memory_set(
246
0
       *destination_data_array,
247
0
       0,
248
0
       sizeof( libpff_data_array_t ) ) == NULL )
249
0
  {
250
0
    libcerror_error_set(
251
0
     error,
252
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
253
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
254
0
     "%s: unable to clear destination data array.",
255
0
     function );
256
257
0
    goto on_error;
258
0
  }
259
0
  ( *destination_data_array )->descriptor_identifier = source_data_array->descriptor_identifier;
260
0
  ( *destination_data_array )->data_identifier       = source_data_array->data_identifier;
261
0
  ( *destination_data_array )->io_handle             = source_data_array->io_handle;
262
0
  ( *destination_data_array )->data_size             = source_data_array->data_size;
263
0
  ( *destination_data_array )->flags                 = source_data_array->flags;
264
265
0
  if( libcdata_array_clone(
266
0
       &( ( *destination_data_array )->entries ),
267
0
       source_data_array->entries,
268
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libpff_data_array_entry_free,
269
0
       (int (*)(intptr_t **, intptr_t *, libcerror_error_t **)) &libpff_data_array_entry_clone,
270
0
       error ) != 1 )
271
0
  {
272
0
    libcerror_error_set(
273
0
     error,
274
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
275
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
276
0
     "%s: unable to clone local descriptors.",
277
0
     function );
278
279
0
    goto on_error;
280
0
  }
281
0
  return( 1 );
282
283
0
on_error:
284
0
  if( *destination_data_array != NULL )
285
0
  {
286
0
    memory_free(
287
0
     *destination_data_array );
288
289
0
    *destination_data_array = NULL;
290
0
  }
291
0
  return( -1 );
292
0
}
293
294
/* Reads the data array entries
295
 * Returns 1 if successful or -1 on error
296
 */
297
int libpff_data_array_read_entries(
298
     libpff_data_array_t *data_array,
299
     libpff_io_handle_t *io_handle,
300
     libbfio_handle_t *file_io_handle,
301
     libpff_offsets_index_t *offsets_index,
302
     libfdata_list_t *descriptor_data_list,
303
     uint8_t recovered,
304
     uint8_t *array_data,
305
     size_t array_data_size,
306
     uint32_t *total_data_size,
307
     int recursion_depth,
308
     libcerror_error_t **error )
309
153k
{
310
153k
  libpff_data_array_entry_t *data_array_entry = NULL;
311
153k
  libpff_data_block_t *data_block             = NULL;
312
153k
  libpff_index_value_t *offset_index_value    = NULL;
313
153k
  static char *function                       = "libpff_data_array_read_entries";
314
153k
  size_t array_entry_data_size                = 0;
315
153k
  uint64_t array_entry_identifier             = 0;
316
153k
  uint32_t calculated_total_data_size         = 0;
317
153k
  uint32_t sub_total_data_size                = 0;
318
153k
  uint16_t array_entry_index                  = 0;
319
153k
  uint16_t number_of_array_entries            = 0;
320
153k
  uint8_t array_entries_level                 = 0;
321
153k
  int element_index                           = 0;
322
153k
  int previous_number_of_data_array_entries   = 0;
323
324
153k
  if( io_handle == NULL )
325
0
  {
326
0
    libcerror_error_set(
327
0
     error,
328
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
329
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
330
0
     "%s: invalid IO handle.",
331
0
     function );
332
333
0
    return( -1 );
334
0
  }
335
153k
  if( data_array == NULL )
336
0
  {
337
0
    libcerror_error_set(
338
0
     error,
339
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
340
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
341
0
     "%s: invalid data array.",
342
0
     function );
343
344
0
    return( -1 );
345
0
  }
346
153k
  if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT )
347
129k
   && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT )
348
0
   && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
349
0
  {
350
0
    libcerror_error_set(
351
0
     error,
352
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
353
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
354
0
     "%s: unsupported file type.",
355
0
     function );
356
357
0
    return( -1 );
358
0
  }
359
153k
  if( array_data == NULL )
360
249
  {
361
249
    libcerror_error_set(
362
249
     error,
363
249
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
364
249
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
365
249
     "%s: invalid array data.",
366
249
     function );
367
368
249
    return( -1 );
369
249
  }
370
153k
  if( ( array_data_size < sizeof( pff_array_t ) )
371
152k
   || ( array_data_size > (size_t) SSIZE_MAX ) )
372
413
  {
373
413
    libcerror_error_set(
374
413
     error,
375
413
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
376
413
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
377
413
     "%s: invalid array data size value out of bounds.",
378
413
     function );
379
380
413
    return( -1 );
381
413
  }
382
152k
  if( total_data_size == NULL )
383
0
  {
384
0
    libcerror_error_set(
385
0
     error,
386
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
387
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
388
0
     "%s: invalid total data size.",
389
0
     function );
390
391
0
    return( -1 );
392
0
  }
393
152k
  if( ( recursion_depth < 0 )
394
152k
   || ( recursion_depth > LIBPFF_MAXIMUM_DATA_ARRAY_RECURSION_DEPTH ) )
395
564
  {
396
564
    libcerror_error_set(
397
564
     error,
398
564
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
399
564
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
400
564
     "%s: invalid recursion depth value out of bounds.",
401
564
     function );
402
403
564
    return( -1 );
404
564
  }
405
#if defined( HAVE_DEBUG_OUTPUT )
406
  if( libcnotify_verbose != 0 )
407
  {
408
    libcnotify_printf(
409
     "%s: array:\n",
410
     function );
411
    libcnotify_print_data(
412
     array_data,
413
     array_data_size,
414
     0 );
415
  }
416
#endif
417
152k
  if( ( (pff_array_t *) array_data )->signature != 0x01 )
418
403
  {
419
403
    libcerror_error_set(
420
403
     error,
421
403
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
422
403
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
423
403
     "%s: unsupported array signature.",
424
403
     function );
425
426
403
    goto on_error;
427
403
  }
428
151k
  array_entries_level = ( (pff_array_t *) array_data )->array_entries_level;
429
430
151k
  byte_stream_copy_to_uint16_little_endian(
431
151k
   ( (pff_array_t *) array_data )->number_of_entries,
432
151k
   number_of_array_entries );
433
151k
  byte_stream_copy_to_uint32_little_endian(
434
151k
   ( (pff_array_t *) array_data )->total_data_size,
435
151k
   *total_data_size );
436
437
151k
  array_data      += sizeof( pff_array_t );
438
151k
  array_data_size -= sizeof( pff_array_t );
439
440
#if defined( HAVE_DEBUG_OUTPUT )
441
  if( libcnotify_verbose != 0 )
442
  {
443
    libcnotify_printf(
444
     "%s: array entries level\t\t\t: %" PRIu8 "\n",
445
     function,
446
     array_entries_level );
447
448
    libcnotify_printf(
449
     "%s: array number of entries\t\t\t: %" PRIu16 "\n",
450
     function,
451
     number_of_array_entries );
452
453
    libcnotify_printf(
454
     "%s: array total data size\t\t\t: %" PRIu32 "\n",
455
     function,
456
     *total_data_size );
457
458
    libcnotify_printf(
459
     "\n" );
460
  }
461
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
462
463
151k
  if( array_entries_level == 0 )
464
164
  {
465
164
    libcerror_error_set(
466
164
     error,
467
164
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
468
164
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
469
164
     "%s: unsupported array entries level: 0.",
470
164
     function );
471
472
164
    goto on_error;
473
164
  }
474
151k
  if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
475
24.1k
  {
476
24.1k
    array_entry_data_size = 4;
477
24.1k
  }
478
127k
  else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
479
0
        || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
480
127k
  {
481
127k
    array_entry_data_size = 8;
482
127k
  }
483
151k
  if( ( (size_t) number_of_array_entries * array_entry_data_size ) > array_data_size )
484
440
  {
485
440
    libcerror_error_set(
486
440
     error,
487
440
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
488
440
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
489
440
     "%s: invalid number of array entries value out of bounds.",
490
440
     function );
491
492
440
    goto on_error;
493
440
  }
494
151k
  if( data_array->data_size == 0 )
495
43.8k
  {
496
43.8k
    data_array->data_size = *total_data_size;
497
43.8k
  }
498
151k
  if( libcdata_array_get_number_of_entries(
499
151k
       data_array->entries,
500
151k
       &previous_number_of_data_array_entries,
501
151k
       error ) != 1 )
502
0
  {
503
0
    libcerror_error_set(
504
0
     error,
505
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
506
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
507
0
     "%s: unable to retrieve the number of data array entries.",
508
0
     function );
509
510
0
    goto on_error;
511
0
  }
512
151k
  if( array_entries_level == 1 )
513
3.98k
  {
514
3.98k
    if( libfdata_list_resize(
515
3.98k
         descriptor_data_list,
516
3.98k
         previous_number_of_data_array_entries + (int) number_of_array_entries,
517
3.98k
         error ) != 1 )
518
0
    {
519
0
      libcerror_error_set(
520
0
       error,
521
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
522
0
       LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
523
0
       "%s: unable to resize descriptor data list.",
524
0
       function );
525
526
0
      goto on_error;
527
0
    }
528
3.98k
    if( libcdata_array_resize(
529
3.98k
         data_array->entries,
530
3.98k
         previous_number_of_data_array_entries + (int) number_of_array_entries,
531
3.98k
         (int (*)(intptr_t **, libcerror_error_t **)) &libpff_data_array_entry_free,
532
3.98k
         error ) != 1 )
533
0
    {
534
0
      libcerror_error_set(
535
0
       error,
536
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
537
0
       LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
538
0
       "%s: unable to resize data array entries array.",
539
0
       function );
540
541
0
      goto on_error;
542
0
    }
543
3.98k
  }
544
151k
  element_index = previous_number_of_data_array_entries;
545
546
151k
  for( array_entry_index = 0;
547
156k
       array_entry_index < number_of_array_entries;
548
151k
       array_entry_index++ )
549
152k
  {
550
152k
    if( array_entry_data_size == 4 )
551
24.2k
    {
552
24.2k
      byte_stream_copy_to_uint32_little_endian(
553
24.2k
       array_data,
554
24.2k
       array_entry_identifier );
555
24.2k
    }
556
128k
    else if( array_entry_data_size == 8 )
557
128k
    {
558
128k
      byte_stream_copy_to_uint64_little_endian(
559
128k
       array_data,
560
128k
       array_entry_identifier );
561
128k
    }
562
152k
    array_data += array_entry_data_size;
563
564
/* TODO handle multiple recovered offset index values */
565
152k
    if( libpff_offsets_index_get_index_value_by_identifier(
566
152k
         offsets_index,
567
152k
         io_handle,
568
152k
         file_io_handle,
569
152k
         array_entry_identifier,
570
152k
         recovered,
571
152k
         0,
572
152k
         &offset_index_value,
573
152k
         error ) != 1 )
574
705
    {
575
705
      libcerror_error_set(
576
705
       error,
577
705
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
578
705
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
579
705
       "%s: unable to find data identifier: %" PRIu64 ".",
580
705
       function,
581
705
       array_entry_identifier );
582
583
705
      goto on_error;
584
705
    }
585
152k
    if( offset_index_value == NULL )
586
0
    {
587
0
      libcerror_error_set(
588
0
       error,
589
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
590
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
591
0
       "%s: missing offset index value: %" PRIu64 ".",
592
0
       function,
593
0
       array_entry_identifier );
594
595
0
      goto on_error;
596
0
    }
597
#if defined( HAVE_DEBUG_OUTPUT )
598
    if( libcnotify_verbose != 0 )
599
    {
600
      libcnotify_printf(
601
       "%s: array entry: %03" PRIu16 " at level: %" PRIu8 " identifier: %" PRIu64 " (%s) at offset: 0x%08" PRIx64 " of size: %" PRIu32 "\n",
602
       function,
603
       array_entry_index,
604
       array_entries_level,
605
       offset_index_value->identifier,
606
       ( ( offset_index_value->identifier & LIBPFF_OFFSET_INDEX_IDENTIFIER_FLAG_INTERNAL ) ? "internal" : "external" ),
607
       offset_index_value->file_offset,
608
       offset_index_value->data_size );
609
    }
610
#endif
611
152k
    if( offset_index_value->file_offset < 0 )
612
0
    {
613
0
      libcerror_error_set(
614
0
       error,
615
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
616
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
617
0
       "%s: invalid file offset value out of bounds.",
618
0
       function );
619
620
0
      goto on_error;
621
0
    }
622
#if UINT32_MAX > SSIZE_MAX
623
    if( offset_index_value->data_size > (size32_t) SSIZE_MAX )
624
    {
625
      libcerror_error_set(
626
       error,
627
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
628
       LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
629
       "%s: data size value exceeds maximum.",
630
       function );
631
632
      goto on_error;
633
    }
634
#endif
635
    /* The data block uses the identifier as the back pointer
636
     */
637
152k
    if( libpff_data_block_initialize(
638
152k
         &data_block,
639
152k
         io_handle,
640
152k
         data_array->descriptor_identifier,
641
152k
         offset_index_value->identifier,
642
152k
         error ) != 1 )
643
0
    {
644
0
      libcerror_error_set(
645
0
       error,
646
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
647
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
648
0
       "%s: unable to create data block.",
649
0
       function );
650
651
0
      goto on_error;
652
0
    }
653
152k
    if( libpff_data_block_read_file_io_handle(
654
152k
         data_block,
655
152k
         file_io_handle,
656
152k
         offset_index_value->file_offset,
657
152k
         offset_index_value->data_size,
658
152k
         io_handle->file_type,
659
152k
         error ) != 1 )
660
523
    {
661
523
      libcerror_error_set(
662
523
       error,
663
523
       LIBCERROR_ERROR_DOMAIN_IO,
664
523
       LIBCERROR_IO_ERROR_READ_FAILED,
665
523
       "%s: unable to read data block.",
666
523
       function );
667
668
523
      goto on_error;
669
523
    }
670
151k
    if( array_entries_level == 1 )
671
4.70k
    {
672
4.70k
      calculated_total_data_size += data_block->uncompressed_data_size;
673
674
4.70k
      if( calculated_total_data_size > data_array->data_size )
675
427
      {
676
427
        libcerror_error_set(
677
427
         error,
678
427
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
679
427
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
680
427
         "%s: data size: %" PRIu32 " exceeds total data size: %" PRIu32 ".",
681
427
         function,
682
427
         calculated_total_data_size,
683
427
         data_array->data_size );
684
685
427
        goto on_error;
686
427
      }
687
/* TODO replace separate function calls by libfdata_list_set_element_by_index_with_mapped_size */
688
4.27k
      if( libfdata_list_set_element_by_index(
689
4.27k
           descriptor_data_list,
690
4.27k
           element_index,
691
4.27k
           0,
692
4.27k
           offset_index_value->file_offset,
693
4.27k
           (size64_t) offset_index_value->data_size,
694
4.27k
           0,
695
4.27k
           error ) != 1 )
696
0
      {
697
0
        libcerror_error_set(
698
0
         error,
699
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
700
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
701
0
         "%s: unable to set descriptor data list element: %d.",
702
0
         function,
703
0
         element_index );
704
705
0
        goto on_error;
706
0
      }
707
4.27k
      if( libfdata_list_set_mapped_size_by_index(
708
4.27k
           descriptor_data_list,
709
4.27k
           element_index,
710
4.27k
           (size64_t) data_block->uncompressed_data_size,
711
4.27k
           error ) != 1 )
712
0
      {
713
0
        libcerror_error_set(
714
0
         error,
715
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
716
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
717
0
         "%s: unable to set descriptor data list element: %d mapped size.",
718
0
         function,
719
0
         element_index );
720
721
0
        goto on_error;
722
0
      }
723
4.27k
      if( libpff_data_array_entry_initialize(
724
4.27k
           &data_array_entry,
725
4.27k
           error ) != 1 )
726
0
      {
727
0
        libcerror_error_set(
728
0
         error,
729
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
730
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
731
0
         "%s: unable to create data array entry.",
732
0
         function );
733
734
0
        goto on_error;
735
0
      }
736
4.27k
      data_array_entry->data_identifier = offset_index_value->identifier;
737
738
4.27k
      if( libcdata_array_set_entry_by_index(
739
4.27k
           data_array->entries,
740
4.27k
           element_index,
741
4.27k
           (intptr_t *) data_array_entry,
742
4.27k
           error ) != 1 )
743
0
      {
744
0
        libcerror_error_set(
745
0
         error,
746
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
747
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
748
0
         "%s: unable to set data array entry: %d.",
749
0
         function,
750
0
         element_index );
751
752
0
        goto on_error;
753
0
      }
754
4.27k
      data_array_entry = NULL;
755
4.27k
    }
756
146k
    else
757
146k
    {
758
146k
      if( libpff_data_array_read_entries(
759
146k
           data_array,
760
146k
           io_handle,
761
146k
           file_io_handle,
762
146k
           offsets_index,
763
146k
           descriptor_data_list,
764
146k
           recovered,
765
146k
           data_block->data,
766
146k
           data_block->data_size,
767
146k
           &sub_total_data_size,
768
146k
           recursion_depth + 1,
769
146k
           error ) != 1 )
770
145k
      {
771
145k
        libcerror_error_set(
772
145k
         error,
773
145k
         LIBCERROR_ERROR_DOMAIN_IO,
774
145k
         LIBCERROR_IO_ERROR_READ_FAILED,
775
145k
         "%s: unable to read data block.",
776
145k
         function );
777
778
145k
        goto on_error;
779
145k
      }
780
1.06k
      calculated_total_data_size += sub_total_data_size;
781
1.06k
    }
782
5.34k
    if( libpff_data_block_free(
783
5.34k
         &data_block,
784
5.34k
         error ) != 1 )
785
0
    {
786
0
      libcerror_error_set(
787
0
       error,
788
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
789
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
790
0
       "%s: unable to free data block.",
791
0
       function );
792
793
0
      goto on_error;
794
0
    }
795
5.34k
    if( libpff_index_value_free(
796
5.34k
         &offset_index_value,
797
5.34k
         error ) != 1 )
798
0
    {
799
0
      libcerror_error_set(
800
0
       error,
801
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
802
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
803
0
       "%s: unable to free offsets index value.",
804
0
       function );
805
806
0
      goto on_error;
807
0
    }
808
5.34k
    element_index++;
809
5.34k
  }
810
3.53k
  if( *total_data_size != calculated_total_data_size )
811
858
  {
812
858
    libcerror_error_set(
813
858
     error,
814
858
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
815
858
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
816
858
     "%s: mismatch in total data size (%" PRIu32 " != %" PRIu32 ").",
817
858
     function,
818
858
     *total_data_size,
819
858
     calculated_total_data_size );
820
821
858
    goto on_error;
822
858
  }
823
2.67k
  return( 1 );
824
825
149k
on_error:
826
149k
  if( data_block != NULL )
827
146k
  {
828
146k
    libpff_data_block_free(
829
146k
     &data_block,
830
146k
     NULL );
831
146k
  }
832
149k
  if( data_array_entry != NULL )
833
0
  {
834
0
    libpff_data_array_entry_free(
835
0
     &data_array_entry,
836
0
     NULL );
837
0
  }
838
149k
  if( offset_index_value != NULL )
839
146k
  {
840
146k
    libpff_index_value_free(
841
146k
     &offset_index_value,
842
146k
     NULL );
843
146k
  }
844
149k
  return( -1 );
845
3.53k
}
846
847
/* Reads the data array element data
848
 * Callback for the descriptor data list
849
 * Returns the number of bytes read if successful or -1 on error
850
 */
851
int libpff_data_array_read_element_data(
852
     libpff_data_array_t *data_array,
853
     libbfio_handle_t *file_io_handle,
854
     libfdata_list_element_t *list_element,
855
     libfcache_cache_t *cache,
856
     int element_file_index LIBPFF_ATTRIBUTE_UNUSED,
857
     off64_t element_offset,
858
     size64_t element_size,
859
     uint32_t element_flags LIBPFF_ATTRIBUTE_UNUSED,
860
     uint8_t read_flags,
861
     libcerror_error_t **error )
862
1.48k
{
863
1.48k
  libpff_data_array_entry_t *data_array_entry = NULL;
864
1.48k
  libpff_data_block_t *data_block             = NULL;
865
1.48k
  static char *function                       = "libpff_data_array_read_element_data";
866
1.48k
  int element_index                           = 0;
867
868
1.48k
  LIBPFF_UNREFERENCED_PARAMETER( element_file_index )
869
1.48k
  LIBPFF_UNREFERENCED_PARAMETER( element_flags )
870
871
1.48k
  if( data_array == NULL )
872
0
  {
873
0
    libcerror_error_set(
874
0
     error,
875
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
876
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
877
0
     "%s: invalid data array.",
878
0
     function );
879
880
0
    return( -1 );
881
0
  }
882
1.48k
  if( data_array->io_handle == NULL )
883
0
  {
884
0
    libcerror_error_set(
885
0
     error,
886
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
887
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
888
0
     "%s: invalid data array - missing IO handle.",
889
0
     function );
890
891
0
    return( -1 );
892
0
  }
893
1.48k
  if( element_size > (size64_t) UINT32_MAX )
894
0
  {
895
0
    libcerror_error_set(
896
0
     error,
897
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
898
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
899
0
     "%s: invalid element size value exceeds maximum.\n",
900
0
     function );
901
902
0
    return( -1 );
903
0
  }
904
1.48k
  if( libfdata_list_element_get_element_index(
905
1.48k
       list_element,
906
1.48k
       &element_index,
907
1.48k
       error ) != 1 )
908
0
  {
909
0
    libcerror_error_set(
910
0
     error,
911
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
912
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
913
0
     "%s: unable to retrieve element index.",
914
0
     function );
915
916
0
    goto on_error;
917
0
  }
918
1.48k
  if( libcdata_array_get_entry_by_index(
919
1.48k
       data_array->entries,
920
1.48k
       element_index,
921
1.48k
       (intptr_t **) &data_array_entry,
922
1.48k
       error ) != 1 )
923
0
  {
924
0
    libcerror_error_set(
925
0
     error,
926
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
927
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
928
0
     "%s: unable to retrieve data array entry: %d.",
929
0
     function,
930
0
     element_index );
931
932
0
    goto on_error;
933
0
  }
934
1.48k
  if( data_array_entry == NULL )
935
0
  {
936
0
    libcerror_error_set(
937
0
     error,
938
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
939
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
940
0
     "%s: missing data array entry.",
941
0
     function );
942
943
0
    goto on_error;
944
0
  }
945
1.48k
  if( libpff_data_block_initialize(
946
1.48k
       &data_block,
947
1.48k
       data_array->io_handle,
948
1.48k
       data_array->descriptor_identifier,
949
1.48k
       data_array_entry->data_identifier,
950
1.48k
       error ) != 1 )
951
0
  {
952
0
    libcerror_error_set(
953
0
     error,
954
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
955
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
956
0
     "%s: unable to create data block.",
957
0
     function );
958
959
0
    goto on_error;
960
0
  }
961
1.48k
  if( libpff_data_block_read_file_io_handle(
962
1.48k
       data_block,
963
1.48k
       file_io_handle,
964
1.48k
       element_offset,
965
1.48k
       (size32_t) element_size,
966
1.48k
       data_array->io_handle->file_type,
967
1.48k
       error ) != 1 )
968
0
  {
969
0
    libcerror_error_set(
970
0
     error,
971
0
     LIBCERROR_ERROR_DOMAIN_IO,
972
0
     LIBCERROR_IO_ERROR_READ_FAILED,
973
0
     "%s: unable to read data block.",
974
0
     function );
975
976
0
    goto on_error;
977
0
  }
978
/* TODO move function into data block ? */
979
1.48k
  if( libpff_data_array_decrypt_entry_data(
980
1.48k
       data_array,
981
1.48k
       element_index,
982
1.48k
       data_array->io_handle->encryption_type,
983
1.48k
       data_block->data,
984
1.48k
       (size_t) element_size,
985
1.48k
       read_flags,
986
1.48k
       error ) != 1 )
987
39
  {
988
39
    libcerror_error_set(
989
39
     error,
990
39
     LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
991
39
     LIBCERROR_ENCRYPTION_ERROR_DECRYPT_FAILED,
992
39
     "%s: unable to decrypt data array entry: %d data.",
993
39
     function,
994
39
     element_index );
995
996
39
    goto on_error;
997
39
  }
998
1.45k
  if( libfdata_list_element_set_element_value(
999
1.45k
       list_element,
1000
1.45k
       (intptr_t *) file_io_handle,
1001
1.45k
       (libfdata_cache_t *) cache,
1002
1.45k
       (intptr_t *) data_block,
1003
1.45k
       (int (*)(intptr_t **, libcerror_error_t **)) &libpff_data_block_free,
1004
1.45k
       LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
1005
1.45k
       error ) != 1 )
1006
0
  {
1007
0
    libcerror_error_set(
1008
0
     error,
1009
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1010
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1011
0
     "%s: unable to set data block as element value.",
1012
0
     function );
1013
1014
0
    goto on_error;
1015
0
  }
1016
1.45k
  return( 1 );
1017
1018
39
on_error:
1019
39
  if( data_block != NULL )
1020
39
  {
1021
39
    libpff_data_block_free(
1022
39
     &data_block,
1023
39
     NULL );
1024
39
  }
1025
39
  return( -1 );
1026
1.45k
}
1027
1028
/* Decrypts the data array entry data
1029
 * Returns 1 if successful or -1 on error
1030
 */
1031
int libpff_data_array_decrypt_entry_data(
1032
     libpff_data_array_t *data_array,
1033
     int array_entry_index,
1034
     uint8_t encryption_type,
1035
     uint8_t *data,
1036
     size_t data_size,
1037
     uint8_t read_flags,
1038
     libcerror_error_t **error )
1039
1.48k
{
1040
1.48k
  libpff_data_array_entry_t *data_array_entry = NULL;
1041
1.48k
  static char *function                       = "libpff_data_array_decrypt_entry_data";
1042
1.48k
  ssize_t process_count                       = 0;
1043
1.48k
  uint16_t table_index_offset                 = 0;
1044
1.48k
  uint8_t decrypt_data                        = 0;
1045
1.48k
  uint8_t force_decryption                    = 0;
1046
1.48k
  uint8_t node_identifier_type                = 0;
1047
1.48k
  uint8_t node_contains_table                 = 0;
1048
1.48k
  int number_of_data_array_entries            = 0;
1049
1050
1.48k
  if( data_array == NULL )
1051
0
  {
1052
0
    libcerror_error_set(
1053
0
     error,
1054
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1055
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1056
0
     "%s: invalid data array.",
1057
0
     function );
1058
1059
0
    return( -1 );
1060
0
  }
1061
1.48k
  if( data == NULL )
1062
39
  {
1063
39
    libcerror_error_set(
1064
39
     error,
1065
39
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1066
39
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1067
39
     "%s: invalid data.",
1068
39
     function );
1069
1070
39
    return( -1 );
1071
39
  }
1072
1.45k
  if( data_size > (size_t) SSIZE_MAX )
1073
0
  {
1074
0
    libcerror_error_set(
1075
0
     error,
1076
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1077
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1078
0
     "%s: invalid data size value exceeds maximum.",
1079
0
     function );
1080
1081
0
    return( -1 );
1082
0
  }
1083
1.45k
  if( libcdata_array_get_number_of_entries(
1084
1.45k
       data_array->entries,
1085
1.45k
       &number_of_data_array_entries,
1086
1.45k
       error ) != 1 )
1087
0
  {
1088
0
    libcerror_error_set(
1089
0
     error,
1090
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1091
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1092
0
     "%s: unable to retrieve the number of data array entries.",
1093
0
     function );
1094
1095
0
    return( -1 );
1096
0
  }
1097
1.45k
  if( libcdata_array_get_entry_by_index(
1098
1.45k
       data_array->entries,
1099
1.45k
       array_entry_index,
1100
1.45k
       (intptr_t **) &data_array_entry,
1101
1.45k
       error ) != 1 )
1102
0
  {
1103
0
    libcerror_error_set(
1104
0
     error,
1105
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1106
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1107
0
     "%s: unable to retrieve data array entry: %d.",
1108
0
     function,
1109
0
     array_entry_index );
1110
1111
0
    return( -1 );
1112
0
  }
1113
1.45k
  if( data_array_entry == NULL )
1114
0
  {
1115
0
    libcerror_error_set(
1116
0
     error,
1117
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1118
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1119
0
     "%s: missing data array entry.",
1120
0
     function );
1121
1122
0
    return( -1 );
1123
0
  }
1124
  /* Check if the internal (unencrypted) flag in (data) offset index identifier is not set
1125
   */
1126
1.45k
  if( ( data_array_entry->data_identifier & LIBPFF_OFFSET_INDEX_IDENTIFIER_FLAG_INTERNAL ) == 0 )
1127
492
  {
1128
492
    decrypt_data = 1;
1129
492
  }
1130
  /* Check if data is encrypted
1131
   * Some 'invalid' files have an encryption type of none but contain encrypted data
1132
   * Although they are considered invalid by Outlook it is still possilble to read them
1133
   */
1134
1.45k
  if( ( encryption_type == LIBPFF_ENCRYPTION_TYPE_NONE )
1135
368
   && ( ( read_flags & LIBPFF_READ_FLAG_IGNORE_FORCE_DECRYPTION ) == 0 )
1136
368
   && ( data_size > 4 ) )
1137
363
  {
1138
363
    node_identifier_type = (uint8_t) ( data_array->descriptor_identifier & 0x0000001fUL );
1139
1140
363
    if( ( ( node_identifier_type == LIBPFF_NODE_IDENTIFIER_TYPE_INTERNAL )
1141
284
      && ( ( data_array->descriptor_identifier == LIBPFF_DESCRIPTOR_IDENTIFIER_MESSAGE_STORE )
1142
284
       || ( data_array->descriptor_identifier == LIBPFF_DESCRIPTOR_IDENTIFIER_NAME_TO_ID_MAP )
1143
0
       || ( data_array->descriptor_identifier == LIBPFF_DESCRIPTOR_IDENTIFIER_UNKNOWN_2049 )
1144
0
       || ( data_array->descriptor_identifier == LIBPFF_DESCRIPTOR_IDENTIFIER_UNKNOWN_2081 )
1145
0
       || ( data_array->descriptor_identifier == LIBPFF_DESCRIPTOR_IDENTIFIER_UNKNOWN_2113 )
1146
0
       || ( data_array->descriptor_identifier == LIBPFF_DESCRIPTOR_IDENTIFIER_UNKNOWN_3073 ) ) )
1147
79
     || ( node_identifier_type == LIBPFF_NODE_IDENTIFIER_TYPE_FOLDER )
1148
77
     || ( node_identifier_type == LIBPFF_NODE_IDENTIFIER_TYPE_SEARCH_FOLDER )
1149
55
     || ( node_identifier_type == LIBPFF_NODE_IDENTIFIER_TYPE_MESSAGE )
1150
55
     || ( node_identifier_type == LIBPFF_NODE_IDENTIFIER_TYPE_ASSOCIATED_CONTENT )
1151
55
     || ( node_identifier_type == LIBPFF_NODE_IDENTIFIER_TYPE_SUB_FOLDERS )
1152
54
     || ( node_identifier_type == LIBPFF_NODE_IDENTIFIER_TYPE_SUB_MESSAGES )
1153
54
     || ( node_identifier_type == LIBPFF_NODE_IDENTIFIER_TYPE_SUB_ASSOCIATED_CONTENTS )
1154
54
     || ( node_identifier_type == LIBPFF_NODE_IDENTIFIER_TYPE_SEARCH_CONTENTS_TABLE )
1155
54
     || ( node_identifier_type == LIBPFF_NODE_IDENTIFIER_TYPE_ATTACHMENTS )
1156
54
     || ( node_identifier_type == LIBPFF_NODE_IDENTIFIER_TYPE_RECIPIENTS )
1157
54
     || ( node_identifier_type == LIBPFF_NODE_IDENTIFIER_TYPE_UNKNOWN_1718 )
1158
54
     || ( node_identifier_type == LIBPFF_NODE_IDENTIFIER_TYPE_UNKNOWN_1751 )
1159
54
     || ( node_identifier_type == LIBPFF_NODE_IDENTIFIER_TYPE_UNKNOWN_1784 ) )
1160
309
    {
1161
309
      node_contains_table = 1;
1162
309
    }
1163
    /* Only check the first entry
1164
     * some table array contain the table type in every array entry but not all
1165
     */
1166
363
    if( ( array_entry_index == 0 )
1167
327
     && ( node_contains_table != 0 ) )
1168
298
    {
1169
      /* Test if the data contains an unencrypted table
1170
       * a table consists of 0xec in the third byte
1171
       * and 0x6c, 0x7c, 0x8c, 0x9c, 0xa5, 0xac, 0xbc, 0xcc in the fourth
1172
       */
1173
298
      if( ( data[ 2 ] != 0xec )
1174
110
       || ( ( data[ 3 ] != 0x6c )
1175
107
        &&  ( data[ 3 ] != 0x7c )
1176
104
        &&  ( data[ 3 ] != 0x8c )
1177
101
        &&  ( data[ 3 ] != 0x9c )
1178
98
        &&  ( data[ 3 ] != 0xa5 )
1179
95
        &&  ( data[ 3 ] != 0xac )
1180
92
        &&  ( data[ 3 ] != 0xbc )
1181
89
        &&  ( data[ 3 ] != 0xcc ) ) )
1182
274
      {
1183
#if defined( HAVE_DEBUG_OUTPUT )
1184
        if( libcnotify_verbose != 0 )
1185
        {
1186
          libcnotify_printf(
1187
           "%s: table signature missing trying to force decryption.\n",
1188
           function );
1189
        }
1190
#endif
1191
274
        force_decryption         = 1;
1192
274
        encryption_type          = LIBPFF_ENCRYPTION_TYPE_COMPRESSIBLE;
1193
274
        decrypt_data             = 1;
1194
274
        data_array_entry->flags |= LIBPFF_DATA_BLOCK_FLAG_DECRYPTION_FORCED;
1195
274
        data_array->flags       |= LIBPFF_DATA_ARRAY_FLAG_DECRYPTION_FORCED;
1196
274
      }
1197
298
    }
1198
65
    else if( data_array->io_handle->force_decryption == 1 )
1199
61
    {
1200
      /* Some of the last table array entries do not seem to be encrypted
1201
       */
1202
61
      if( ( node_contains_table != 0 )
1203
11
       && ( array_entry_index == ( number_of_data_array_entries - 1 ) ) )
1204
11
      {
1205
11
        byte_stream_copy_to_uint16_little_endian(
1206
11
         data,
1207
11
         table_index_offset );
1208
1209
11
        if( (size_t) table_index_offset > data_size )
1210
9
        {
1211
#if defined( HAVE_DEBUG_OUTPUT )
1212
          if( libcnotify_verbose != 0 )
1213
          {
1214
            libcnotify_printf(
1215
             "%s: detected encrypted last table array entry - decryption forced.\n",
1216
             function );
1217
          }
1218
#endif
1219
9
          encryption_type          = LIBPFF_ENCRYPTION_TYPE_COMPRESSIBLE;
1220
9
          decrypt_data             = 1;
1221
9
          data_array_entry->flags |= LIBPFF_DATA_BLOCK_FLAG_DECRYPTION_FORCED;
1222
9
          data_array->flags       |= LIBPFF_DATA_ARRAY_FLAG_DECRYPTION_FORCED;
1223
9
        }
1224
11
      }
1225
50
      else
1226
50
      {
1227
#if defined( HAVE_DEBUG_OUTPUT )
1228
        if( libcnotify_verbose != 0 )
1229
        {
1230
          libcnotify_printf(
1231
           "%s: decryption forced.\n",
1232
           function );
1233
        }
1234
#endif
1235
1236
50
        encryption_type          = LIBPFF_ENCRYPTION_TYPE_COMPRESSIBLE;
1237
50
        decrypt_data             = 1;
1238
50
        data_array_entry->flags |= LIBPFF_DATA_BLOCK_FLAG_DECRYPTION_FORCED;
1239
50
        data_array->flags       |= LIBPFF_DATA_ARRAY_FLAG_DECRYPTION_FORCED;
1240
50
      }
1241
61
    }
1242
363
  }
1243
  /* Check if unencrypted flag in offset index identifier is not set
1244
   */
1245
1.45k
  if( decrypt_data != 0 )
1246
614
  {
1247
614
    process_count = libpff_encryption_decrypt(
1248
614
                     encryption_type,
1249
614
                     (uint32_t) data_array_entry->data_identifier,
1250
614
                     data,
1251
614
                     data_size,
1252
614
                     error );
1253
1254
614
    if( process_count != (ssize_t) data_size )
1255
0
    {
1256
0
      libcerror_error_set(
1257
0
       error,
1258
0
       LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
1259
0
       LIBCERROR_ENCRYPTION_ERROR_DECRYPT_FAILED,
1260
0
       "%s: unable to decrypt array entry data.",
1261
0
       function );
1262
1263
0
      return( -1 );
1264
0
    }
1265
614
    if( force_decryption != 0 )
1266
274
    {
1267
      /* Test if the data contains an unencrypted table
1268
       * a table consists of 0xec in the third byte
1269
       * and 0x6c, 0x7c, 0x8c, 0x9c, 0xa5, 0xac, 0xbc, 0xcc in the fourth
1270
       */
1271
274
      if( ( data[ 2 ] == 0xec )
1272
105
       && ( ( data[ 3 ] == 0x6c )
1273
102
        ||  ( data[ 3 ] == 0x7c )
1274
99
        ||  ( data[ 3 ] == 0x8c )
1275
96
        ||  ( data[ 3 ] == 0x9c )
1276
93
        ||  ( data[ 3 ] == 0xa5 )
1277
90
        ||  ( data[ 3 ] == 0xac )
1278
87
        ||  ( data[ 3 ] == 0xbc )
1279
84
        ||  ( data[ 3 ] == 0xcc ) ) )
1280
24
      {
1281
#if defined( HAVE_DEBUG_OUTPUT )
1282
        if( libcnotify_verbose != 0 )
1283
        {
1284
          libcnotify_printf(
1285
           "%s: compressible encrypted data detected while encryption type is none - decryption forced.\n",
1286
           function );
1287
        }
1288
#endif
1289
24
        data_array->io_handle->force_decryption = 1;
1290
24
      }
1291
274
    }
1292
614
  }
1293
1.45k
  return( 1 );
1294
1.45k
}
1295