Coverage Report

Created: 2023-06-07 06:53

/src/libewf/libewf/libewf_ltree_section.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Ltree section functions
3
 *
4
 * Copyright (C) 2006-2023, 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 <narrow_string.h>
26
#include <types.h>
27
28
#include "libewf_checksum.h"
29
#include "libewf_debug.h"
30
#include "libewf_definitions.h"
31
#include "libewf_hash_sections.h"
32
#include "libewf_io_handle.h"
33
#include "libewf_libbfio.h"
34
#include "libewf_libcerror.h"
35
#include "libewf_libcnotify.h"
36
#include "libewf_libhmac.h"
37
#include "libewf_ltree_section.h"
38
#include "libewf_section.h"
39
#include "libewf_section_descriptor.h"
40
41
#include "ewf_ltree.h"
42
43
/* Reads a version 1 ltree section or version 2 singles files data section
44
 * single_files_data will be set to a pointer within the section data
45
 * Returns 1 if successful or -1 on error
46
 */
47
int libewf_ltree_section_read_data(
48
     const uint8_t *data,
49
     size_t data_size,
50
     uint8_t format_version,
51
     uint8_t **single_files_data,
52
     size_t *single_files_data_size,
53
     libcerror_error_t **error )
54
48
{
55
48
  uint8_t calculated_md5_hash[ 16 ];
56
57
48
  uint8_t ltree_header_data[ sizeof( ewf_ltree_header_t ) ];
58
59
48
  static char *function        = "libewf_ltree_section_read_data";
60
48
  size_t data_offset           = 0;
61
48
  uint64_t stored_data_size    = 0;
62
48
  uint32_t calculated_checksum = 0;
63
48
  uint32_t stored_checksum     = 0;
64
65
#if defined( HAVE_DEBUG_OUTPUT )
66
  size_t trailing_data_size    = 0;
67
#endif
68
69
48
  if( data == NULL )
70
0
  {
71
0
    libcerror_error_set(
72
0
     error,
73
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
74
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
75
0
     "%s: missing data.",
76
0
     function );
77
78
0
    return( -1 );
79
0
  }
80
48
  if( data_size > (size_t) SSIZE_MAX )
81
0
  {
82
0
    libcerror_error_set(
83
0
     error,
84
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
85
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
86
0
     "%s: invalid data size value exceeds maximum.",
87
0
     function );
88
89
0
    return( -1 );
90
0
  }
91
48
  if( ( format_version != 1 )
92
48
   && ( format_version != 2 ) )
93
0
  {
94
0
    libcerror_error_set(
95
0
     error,
96
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
97
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
98
0
     "%s: unsupported format version.",
99
0
     function );
100
101
0
    return( -1 );
102
0
  }
103
48
  if( single_files_data == NULL )
104
0
  {
105
0
    libcerror_error_set(
106
0
     error,
107
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
108
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
109
0
     "%s: invalid single files data.",
110
0
     function );
111
112
0
    return( -1 );
113
0
  }
114
48
  if( *single_files_data != NULL )
115
0
  {
116
0
    libcerror_error_set(
117
0
     error,
118
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
119
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
120
0
     "%s: invalid single files data value already set.",
121
0
     function );
122
123
0
    return( -1 );
124
0
  }
125
48
  if( single_files_data_size == NULL )
126
0
  {
127
0
    libcerror_error_set(
128
0
     error,
129
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
130
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
131
0
     "%s: invalid single files data size.",
132
0
     function );
133
134
0
    return( -1 );
135
0
  }
136
48
  if( format_version == 1 )
137
48
  {
138
48
    if( data_size < sizeof( ewf_ltree_header_t ) )
139
0
    {
140
0
      libcerror_error_set(
141
0
       error,
142
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
143
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
144
0
       "%s: invalid section size value out of bounds - insufficient space for header.",
145
0
       function );
146
147
0
      return( -1 );
148
0
    }
149
#if defined( HAVE_DEBUG_OUTPUT )
150
    if( libcnotify_verbose != 0 )
151
    {
152
      libcnotify_printf(
153
       "%s: ltree header data:\n",
154
       function );
155
      libcnotify_print_data(
156
       data,
157
       sizeof( ewf_ltree_header_t ),
158
       0 );
159
    }
160
#endif
161
48
    byte_stream_copy_to_uint64_little_endian(
162
48
     ( (ewf_ltree_header_t *) data )->data_size,
163
48
     stored_data_size );
164
165
48
    byte_stream_copy_to_uint32_little_endian(
166
48
     ( (ewf_ltree_header_t *) data )->checksum,
167
48
     stored_checksum );
168
169
#if defined( HAVE_DEBUG_OUTPUT )
170
    if( libcnotify_verbose != 0 )
171
    {
172
      libcnotify_printf(
173
       "%s: integrity hash:\n",
174
       function );
175
      libcnotify_print_data(
176
       ( (ewf_ltree_header_t *) data )->integrity_hash,
177
       16,
178
       0 );
179
180
      libcnotify_printf(
181
       "%s: data size\t\t\t\t\t: %" PRIu64 "\n",
182
       function,
183
       stored_data_size );
184
185
      libcnotify_printf(
186
       "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n",
187
       function,
188
       stored_checksum );
189
190
      libcnotify_printf(
191
       "%s: unknown1:\n",
192
       function );
193
      libcnotify_print_data(
194
       ( (ewf_ltree_header_t *) data )->unknown1,
195
       20,
196
       0 );
197
    }
198
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
199
200
48
    if( memory_copy(
201
48
         ltree_header_data,
202
48
         data,
203
48
         sizeof( ewf_ltree_header_t ) ) == NULL )
204
0
    {
205
0
      libcerror_error_set(
206
0
       error,
207
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
208
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
209
0
       "%s: unable to copy ltree header data.",
210
0
       function );
211
212
0
      return( -1 );
213
0
    }
214
48
    byte_stream_copy_from_uint32_little_endian(
215
48
     ( (ewf_ltree_header_t *) ltree_header_data )->checksum,
216
48
     0 );
217
218
48
    if( libewf_checksum_calculate_adler32(
219
48
         &calculated_checksum,
220
48
         ltree_header_data,
221
48
         sizeof( ewf_ltree_header_t ),
222
48
         1,
223
48
         error ) != 1 )
224
0
    {
225
0
      libcerror_error_set(
226
0
       error,
227
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
228
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
229
0
       "%s: unable to calculate header checksum.",
230
0
       function );
231
232
0
      return( -1 );
233
0
    }
234
48
    if( stored_checksum != calculated_checksum )
235
40
    {
236
40
      libcerror_error_set(
237
40
       error,
238
40
       LIBCERROR_ERROR_DOMAIN_INPUT,
239
40
       LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
240
40
       "%s: header checksum does not match (stored: 0x%08" PRIx32 ", calculated: 0x%08" PRIx32 ").",
241
40
       function,
242
40
       stored_checksum,
243
40
       calculated_checksum );
244
245
40
      return( -1 );
246
40
    }
247
8
    data_offset += sizeof( ewf_ltree_header_t );
248
8
    data_size   -= sizeof( ewf_ltree_header_t );
249
250
8
    if( stored_data_size > (uint64_t) data_size )
251
8
    {
252
8
      libcerror_error_set(
253
8
       error,
254
8
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
255
8
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
256
8
       "%s: invalid section size value out of bounds - insufficient space for entries data.",
257
8
       function );
258
259
8
      return( -1 );
260
8
    }
261
0
    *single_files_data      = (uint8_t *) &( data[ data_offset ] );
262
0
    *single_files_data_size = (size_t) stored_data_size;
263
0
  }
264
0
  else if( format_version == 2 )
265
0
  {
266
0
    *single_files_data      = (uint8_t *) data;
267
0
    *single_files_data_size = data_size;
268
0
  }
269
#if defined( HAVE_DEBUG_OUTPUT )
270
  if( libcnotify_verbose != 0 )
271
  {
272
    if( libewf_debug_utf16_stream_print(
273
         "single files data",
274
         *single_files_data,
275
         *single_files_data_size,
276
         error ) != 1 )
277
    {
278
      libcerror_error_set(
279
       error,
280
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
281
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
282
       "%s: unable to print single files data.",
283
       function );
284
285
      return( -1 );
286
    }
287
  }
288
#endif
289
0
  if( format_version == 1 )
290
0
  {
291
0
    if( libhmac_md5_calculate(
292
0
         *single_files_data,
293
0
         *single_files_data_size,
294
0
         calculated_md5_hash,
295
0
         16,
296
0
         error ) != 1 )
297
0
    {
298
0
      libcerror_error_set(
299
0
       error,
300
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
301
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
302
0
       "%s: unable to calculate integrity hash.",
303
0
       function );
304
305
0
      return( -1 );
306
0
    }
307
#if defined( HAVE_DEBUG_OUTPUT )
308
    if( libcnotify_verbose != 0 )
309
    {
310
      libcnotify_printf(
311
       "%s: calculated MD5 hash:\n",
312
       function );
313
      libcnotify_print_data(
314
       calculated_md5_hash,
315
       16,
316
       0 );
317
    }
318
#endif
319
0
    if( memory_compare(
320
0
         data,
321
0
         calculated_md5_hash,
322
0
         16 ) != 0 )
323
0
    {
324
0
      libcerror_error_set(
325
0
       error,
326
0
       LIBCERROR_ERROR_DOMAIN_INPUT,
327
0
       LIBCERROR_INPUT_ERROR_VALUE_MISMATCH,
328
0
       "%s: mismatch in integrity hash.",
329
0
       function );
330
331
0
      return( -1 );
332
0
    }
333
#if defined( HAVE_DEBUG_OUTPUT ) || defined( HAVE_VERBOSE_OUTPUT )
334
    if( libcnotify_verbose != 0 )
335
    {
336
      if( stored_data_size < (uint64_t) data_size )
337
      {
338
#if defined( HAVE_DEBUG_OUTPUT )
339
        data_offset       += stored_data_size;
340
        trailing_data_size = data_size - stored_data_size;
341
342
        libcnotify_printf(
343
         "%s: trailing data:\n",
344
         function );
345
        libcnotify_print_data(
346
         &( data[ data_offset ] ),
347
         trailing_data_size,
348
         0 );
349
350
#elif defined( HAVE_VERBOSE_OUTPUT )
351
        libcnotify_printf(
352
         "%s: section has trailing data.\n",
353
         function );
354
#endif
355
      }
356
    }
357
#endif /* defined( HAVE_DEBUG_OUTPUT ) || defined( HAVE_VERBOSE_OUTPUT ) */
358
0
  }
359
0
  return( 1 );
360
0
}
361
362
/* Reads a version 1 ltree section or version 2 singles files data section
363
 * section_data will be set to a buffer containing the full section data
364
 * single_files_data will be set to a pointer within the section data
365
 * Returns the number of bytes read or -1 on error
366
 */
