Coverage Report

Created: 2026-07-25 07:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libewf/libewf/libewf_digest_section.c
Line
Count
Source
1
/*
2
 * Digest section functions
3
 *
4
 * Copyright (C) 2006-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 <byte_stream.h>
24
#include <memory.h>
25
#include <narrow_string.h>
26
#include <types.h>
27
28
#include "libewf_digest_section.h"
29
#include "libewf_checksum.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_section.h"
37
#include "libewf_section_descriptor.h"
38
39
#include "ewf_digest.h"
40
41
/* Reads a digest section
42
 * Returns 1 if successful or -1 on error
43
 */
44
int libewf_digest_section_read_data(
45
     const uint8_t *data,
46
     size_t data_size,
47
     libewf_hash_sections_t *hash_sections,
48
     libcerror_error_t **error )
49
6
{
50
6
  static char *function        = "libewf_digest_section_read_data";
51
6
  uint32_t calculated_checksum = 0;
52
6
  uint32_t stored_checksum     = 0;
53
6
  int result                   = 0;
54
55
6
  if( data == NULL )
56
0
  {
57
0
    libcerror_error_set(
58
0
     error,
59
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
60
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
61
0
     "%s: missing data.",
62
0
     function );
63
64
0
    return( -1 );
65
0
  }
66
6
  if( data_size != (size_t) sizeof( ewf_digest_t ) )
67
6
  {
68
6
    libcerror_error_set(
69
6
     error,
70
6
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
71
6
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
72
6
     "%s: invalid data size value out of bounds.",
73
6
     function );
74
75
6
    return( -1 );
76
6
  }
77
0
  if( hash_sections == 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 hash sections.",
84
0
     function );
85
86
0
    return( -1 );
87
0
  }
88
#if defined( HAVE_DEBUG_OUTPUT )
89
  if( libcnotify_verbose != 0 )
90
  {
91
    libcnotify_printf(
92
     "%s: digest data:\n",
93
     function );
94
    libcnotify_print_data(
95
     data,
96
     data_size,
97
     0 );
98
  }
99
#endif
100
0
  byte_stream_copy_to_uint32_little_endian(
101
0
   ( (ewf_digest_t *) data )->checksum,
102
0
   stored_checksum );
103
104
#if defined( HAVE_DEBUG_OUTPUT )
105
  if( libcnotify_verbose != 0 )
106
  {
107
    libcnotify_printf(
108
     "%s: MD5 hash:\n",
109
     function );
110
    libcnotify_print_data(
111
     ( (ewf_digest_t *) data )->md5_hash,
112
     16,
113
     0 );
114
115
    libcnotify_printf(
116
     "%s: SHA1 hash:\n",
117
     function );
118
    libcnotify_print_data(
119
     ( (ewf_digest_t *) data )->sha1_hash,
120
     20,
121
     0 );
122
123
    libcnotify_printf(
124
     "%s: padding:\n",
125
     function );
126
    libcnotify_print_data(
127
     ( (ewf_digest_t *) data )->padding1,
128
     40,
129
     0 );
130
131
    libcnotify_printf(
132
     "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n",
133
     function,
134
     stored_checksum );
135
136
    libcnotify_printf(
137
     "\n" );
138
  }
139
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
140
141
0
  if( libewf_checksum_calculate_adler32(
142
0
       &calculated_checksum,
143
0
       data,
144
0
       data_size - 4,
145
0
       1,
146
0
       error ) != 1 )
147
0
  {
148
0
    libcerror_error_set(
149
0
     error,
150
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
151
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
152
0
     "%s: unable to calculate checksum.",
153
0
     function );
154
155
0
    return( -1 );
156
0
  }
157
0
  if( stored_checksum != calculated_checksum )
158
0
  {
159
0
    libcerror_error_set(
160
0
     error,
161
0
     LIBCERROR_ERROR_DOMAIN_INPUT,
162
0
     LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
163
0
     "%s: checksum does not match (stored: 0x%08" PRIx32 ", calculated: 0x%08" PRIx32 ").",
164
0
     function,
165
0
     stored_checksum,
166
0
     calculated_checksum );
167
168
0
    return( -1 );
169
0
  }
170
0
  result = libewf_section_test_zero(
171
0
      ( (ewf_digest_t *) data )->md5_hash,
172
0
      16,
173
0
      error );
