Coverage Report

Created: 2025-09-05 06:58

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