367
ssize_t libewf_ltree_section_read_file_io_pool(
368
         libewf_section_descriptor_t *section_descriptor,
369
         libewf_io_handle_t *io_handle,
370
         libbfio_pool_t *file_io_pool,
371
         int file_io_pool_entry,
372
         uint8_t format_version,
373
         uint8_t **section_data,
374
         size_t *section_data_size,
375
         uint8_t **single_files_data,
376
         size_t *single_files_data_size,
377
         libcerror_error_t **error )
378
49
{
379
49
  static char *function = "libewf_ltree_section_read_file_io_pool";
380
49
  ssize_t read_count    = 0;
381
382
49
  if( section_descriptor == 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 section descriptor.",
389
0
     function );
390
391
0
    return( -1 );
392
0
  }
393
49
  read_count = libewf_section_read_data(
394
49
                section_descriptor,
395
49
                io_handle,
396
49
                file_io_pool,
397
49
                file_io_pool_entry,
398
49
                section_data,
399
49
                section_data_size,
400
49
                error );
401
402
49
  if( read_count == -1 )
403
1
  {
404
1
    libcerror_error_set(
405
1
     error,
406
1
     LIBCERROR_ERROR_DOMAIN_IO,
407
1
     LIBCERROR_IO_ERROR_READ_FAILED,
408
1
     "%s: unable to read section data.",
409
1
     function );
410
411
1
    goto on_error;
412
1
  }