174
175
0
  if( result == -1 )
176
0
  {
177
0
    libcerror_error_set(
178
0
     error,
179
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
180
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
181
0
     "%s: unable to determine if MD5 hash is empty.",
182
0
     function );
183
184
0
    return( -1 );
185
0
  }
186
0
  else if( result == 0 )
187
0
  {
188
0
    if( memory_copy(
189
0
         hash_sections->md5_digest,
190
0
         ( (ewf_digest_t *) data )->md5_hash,
191
0
         16 ) == NULL )
192
0
    {
193
0
      libcerror_error_set(
194
0
       error,
195
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
196
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
197
0
       "%s: unable to set MD5 digest in hash sections.",
198
0
       function );
199
200
0
      return( -1 );
201
0
    }
202
0
    hash_sections->md5_digest_set = 1;
203
0
  }
204
0
  else
205
0
  {
206
0
    hash_sections->md5_digest_set = 0;
207
0
  }
208
0
  result = libewf_section_test_zero(
209
0
      ( (ewf_digest_t *) data )->sha1_hash,
210
0
      20,
211
0
      error );
212
213
0
  if( result == -1 )
214
0
  {
215
0
    libcerror_error_set(
216
0
     error,
217
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
218
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
219
0
     "%s: unable to determine if SHA1 hash is empty.",
220
0
     function );
221
222
0
    return( -1 );
223
0
  }
224
0
  else if( result == 0 )
225
0
  {
226
0
    if( memory_copy(
227
0
         hash_sections->sha1_digest,
228
0
         ( (ewf_digest_t *) data )->sha1_hash,
229
0
         20 ) == NULL )
230
0
    {
231
0
      libcerror_error_set(
232
0
       error,
233
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
234
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
235
0
       "%s: unable to set SHA1 digest in hash sections.",
236
0
       function );
237
238
0
      return( -1 );
239
0
    }
240
0
    hash_sections->sha1_digest_set = 1;
241
0
  }
242
0
  else
243
0
  {
244
0
    hash_sections->sha1_digest_set = 0;
245
0
  }
246
0
  return( 1 );
247
0
}
248
249
/* Reads a digest section
250
 * Returns the number of bytes read or -1 on error
251
 */
252
ssize_t libewf_digest_section_read_file_io_pool(
253
         libewf_section_descriptor_t *section_descriptor,
254
         libewf_io_handle_t *io_handle,
255
         libbfio_pool_t *file_io_pool,
256
         int file_io_pool_entry,
257
         libewf_hash_sections_t *hash_sections,
258
         libcerror_error_t **error )
259
8
{
260
8
  uint8_t *section_data    = NULL;
261
8
  static char *function    = "libewf_digest_section_read_file_io_pool";
262
8
  size_t section_data_size = 0;
263
8
  ssize_t read_count       = 0;
264
265
8
  if( section_descriptor == NULL )
266
0
  {
267
0
    libcerror_error_set(
268
0
     error,
269
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
270
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
271
0
     "%s: invalid section descriptor.",
272
0
     function );
273
274
0
    return( -1 );
275
0
  }
276
8
  read_count = libewf_section_read_data(
277
8
                section_descriptor,
278
8
                io_handle,
279
8
                file_io_pool,
280
8
                file_io_pool_entry,
281
8
                &section_data,
282
8
                &section_data_size,
283
8
                error );
284
285
8
  if( read_count == -1 )
286
2
  {
287
2
    libcerror_error_set(
288
2
     error,
289
2
     LIBCERROR_ERROR_DOMAIN_IO,
290
2
     LIBCERROR_IO_ERROR_READ_FAILED,
291
2
     "%s: unable to read section data.",
292
2
     function );
293
294
2
    goto on_error;
295
2
  }
296
6
  else if( read_count != 0 )
297
6
  {
298
6
    if( libewf_digest_section_read_data(
299
6
         section_data,
300
6
         section_data_size,
301
6
         hash_sections,
302
6
         error ) != 1 )
303
6
    {
304
6
      libcerror_error_set(
305
6
       error,
306
6
       LIBCERROR_ERROR_DOMAIN_IO,
307
6
       LIBCERROR_IO_ERROR_READ_FAILED,
308
6
       "%s: unable to read digest section.",
309
6
       function );
310
311
6
      goto on_error;
312
6
    }
313
0
    memory_free(
314
0
     section_data );
315
0
  }
316
0
  return( read_count );
317
318
8
on_error:
319
8
  if( section_data != NULL )
320
6
  {
321
6
    memory_free(
322
6
     section_data );
323
6
  }
324
8
  return( -1 );
325
8
}
326
327
/* Writes a digest section
328
 * Returns 1 if successful or -1 on error
329
 */
330
int libewf_digest_section_write_data(
331
     uint8_t *data,
332
     size_t data_size,
333
     libewf_hash_sections_t *hash_sections,
334
     libcerror_error_t **error )
335
0
{
336
0
  static char *function        = "libewf_digest_section_write_data";
337
0
  uint32_t calculated_checksum = 0;
338
339
0
  if( data == NULL )
340
0
  {
341
0
    libcerror_error_set(
342
0
     error,
343
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
344
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
345
0
     "%s: missing data.",
346
0
     function );
347
348
0
    return( -1 );
349
0
  }
350
0
  if( data_size > (size_t) SSIZE_MAX )
351
0
  {
352
0
    libcerror_error_set(
353
0
     error,
354
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
355
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
356
0
     "%s: invalid data size value exceeds maximum.",
357
0
     function );
358
359
0
    return( -1 );
360
0
  }
361
0
  if( data_size != (size_t) sizeof( ewf_digest_t ) )
362
0
  {
363
0
    libcerror_error_set(
364
0
     error,
365
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
366
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
367
0
     "%s: invalid data size value out of bounds.",
368
0
     function );
369
370
0
    return( -1 );
371
0
  }
372
0
  if( hash_sections == NULL )
373
0
  {
374
0
    libcerror_error_set(
375
0
     error,
376
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
377
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
378
0
     "%s: invalid hash sections.",
379
0
     function );
380
381
0
    return( -1 );
382
0
  }
383
0
  if( memory_set(
384
0
       data,
385
0
       0,
386
0
       data_size ) == NULL )
387
0
  {
388
0
    libcerror_error_set(
389
0
     error,
390
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
391
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
392
0
     "%s: unable to clear data.",
393
0
     function );
394
395
0
    return( -1 );
396
0
  }
397
0
  if( hash_sections->md5_digest_set != 0 )
398
0
  {
399
0
    if( memory_copy(
400
0
         ( (ewf_digest_t *) data )->md5_hash,
401
0
         hash_sections->md5_digest,
402
0
         16 ) == NULL )
403
0
    {
404
0
      libcerror_error_set(
405
0
       error,
406
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
407
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
408
0
       "%s: unable to set MD5 hash.",
409
0
       function );
410
411
0
      return( -1 );
412
0
    }
413
0
  }
414
0
  if( hash_sections->sha1_digest_set != 0 )
415
0
  {
416
0
    if( memory_copy(
417
0
         ( (ewf_digest_t *) data )->sha1_hash,
418
0
         hash_sections->sha1_digest,
419
0
         20 ) == NULL )
420
0
    {
421
0
      libcerror_error_set(
422
0
       error,
423
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
424
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
425
0
       "%s: unable to set SHA1 hash.",
426
0
       function );
427
428
0
      return( -1 );
429
0
    }
430
0
  }
431
#if defined( HAVE_DEBUG_OUTPUT )
432
  if( libcnotify_verbose != 0 )
433
  {
434
    libcnotify_printf(
435
     "%s: digest section data:\n",
436
     function );
437
    libcnotify_print_data(
438
     data,
439
     data_size,
440
     0 );
441
  }
442
#endif
443
#if defined( HAVE_DEBUG_OUTPUT )
444
  if( libcnotify_verbose != 0 )
445
  {
446
    libcnotify_printf(
447
     "%s: MD5 hash:\n",
448
     function );
449
    libcnotify_print_data(
450
     ( (ewf_digest_t *) data )->md5_hash,
451
     16,
452
     0 );
453
454
    libcnotify_printf(
455
     "%s: SHA1 hash:\n",
456
     function );
457
    libcnotify_print_data(
458
     ( (ewf_digest_t *) data )->sha1_hash,
459
     20,
460
     0 );
461
  }
462
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
463
464
0
  if( libewf_checksum_calculate_adler32(
465
0
       &calculated_checksum,
466
0
       data,
467
0
       data_size - 4,
468
0
       1,
469
0
       error ) != 1 )
470
0
  {
471
0
    libcerror_error_set(
472
0
     error,
473
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
474
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
475
0
     "%s: unable to calculate checksum.",
476
0
     function );
477
478
0
    return( -1 );
479
0
  }
480
0
  byte_stream_copy_from_uint32_little_endian(
481
0
   ( (ewf_digest_t *) data )->checksum,
482
0
   calculated_checksum );
483
484
0
  return( 1 );
485
0
}
486
487
/* Writes a digest section
488
 * Returns the number of bytes written or -1 on error
489
 */