413
48
  else if( read_count > 0 )
414
48
  {
415
48
    if( section_data == NULL )
416
0
    {
417
0
      libcerror_error_set(
418
0
       error,
419
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
420
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
421
0
       "%s: missing section data.",
422
0
       function );
423
424
0
      goto on_error;
425
0
    }
426
48
    if( libewf_ltree_section_read_data(
427
48
         *section_data,
428
48
         *section_data_size,
429
48
         format_version,
430
48
         single_files_data,
431
48
         single_files_data_size,
432
48
         error ) != 1 )
433
48
    {
434
48
      libcerror_error_set(
435
48
       error,
436
48
       LIBCERROR_ERROR_DOMAIN_IO,
437
48
       LIBCERROR_IO_ERROR_READ_FAILED,
438
48
       "%s: unable to read ltree section.",
439
48
       function );
440
441
48
      goto on_error;
442
48
    }
443
48
  }
444
0
  return( read_count );
445
446
49
on_error:
447
49
  if( *section_data != NULL )
448
48
  {
449
48
    memory_free(
450
48
     *section_data );
451
452
48
    *section_data = NULL;
453
48
  }
454
49
  *section_data_size = 0;
455
456
49
  return( -1 );
457
49
}
458
459
/* Writes a version 1 ltree section or version 2 singles files data section
460
 * Returns the number of bytes written or -1 on error
461
 */
462
ssize_t libewf_ltree_section_write_file_io_pool(
463
         libewf_section_descriptor_t *section_descriptor,
464
         libewf_io_handle_t *io_handle,
465
         libbfio_pool_t *file_io_pool,
466
         int file_io_pool_entry,
467
         uint8_t format_version,
468
         off64_t section_offset,
469
         uint8_t *section_data,
470
         size_t section_data_size,
471
         uint8_t *single_files_data,
472
         size_t single_files_data_size,
473
         libcerror_error_t **error )
474
0
{
475
0
  static char *function               = "libewf_ltree_section_write_file_io_pool";
476
0
  size_t ltree_header_data_size       = 0;
477
0
  size_t required_section_data_size   = 0;
478
0
  size_t section_descriptor_data_size = 0;
479
0
  ssize_t total_write_count           = 0;
480
0
  ssize_t write_count                 = 0;
481
0
  uint32_t calculated_checksum        = 0;
482
0
  uint32_t section_padding_size       = 0;
483
484
0
  if( section_descriptor == NULL )
485
0
  {
486
0
    libcerror_error_set(
487
0
     error,
488
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
489
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
490
0
     "%s: invalid section descriptor.",
491
0
     function );
492
493
0
    return( -1 );
494
0
  }
495
0
  if( format_version == 1 )
496
0
  {
497
0
    section_descriptor_data_size = sizeof( ewf_section_descriptor_v1_t );
498
0
    ltree_header_data_size       = sizeof( ewf_ltree_header_t );
499
0
  }
500
0
  else if( format_version == 2 )
501
0
  {
502
0
    section_descriptor_data_size = sizeof( ewf_section_descriptor_v2_t );
503
0
  }
504
0
  else
505
0
  {
506
0
    libcerror_error_set(
507
0
     error,
508
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
509
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
510
0
     "%s: unsupported format version.",
511
0
     function );
512
513
0
    return( -1 );
514
0
  }
515
0
  if( section_data == NULL )
516
0
  {
517
0
    libcerror_error_set(
518
0
     error,
519
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
520
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
521
0
     "%s: invalid section data.",
522
0
     function );
523
524
0
    return( -1 );
525
0
  }
526
0
  if( section_data_size > (size_t) SSIZE_MAX )
527
0
  {
528
0
    libcerror_error_set(
529
0
     error,
530
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
531
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
532
0
     "%s: invalid section data size value exceeds maximum.",
533
0
     function );
534
535
0
    return( -1 );
536
0
  }
537
0
  if( single_files_data == NULL )
538
0
  {
539
0
    libcerror_error_set(
540
0
     error,
541
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
542
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
543
0
     "%s: invalid single files data.",
544
0
     function );
545
546
0
    return( -1 );
547
0
  }
548
0
  required_section_data_size = ltree_header_data_size
549
0
                             + single_files_data_size;
550
551
0
  if( required_section_data_size > section_data_size )
552
0
  {
553
0
    libcerror_error_set(
554
0
     error,
555
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
556
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
557
0
     "%s: invalid section data value too small.",
558
0
     function );
559
560
0
    return( -1 );
561
0
  }
562
0
  if( single_files_data_size > (size_t) SSIZE_MAX )
563
0
  {
564
0
    libcerror_error_set(
565
0
     error,
566
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
567
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
568
0
     "%s: invalid single files data size value exceeds maximum.",
569
0
     function );
570
571
0
    return( -1 );
572
0
  }
573
0
  if( libewf_section_descriptor_set(
574
0
       section_descriptor,
575
0
       LIBEWF_SECTION_TYPE_SINGLE_FILES_DATA,
576
0
       (uint8_t *) "ltree",
577
0
       5,
578
0
       section_offset,
579
0
       (size64_t) ( section_descriptor_data_size + required_section_data_size ),
580
0
       (size64_t) required_section_data_size,
581
0
       section_padding_size,
582
0
       error ) != 1 )
583
0
  {
584
0
    libcerror_error_set(
585
0
     error,
586
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
587
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
588
0
     "%s: unable to set section descriptor.",
589
0
     function );
590
591
0
    return( -1 );
592
0
  }
593
0
  if( format_version == 1 )
594
0
  {
595
0
    write_count = libewf_section_descriptor_write_file_io_pool(
596
0
             section_descriptor,
597
0
             file_io_pool,
598
0
             file_io_pool_entry,
599
0
             format_version,
600
0
             error );
601
602
0
    if( write_count != (ssize_t) section_descriptor_data_size )
603
0
    {
604
0
      libcerror_error_set(
605
0
       error,
606
0
       LIBCERROR_ERROR_DOMAIN_IO,
607
0
       LIBCERROR_IO_ERROR_WRITE_FAILED,
608
0
       "%s: unable to write section descriptor data.",
609
0
       function );
610
611
0
      return( -1 );
612
0
    }
613
0
    total_write_count += write_count;
614
0
  }
615
0
  if( format_version == 1 )
616
0
  {
617
0
    if( ( section_data + ltree_header_data_size ) != single_files_data )
618
0
    {
619
0
      libcerror_error_set(
620
0
       error,
621
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
622
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
623
0
       "%s: invalid single files data value out of bounds.",
624
0
       function );
625
626
0
      return( -1 );
627
0
    }
628
0
    if( single_files_data_size > (size_t) UINT32_MAX )
629
0
    {
630
0
      libcerror_error_set(
631
0
       error,
632
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
633
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
634
0
       "%s: invalid single files data size value exceeds maximum.",
635
0
       function );
636
637
0
      return( -1 );
638
0
    }
639
0
    if( section_data_size < ltree_header_data_size )
640
0
    {
641
0
      libcerror_error_set(
642
0
       error,
643
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
644
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
645
0
       "%s: invalid section size value out of bounds - insufficient space for header.",
646
0
       function );
647
648
0
      return( -1 );
649
0
    }
650
0
    if( memory_set(
651
0
         section_data,
652
0
         0,
653
0
         ltree_header_data_size ) == NULL )
654
0
    {
655
0
      libcerror_error_set(
656
0
       error,
657
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
658
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
659
0
       "%s: unable to clear ltree header data.",
660
0
       function );
661
662
0
      return( -1 );
663
0
    }
664
0
    if( libhmac_md5_calculate(
665
0
         single_files_data,
666
0
         single_files_data_size,
667
0
         ( (ewf_ltree_header_t *) section_data )->integrity_hash,
668
0
         16,
669
0
         error ) != 1 )
670
0
    {
671
0
      libcerror_error_set(
672
0
       error,
673
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
674
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
675
0
       "%s: unable to calculate integrity hash.",
676
0
       function );
677
678
0
      return( -1 );
679
0
    }
680
#if defined( HAVE_DEBUG_OUTPUT )
681
    if( libcnotify_verbose != 0 )
682
    {
683
      libcnotify_printf(
684
       "%s: calculated MD5 hash:\n",
685
       function );
686
      libcnotify_print_data(
687
       ( (ewf_ltree_header_t *) section_data )->integrity_hash,
688
       16,
689
       0 );
690
    }
691
#endif
692
0
    byte_stream_copy_from_uint32_little_endian(
693
0
     ( (ewf_ltree_header_t *) section_data )->data_size,
694
0
     single_files_data_size );
695
696
0
    if( libewf_checksum_calculate_adler32(
697
0
         &calculated_checksum,
698
0
         section_data,
699
0
         ltree_header_data_size,
700
0
         1,
701
0
         error ) != 1 )
702
0
    {
703
0
      libcerror_error_set(
704
0
       error,
705
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
706
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
707
0
       "%s: unable to calculate header checksum.",
708
0
       function );
709
710
0
      return( -1 );
711
0
    }
712
0
    byte_stream_copy_from_uint32_little_endian(
713
0
     ( (ewf_ltree_header_t *) section_data )->checksum,
714
0
     calculated_checksum );
715
716
#if defined( HAVE_DEBUG_OUTPUT )
717
    if( libcnotify_verbose != 0 )
718
    {
719
      libcnotify_printf(
720
       "%s: ltree header data:\n",
721
       function );
722
      libcnotify_print_data(
723
       section_data,
724
       ltree_header_data_size,
725
       0 );
726
    }
727
#endif
728
#if defined( HAVE_DEBUG_OUTPUT )
729
    if( libcnotify_verbose != 0 )
730
    {
731
      libcnotify_printf(
732
       "%s: integrity hash:\n",
733
       function );
734
      libcnotify_print_data(
735
       ( (ewf_ltree_header_t *) section_data )->integrity_hash,
736
       16,
737
       0 );
738
739
      libcnotify_printf(
740
       "%s: data size\t\t\t\t\t: %" PRIzd "\n",
741
       function,
742
       single_files_data_size );
743
744
      libcnotify_printf(
745
       "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n",
746
       function,
747
       calculated_checksum );
748
749
      libcnotify_printf(
750
       "%s: unknown1:\n",
751
       function );
752
      libcnotify_print_data(
753
       ( (ewf_ltree_header_t *) section_data )->unknown1,
754
       20,
755
       0 );
756
    }
757
#endif
758
0
  }
759
0
  else if( format_version == 2 )
760
0
  {
761
0
    section_descriptor->data_flags |= LIBEWF_SECTION_DATA_FLAGS_HAS_INTEGRITY_HASH;
762
0
  }
763
0
  write_count = libewf_section_write_data(
764
0
                 section_descriptor,
765
0
                 io_handle,
766
0
                 file_io_pool,
767
0
                 file_io_pool_entry,
768
0
                 section_data,
769
0
                 required_section_data_size,
770
0
                 error );
771
772
0
  if( write_count == -1 )
773
0
  {
774
0
    libcerror_error_set(
775
0
     error,
776
0
     LIBCERROR_ERROR_DOMAIN_IO,
777
0
     LIBCERROR_IO_ERROR_WRITE_FAILED,
778
0
     "%s: unable to write section data.",
779
0
     function );
780
781
0
    return( -1 );
782
0
  }
783
0
  total_write_count += write_count;
784
785
0
  if( format_version == 2 )
786
0
  {
787
0
    write_count = libewf_section_descriptor_write_file_io_pool(
788
0
             section_descriptor,
789
0
             file_io_pool,
790
0
             file_io_pool_entry,
791
0
             format_version,
792
0
             error );
793
794
0
    if( write_count != (ssize_t) section_descriptor_data_size )
795
0
    {
796
0
      libcerror_error_set(
797
0
       error,
798
0
       LIBCERROR_ERROR_DOMAIN_IO,
799
0
       LIBCERROR_IO_ERROR_WRITE_FAILED,
800
0
       "%s: unable to write section descriptor data.",
801
0
       function );
802
803
0
      return( -1 );
804
0
    }
805
0
    total_write_count += write_count;
806
0
  }
807
0
  return( total_write_count );
808
0
}
809