490
ssize_t libewf_digest_section_write_file_io_pool(
491
         libewf_section_descriptor_t *section_descriptor,
492
         libewf_io_handle_t *io_handle,
493
         libbfio_pool_t *file_io_pool,
494
         int file_io_pool_entry,
495
         off64_t section_offset,
496
         libewf_hash_sections_t *hash_sections,
497
         libcerror_error_t **error )
498
0
{
499
0
  uint8_t section_data[ sizeof( ewf_digest_t ) ];
500
501
0
  static char *function     = "libewf_digest_section_write_file_io_pool";
502
0
  ssize_t total_write_count = 0;
503
0
  ssize_t write_count       = 0;
504
505
0
  if( section_descriptor == NULL )
506
0
  {
507
0
    libcerror_error_set(
508
0
     error,
509
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
510
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
511
0
     "%s: invalid section descriptor.",
512
0
     function );
513
514
0
    return( -1 );
515
0
  }
516
0
  if( libewf_section_descriptor_set(
517
0
       section_descriptor,
518
0
       0,
519
0
       (uint8_t *) "digest",
520
0
       6,
521
0
       section_offset,
522
0
       (size64_t) ( sizeof( ewf_section_descriptor_v1_t ) + sizeof( ewf_digest_t ) ),
523
0
       (size64_t) sizeof( ewf_digest_t ),
524
0
       0,
525
0
       error ) != 1 )
526
0
  {
527
0
    libcerror_error_set(
528
0
     error,
529
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
530
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
531
0
     "%s: unable to set section descriptor.",
532
0
     function );
533
534
0
    return( -1 );
535
0
  }
536
0
  write_count = libewf_section_descriptor_write_file_io_pool(
537
0
                 section_descriptor,
538
0
                 file_io_pool,
539
0
                 file_io_pool_entry,
540
0
                 1,
541
0
                 error );
542
543
0
  if( write_count != (ssize_t) sizeof( ewf_section_descriptor_v1_t ) )
544
0
  {
545
0
    libcerror_error_set(
546
0
     error,
547
0
     LIBCERROR_ERROR_DOMAIN_IO,
548
0
     LIBCERROR_IO_ERROR_WRITE_FAILED,
549
0
     "%s: unable to write section descriptor.",
550
0
     function );
551
552
0
    return( -1 );
553
0
  }
554
0
  total_write_count += write_count;
555
556
0
  if( libewf_digest_section_write_data(
557
0
       section_data,
558
0
       sizeof( ewf_digest_t ),
559
0
       hash_sections,
560
0
       error ) != 1 )
561
0
  {
562
0
    libcerror_error_set(
563
0
     error,
564
0
     LIBCERROR_ERROR_DOMAIN_IO,
565
0
     LIBCERROR_IO_ERROR_READ_FAILED,
566
0
     "%s: unable to write section data.",
567
0
     function );
568
569
0
    return( -1 );
570
0
  }
571
0
  write_count = libewf_section_write_data(
572
0
                 section_descriptor,
573
0
                 io_handle,
574
0
                 file_io_pool,
575
0
                 file_io_pool_entry,
576
0
                 section_data,
577
0
                 sizeof( ewf_digest_t ),
578
0
                 error );
579
580
0
  if( write_count == -1 )
581
0
  {
582
0
    libcerror_error_set(
583
0
     error,
584
0
     LIBCERROR_ERROR_DOMAIN_IO,
585
0
     LIBCERROR_IO_ERROR_WRITE_FAILED,
586
0
     "%s: unable to write section data.",
587
0
     function );
588
589
0
    return( -1 );
590
0
  }
591
0
  total_write_count += write_count;
592
593
0
  return( total_write_count );
594
0
}
595