Coverage Report

Created: 2025-09-05 06:58

/src/libfvde/libfvde/libfvde_volume_header.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The FVDE volume header functions
3
 *
4
 * Copyright (C) 2011-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 "libfvde_checksum.h"
28
#include "libfvde_debug.h"
29
#include "libfvde_definitions.h"
30
#include "libfvde_libbfio.h"
31
#include "libfvde_libcerror.h"
32
#include "libfvde_libcnotify.h"
33
#include "libfvde_libfguid.h"
34
#include "libfvde_volume_header.h"
35
36
#include "fvde_volume.h"
37
38
/* Creates a volume header
39
 * Make sure the value volume_header is referencing, is set to NULL
40
 * Returns 1 if successful or -1 on error
41
 */
42
int libfvde_volume_header_initialize(
43
     libfvde_volume_header_t **volume_header,
44
     libcerror_error_t **error )
45
1.35k
{
46
1.35k
  static char *function = "libfvde_volume_header_initialize";
47
48
1.35k
  if( volume_header == NULL )
49
0
  {
50
0
    libcerror_error_set(
51
0
     error,
52
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
53
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
54
0
     "%s: invalid volume header.",
55
0
     function );
56
57
0
    return( -1 );
58
0
  }
59
1.35k
  if( *volume_header != NULL )
60
0
  {
61
0
    libcerror_error_set(
62
0
     error,
63
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
64
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
65
0
     "%s: invalid volume header value already set.",
66
0
     function );
67
68
0
    return( -1 );
69
0
  }
70
1.35k
  *volume_header = memory_allocate_structure(
71
1.35k
                    libfvde_volume_header_t );
72
73
1.35k
  if( *volume_header == NULL )
74
0
  {
75
0
    libcerror_error_set(
76
0
     error,
77
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
78
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
79
0
     "%s: unable to create volume header.",
80
0
     function );
81
82
0
    goto on_error;
83
0
  }
84
1.35k
  if( memory_set(
85
1.35k
       *volume_header,
86
1.35k
       0,
87
1.35k
       sizeof( libfvde_volume_header_t ) ) == NULL )
88
0
  {
89
0
    libcerror_error_set(
90
0
     error,
91
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
92
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
93
0
     "%s: unable to clear volume header.",
94
0
     function );
95
96
0
    goto on_error;
97
0
  }
98
1.35k
  return( 1 );
99
100
0
on_error:
101
0
  if( *volume_header != NULL )
102
0
  {
103
0
    memory_free(
104
0
     *volume_header );
105
106
0
    *volume_header = NULL;
107
0
  }
108
0
  return( -1 );
109
1.35k
}
110
111
/* Frees a volume header
112
 * Returns 1 if successful or -1 on error
113
 */
114
int libfvde_volume_header_free(
115
     libfvde_volume_header_t **volume_header,
116
     libcerror_error_t **error )
117
1.35k
{
118
1.35k
  static char *function = "libfvde_volume_header_free";
119
120
1.35k
  if( volume_header == NULL )
121
0
  {
122
0
    libcerror_error_set(
123
0
     error,
124
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
125
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
126
0
     "%s: invalid volume header.",
127
0
     function );
128
129
0
    return( -1 );
130
0
  }
131
1.35k
  if( *volume_header != NULL )
132
1.35k
  {
133
1.35k
    memory_free(
134
1.35k
     *volume_header );
135
136
1.35k
    *volume_header = NULL;
137
1.35k
  }
138
1.35k
  return( 1 );
139
1.35k
}
140
141
/* Reads the volume header
142
 * Returns 1 if successful or -1 on error
143
 */
144
int libfvde_volume_header_read_data(
145
     libfvde_volume_header_t *volume_header,
146
     const uint8_t *data,
147
     size_t data_size,
148
     libcerror_error_t **error )
149
1.34k
{
150
1.34k
  static char *function        = "libfvde_volume_header_read_data";
151
1.34k
  uint32_t calculated_checksum = 0;
152
1.34k
  uint32_t checksum_algorithm  = 0;
153
1.34k
  uint32_t initial_value       = 0;
154
1.34k
  uint32_t stored_checksum     = 0;
155
1.34k
  uint16_t block_type          = 0;
156
1.34k
  uint16_t format_version      = 0;
157
1.34k
  int metadata_block_index     = 0;
158
159
#if defined( HAVE_DEBUG_OUTPUT )
160
  uint64_t value_64bit         = 0;
161
  uint32_t value_32bit         = 0;
162
  uint16_t value_16bit         = 0;
163
#endif
164
165
1.34k
  if( volume_header == NULL )
166
0
  {
167
0
    libcerror_error_set(
168
0
     error,
169
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
170
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
171
0
     "%s: invalid volume header.",
172
0
     function );
173
174
0
    return( -1 );
175
0
  }
176
1.34k
  if( data == NULL )
177
0
  {
178
0
    libcerror_error_set(
179
0
     error,
180
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
181
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
182
0
     "%s: invalid data.",
183
0
     function );
184
185
0
    return( -1 );
186
0
  }
187
1.34k
  if( ( data_size < sizeof( fvde_volume_header_t ) )
188
1.34k
   || ( data_size > (size_t) SSIZE_MAX ) )
189
0
  {
190
0
    libcerror_error_set(
191
0
     error,
192
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
193
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
194
0
     "%s: invalid data size value out of bounds.",
195
0
     function );
196
197
0
    return( -1 );
198
0
  }
199
#if defined( HAVE_DEBUG_OUTPUT )
200
  if( libcnotify_verbose != 0 )
201
  {
202
    libcnotify_printf(
203
     "%s: volume header data:\n",
204
     function );
205
    libcnotify_print_data(
206
     data,
207
     sizeof( fvde_volume_header_t ),
208
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
209
  }
210
#endif
211
1.34k
  byte_stream_copy_to_uint32_little_endian(
212
1.34k
   ( (fvde_volume_header_t *) data )->checksum,
213
1.34k
   stored_checksum );
214
215
1.34k
  byte_stream_copy_to_uint32_little_endian(
216
1.34k
   ( (fvde_volume_header_t *) data )->initial_value,
217
1.34k
   initial_value );
218
219
1.34k
  byte_stream_copy_to_uint16_little_endian(
220
1.34k
   ( (fvde_volume_header_t *) data )->block_type,
221
1.34k
   block_type );
222
223
1.34k
  byte_stream_copy_to_uint16_little_endian(
224
1.34k
   ( (fvde_volume_header_t *) data )->format_version,
225
1.34k
   format_version );
226
227
1.34k
  byte_stream_copy_to_uint32_little_endian(
228
1.34k
   ( (fvde_volume_header_t *) data )->serial_number,
229
1.34k
   volume_header->serial_number );
230
231
1.34k
  byte_stream_copy_to_uint32_little_endian(
232
1.34k
   ( (fvde_volume_header_t *) data )->bytes_per_sector,
233
1.34k
   volume_header->bytes_per_sector );
234
235
1.34k
  byte_stream_copy_to_uint64_little_endian(
236
1.34k
   ( (fvde_volume_header_t *) data )->volume_size,
237
1.34k
   volume_header->physical_volume_size );
238
239
1.34k
  byte_stream_copy_to_uint32_little_endian(
240
1.34k
   ( (fvde_volume_header_t *) data )->checksum_algorithm,
241
1.34k
   checksum_algorithm );
242
243
1.34k
  byte_stream_copy_to_uint32_little_endian(
244
1.34k
   ( (fvde_volume_header_t *) data )->block_size,
245
1.34k
   volume_header->block_size );
246
247
1.34k
  byte_stream_copy_to_uint32_little_endian(
248
1.34k
   ( (fvde_volume_header_t *) data )->metadata_size,
249
1.34k
   volume_header->metadata_size );
250
251
1.34k
  for( metadata_block_index = 0;
252
6.71k
       metadata_block_index < 4;
253
5.36k
       metadata_block_index++ )
254
5.36k
  {
255
5.36k
    byte_stream_copy_to_uint64_little_endian(
256
5.36k
     &( ( ( (fvde_volume_header_t *) data )->metadata_block_numbers )[ metadata_block_index * 8 ] ),
257
5.36k
     volume_header->metadata_offsets[ metadata_block_index ] );
258
5.36k
  }
259
1.34k
  byte_stream_copy_to_uint32_little_endian(
260
1.34k
   ( (fvde_volume_header_t *) data )->encryption_method,
261
1.34k
   volume_header->physical_volume_encryption_method );
262
263
/* TODO copy all key data ? */
264
1.34k
  if( memory_copy(
265
1.34k
       volume_header->key_data,
266
1.34k
       &( ( (fvde_volume_header_t *) data )->key_data ),
267
1.34k
       16 ) == NULL )
268
0
  {
269
0
    libcerror_error_set(
270
0
     error,
271
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
272
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
273
0
     "%s: unable to copy key data.",
274
0
     function );
275
276
0
    return( -1 );
277
0
  }
278
1.34k
  if( memory_copy(
279
1.34k
       volume_header->physical_volume_identifier,
280
1.34k
       &( ( (fvde_volume_header_t *) data )->physical_volume_identifier ),
281
1.34k
       16 ) == NULL )
282
0
  {
283
0
    libcerror_error_set(
284
0
     error,
285
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
286
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
287
0
     "%s: unable to copy physical volume identifier.",
288
0
     function );
289
290
0
    return( -1 );
291
0
  }
292
1.34k
  if( memory_copy(
293
1.34k
       volume_header->volume_group_identifier,
294
1.34k
       &( ( (fvde_volume_header_t *) data )->volume_group_identifier ),
295
1.34k
       16 ) == NULL )
296
0
  {
297
0
    libcerror_error_set(
298
0
     error,
299
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
300
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
301
0
     "%s: unable to copy volume group identifier.",
302
0
     function );
303
304
0
    return( -1 );
305
0
  }
306
#if defined( HAVE_DEBUG_OUTPUT )
307
  if( libcnotify_verbose != 0 )
308
  {
309
    libcnotify_printf(
310
     "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n",
311
     function,
312
     stored_checksum );
313
314
    libcnotify_printf(
315
     "%s: initial value\t\t\t\t: 0x%08" PRIx32 "\n",
316
     function,
317
     initial_value );
318
319
    libcnotify_printf(
320
     "%s: format version\t\t\t\t: %" PRIu16 "\n",
321
     function,
322
     format_version );
323
324
    libcnotify_printf(
325
     "%s: block type\t\t\t\t: 0x%04" PRIx16 "\n",
326
     function,
327
     block_type );
328
329
    libcnotify_printf(
330
     "%s: serial number\t\t\t\t: 0x%08" PRIx32 "\n",
331
     function,
332
     volume_header->serial_number );
333
334
    byte_stream_copy_to_uint64_little_endian(
335
     ( (fvde_volume_header_t *) data )->unknown2,
336
     value_64bit );
337
    libcnotify_printf(
338
     "%s: unknown2\t\t\t\t: 0x%08" PRIx64 "\n",
339
     function,
340
     value_64bit );
341
342
    byte_stream_copy_to_uint64_little_endian(
343
     ( (fvde_volume_header_t *) data )->unknown3a,
344
     value_64bit );
345
    libcnotify_printf(
346
     "%s: unknown3a\t\t\t\t: 0x%08" PRIx64 "\n",
347
     function,
348
     value_64bit );
349
350
    byte_stream_copy_to_uint64_little_endian(
351
     ( (fvde_volume_header_t *) data )->unknown3b,
352
     value_64bit );
353
    libcnotify_printf(
354
     "%s: unknown3b\t\t\t\t: 0x%08" PRIx64 "\n",
355
     function,
356
     value_64bit );
357
358
    byte_stream_copy_to_uint64_little_endian(
359
     ( (fvde_volume_header_t *) data )->unknown3c,
360
     value_64bit );
361
    libcnotify_printf(
362
     "%s: unknown3c\t\t\t\t: 0x%08" PRIx64 "\n",
363
     function,
364
     value_64bit );
365
366
    libcnotify_printf(
367
     "%s: bytes per sector\t\t\t: %" PRIu32 "\n",
368
     function,
369
     volume_header->bytes_per_sector );
370
371
    byte_stream_copy_to_uint32_little_endian(
372
     ( (fvde_volume_header_t *) data )->unknown4a,
373
     value_32bit );
374
    libcnotify_printf(
375
     "%s: unknown4a\t\t\t\t: 0x%08" PRIx32 "\n",
376
     function,
377
     value_32bit );
378
379
    byte_stream_copy_to_uint64_little_endian(
380
     ( (fvde_volume_header_t *) data )->unknown4b,
381
     value_64bit );
382
    libcnotify_printf(
383
     "%s: unknown4b\t\t\t\t: 0x%08" PRIx64 "\n",
384
     function,
385
     value_64bit );
386
387
    libcnotify_printf(
388
     "%s: physical volume size\t\t\t: %" PRIu64 "\n",
389
     function,
390
     volume_header->physical_volume_size );
391
392
    libcnotify_printf(
393
     "%s: unknown5:\n",
394
     function );
395
    libcnotify_print_data(
396
     ( (fvde_volume_header_t *) data )->unknown5,
397
     16,
398
     0 );
399
400
    libcnotify_printf(
401
     "%s: core storage signature\t\t\t: %c%c\n",
402
     function,
403
     ( (fvde_volume_header_t *) data )->core_storage_signature[ 0 ],
404
     ( (fvde_volume_header_t *) data )->core_storage_signature[ 1 ] );
405
406
    libcnotify_printf(
407
     "%s: checksum algorithm\t\t\t: %" PRIu32 "\n",
408
     function,
409
     checksum_algorithm );
410
411
    byte_stream_copy_to_uint16_little_endian(
412
     ( (fvde_volume_header_t *) data )->unknown6,
413
     value_16bit );
414
    libcnotify_printf(
415
     "%s: unknown6\t\t\t\t: 0x%04" PRIx16 "\n",
416
     function,
417
     value_16bit );
418
419
    libcnotify_printf(
420
     "%s: block size\t\t\t\t: %" PRIu32 "\n",
421
     function,
422
     volume_header->block_size );
423
424
    libcnotify_printf(
425
     "%s: metadata size\t\t\t\t: %" PRIu32 "\n",
426
     function,
427
     volume_header->metadata_size );
428
429
    for( metadata_block_index = 0;
430
         metadata_block_index < 4;
431
         metadata_block_index++ )
432
    {
433
      libcnotify_printf(
434
       "%s: metadata: %d block number\t\t: %" PRIu64 "\n",
435
       function,
436
       metadata_block_index + 1,
437
       volume_header->metadata_offsets[ metadata_block_index] );
438
    }
439
    libcnotify_printf(
440
     "%s: unknown7:\n",
441
     function );
442
    libcnotify_print_data(
443
     ( (fvde_volume_header_t *) data )->unknown7,
444
     32,
445
     0 );
446
447
    byte_stream_copy_to_uint32_little_endian(
448
     ( (fvde_volume_header_t *) data )->key_data_size,
449
     value_32bit );
450
    libcnotify_printf(
451
     "%s: key data size\t\t\t\t: %" PRIu32 "\n",
452
     function,
453
     value_32bit );
454
455
    libcnotify_printf(
456
     "%s: encryption method\t\t\t: %" PRIu32 "\n",
457
     function,
458
     volume_header->physical_volume_encryption_method );
459
460
    libcnotify_printf(
461
     "%s: key data:\n",
462
     function );
463
    libcnotify_print_data(
464
     ( (fvde_volume_header_t *) data )->key_data,
465
     128,
466
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
467
468
    if( libfvde_debug_print_guid_value(
469
         function,
470
         "physical volume identifier\t\t",
471
         volume_header->physical_volume_identifier,
472
         16,
473
         LIBFGUID_ENDIAN_BIG,
474
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
475
         error ) != 1 )
476
    {
477
      libcerror_error_set(
478
       error,
479
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
480
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
481
       "%s: unable to print GUID value.",
482
       function );
483
484
      return( -1 );
485
    }
486
    if( libfvde_debug_print_guid_value(
487
         function,
488
         "volume group identifier\t\t",
489
         volume_header->volume_group_identifier,
490
         16,
491
         LIBFGUID_ENDIAN_BIG,
492
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
493
         error ) != 1 )
494
    {
495
      libcerror_error_set(
496
       error,
497
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
498
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
499
       "%s: unable to print GUID value.",
500
       function );
501
502
      return( -1 );
503
    }
504
    libcnotify_printf(
505
     "%s: unknown8:\n",
506
     function );
507
    libcnotify_print_data(
508
     ( (fvde_volume_header_t *) data )->unknown8,
509
     176,
510
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
511
  }
512
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
513
514
1.34k
  if( memory_compare(
515
1.34k
       ( (fvde_volume_header_t *) data )->core_storage_signature,
516
1.34k
       "CS",
517
1.34k
       2 ) != 0 )
518
39
  {
519
39
    libcerror_error_set(
520
39
     error,
521
39
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
522
39
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
523
39
     "%s: unsupported core storage signature.",
524
39
     function );
525
526
39
    return( -1 );
527
39
  }
528
1.30k
  if( format_version != 1 )
529
16
  {
530
16
    libcerror_error_set(
531
16
     error,
532
16
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
533
16
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
534
16
     "%s: unsupported format version: %" PRIu16 ".",
535
16
     function,
536
16
     format_version );
537
538
16
    return( -1 );
539
16
  }
540
1.28k
  if( checksum_algorithm != 1 )
541
38
  {
542
38
    libcerror_error_set(
543
38
     error,
544
38
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
545
38
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
546
38
     "%s: unsupported checksum algorithm: %" PRIu32 ".",
547
38
     function,
548
38
     checksum_algorithm );
549
550
38
    return( -1 );
551
38
  }
552
1.24k
  if( initial_value != 0xffffffffUL )
553
46
  {
554
46
    libcerror_error_set(
555
46
     error,
556
46
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
557
46
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
558
46
     "%s: unsupported initial value: 0x%08" PRIx32 ".",
559
46
     function,
560
46
     initial_value );
561
562
46
    return( -1 );
563
46
  }
564
1.20k
  if( libfvde_checksum_calculate_weak_crc32(
565
1.20k
       &calculated_checksum,
566
1.20k
       &( data[ 8 ] ),
567
1.20k
       504,
568
1.20k
       initial_value,
569
1.20k
       error ) != 1 )
570
0
  {
571
0
    libcerror_error_set(
572
0
     error,
573
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
574
0
     LIBCERROR_RUNTIME_ERROR_GENERIC,
575
0
     "%s: unable to calculate weak CRC-32.",
576
0
     function );
577
578
0
    return( -1 );
579
0
  }
580
1.20k
  if( stored_checksum != calculated_checksum )
581
51
  {
582
51
    libcerror_error_set(
583
51
     error,
584
51
     LIBCERROR_ERROR_DOMAIN_INPUT,
585
51
     LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
586
51
     "%s: mismatch in checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).",
587
51
     function,
588
51
     stored_checksum,
589
51
     calculated_checksum );
590
591
51
    return( -1 );
592
51
  }
593
1.15k
  if( block_type != 0x0010 )
594
16
  {
595
16
    libcerror_error_set(
596
16
     error,
597
16
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
598
16
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
599
16
     "%s: unsupported block type: 0x%08" PRIx16 ".",
600
16
     function,
601
16
     block_type );
602
603
16
    return( -1 );
604
16
  }
605
1.13k
  if( volume_header->physical_volume_encryption_method != 2 )
606
42
  {
607
42
    libcerror_error_set(
608
42
     error,
609
42
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
610
42
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
611
42
     "%s: unsupported encryption method: %" PRIu32 ".",
612
42
     function,
613
42
     volume_header->physical_volume_encryption_method );
614
615
42
    return( -1 );
616
42
  }
617
1.09k
  if( volume_header->bytes_per_sector == 0 )
618
1
  {
619
1
    libcerror_error_set(
620
1
     error,
621
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
622
1
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
623
1
     "%s: invalid bytes per sector value out of bounds.",
624
1
     function );
625
626
1
    return( -1 );
627
1
  }
628
1.09k
  if( volume_header->block_size == 0 )
629
1
  {
630
1
    libcerror_error_set(
631
1
     error,
632
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
633
1
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
634
1
     "%s: invalid block size value out of bounds.",
635
1
     function );
636
637
1
    return( -1 );
638
1
  }
639
1.09k
  for( metadata_block_index = 0;
640
5.30k
       metadata_block_index < 4;
641
4.21k
       metadata_block_index++ )
642
4.26k
  {
643
4.26k
    if( volume_header->metadata_offsets[ metadata_block_index ] > ( (uint64_t) INT64_MAX / volume_header->block_size ) )
644
54
    {
645
54
      libcerror_error_set(
646
54
       error,
647
54
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
648
54
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
649
54
       "%s: invalid metadata: %d block number value out of bounds.",
650
54
       function,
651
54
       metadata_block_index + 1 );
652
653
54
      return( -1 );
654
54
    }
655
4.21k
    volume_header->metadata_offsets[ metadata_block_index ] *= volume_header->block_size;
656
4.21k
  }
657
1.03k
  return( 1 );
658
1.09k
}
659
660
/* Reads the volume header
661
 * Returns 1 if successful or -1 on error
662
 */
663
int libfvde_volume_header_read_file_io_handle(
664
     libfvde_volume_header_t *volume_header,
665
     libbfio_handle_t *file_io_handle,
666
     off64_t file_offset,
667
     libcerror_error_t **error )
668
1.35k
{
669
1.35k
  uint8_t volume_header_data[ sizeof( fvde_volume_header_t ) ];
670
671
1.35k
  static char *function = "libfvde_volume_header_read_file_io_handle";
672
1.35k
  ssize_t read_count    = 0;
673
674
1.35k
  if( volume_header == NULL )
675
0
  {
676
0
    libcerror_error_set(
677
0
     error,
678
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
679
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
680
0
     "%s: invalid volume header.",
681
0
     function );
682
683
0
    return( -1 );
684
0
  }
685
#if defined( HAVE_DEBUG_OUTPUT )
686
  if( libcnotify_verbose != 0 )
687
  {
688
    libcnotify_printf(
689
     "%s: reading volume header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
690
     function,
691
     file_offset,
692
     file_offset );
693
  }
694
#endif
695
1.35k
  read_count = libbfio_handle_read_buffer_at_offset(
696
1.35k
                file_io_handle,
697
1.35k
                (uint8_t *) &volume_header_data,
698
1.35k
                sizeof( fvde_volume_header_t ),
699
1.35k
                file_offset,
700
1.35k
                error );
701
702
1.35k
  if( read_count != (ssize_t) sizeof( fvde_volume_header_t ) )
703
16
  {
704
16
    libcerror_error_set(
705
16
     error,
706
16
     LIBCERROR_ERROR_DOMAIN_IO,
707
16
     LIBCERROR_IO_ERROR_READ_FAILED,
708
16
     "%s: unable to read volume header data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
709
16
     function,
710
16
     file_offset,
711
16
     file_offset );
712
713
16
    return( -1 );
714
16
  }
715
1.34k
  if( libfvde_volume_header_read_data(
716
1.34k
       volume_header,
717
1.34k
       (uint8_t *) &volume_header_data,
718
1.34k
       sizeof( fvde_volume_header_t ),
719
1.34k
       error ) != 1 )
720
304
  {
721
304
    libcerror_error_set(
722
304
     error,
723
304
     LIBCERROR_ERROR_DOMAIN_IO,
724
304
     LIBCERROR_IO_ERROR_READ_FAILED,
725
304
     "%s: unable to read volume header data.",
726
304
     function );
727
728
304
    return( -1 );
729
304
  }
730
1.03k
  return( 1 );
731
1.34k
}
732
733
/* Retrieves the (logical) volume group identifier
734
 * The identifier is a UUID and is 16 bytes of size
735
 * Returns 1 if successful or -1 on error
736
 */
737
int libfvde_volume_header_get_volume_group_identifier(
738
     libfvde_volume_header_t *volume_header,
739
     uint8_t *uuid_data,
740
     size_t uuid_data_size,
741
     libcerror_error_t **error )
742
0
{
743
0
  static char *function = "libfvde_volume_header_get_volume_group_identifier";
744
745
0
  if( volume_header == NULL )
746
0
  {
747
0
    libcerror_error_set(
748
0
     error,
749
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
750
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
751
0
     "%s: invalid volume header.",
752
0
     function );
753
754
0
    return( -1 );
755
0
  }
756
0
  if( uuid_data == NULL )
757
0
  {
758
0
    libcerror_error_set(
759
0
     error,
760
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
761
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
762
0
     "%s: invalid UUID data.",
763
0
     function );
764
765
0
    return( -1 );
766
0
  }
767
0
  if( ( uuid_data_size < 16 )
768
0
   || ( uuid_data_size > (size_t) SSIZE_MAX ) )
769
0
  {
770
0
    libcerror_error_set(
771
0
     error,
772
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
773
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
774
0
     "%s: invalid UUID data size value out of bounds.",
775
0
     function );
776
777
0
    return( -1 );
778
0
  }
779
0
  if( memory_copy(
780
0
       uuid_data,
781
0
       volume_header->volume_group_identifier,
782
0
       16 ) == NULL )
783
0
  {
784
0
    libcerror_error_set(
785
0
     error,
786
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
787
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
788
0
     "%s: unable to copy volume group identifier.",
789
0
     function );
790
791
0
    return( -1 );
792
0
  }
793
0
  return( 1 );
794
0
}
795
796
/* Retrieves the physical volume identifier
797
 * The identifier is a UUID and is 16 bytes of size
798
 * Returns 1 if successful or -1 on error
799
 */
800
int libfvde_volume_header_get_physical_volume_identifier(
801
     libfvde_volume_header_t *volume_header,
802
     uint8_t *uuid_data,
803
     size_t uuid_data_size,
804
     libcerror_error_t **error )
805
0
{
806
0
  static char *function = "libfvde_volume_header_get_physical_volume_identifier";
807
808
0
  if( volume_header == NULL )
809
0
  {
810
0
    libcerror_error_set(
811
0
     error,
812
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
813
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
814
0
     "%s: invalid volume header.",
815
0
     function );
816
817
0
    return( -1 );
818
0
  }
819
0
  if( uuid_data == NULL )
820
0
  {
821
0
    libcerror_error_set(
822
0
     error,
823
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
824
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
825
0
     "%s: invalid UUID data.",
826
0
     function );
827
828
0
    return( -1 );
829
0
  }
830
0
  if( ( uuid_data_size < 16 )
831
0
   || ( uuid_data_size > (size_t) SSIZE_MAX ) )
832
0
  {
833
0
    libcerror_error_set(
834
0
     error,
835
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
836
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
837
0
     "%s: invalid UUID data size value out of bounds.",
838
0
     function );
839
840
0
    return( -1 );
841
0
  }
842
0
  if( memory_copy(
843
0
       uuid_data,
844
0
       volume_header->physical_volume_identifier,
845
0
       16 ) == NULL )
846
0
  {
847
0
    libcerror_error_set(
848
0
     error,
849
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
850
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
851
0
     "%s: unable to copy physical volume identifier.",
852
0
     function );
853
854
0
    return( -1 );
855
0
  }
856
0
  return( 1 );
857
0
}
858
859
/* Retrieves the physical volume encryption method
860
 * Returns 1 if successful or -1 on error
861
 */
862
int libfvde_volume_header_get_physical_volume_encryption_method(
863
     libfvde_volume_header_t *volume_header,
864
     uint32_t *encryption_method,
865
     libcerror_error_t **error )
866
0
{
867
0
  static char *function = "libfvde_volume_header_get_physical_volume_encryption_method";
868
869
0
  if( volume_header == NULL )
870
0
  {
871
0
    libcerror_error_set(
872
0
     error,
873
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
874
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
875
0
     "%s: invalid volume header.",
876
0
     function );
877
878
0
    return( -1 );
879
0
  }
880
0
  if( encryption_method == NULL )
881
0
  {
882
0
    libcerror_error_set(
883
0
     error,
884
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
885
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
886
0
     "%s: invalid encryption method.",
887
0
     function );
888
889
0
    return( -1 );
890
0
  }
891
0
  *encryption_method = volume_header->physical_volume_encryption_method;
892
893
0
  return( 1 );
894
0
}
895
896
/* Retrieves the physical volume size
897
 * Returns 1 if successful or -1 on error
898
 */
899
int libfvde_volume_header_get_physical_volume_size(
900
     libfvde_volume_header_t *volume_header,
901
     size64_t *size,
902
     libcerror_error_t **error )
903
0
{
904
0
  static char *function = "libfvde_volume_header_get_physical_volume_size";
905
906
0
  if( volume_header == NULL )
907
0
  {
908
0
    libcerror_error_set(
909
0
     error,
910
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
911
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
912
0
     "%s: invalid volume header.",
913
0
     function );
914
915
0
    return( -1 );
916
0
  }
917
0
  if( size == NULL )
918
0
  {
919
0
    libcerror_error_set(
920
0
     error,
921
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
922
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
923
0
     "%s: invalid size.",
924
0
     function );
925
926
0
    return( -1 );
927
0
  }
928
0
  *size = volume_header->physical_volume_size;
929
930
0
  return( 1 );
931
0
}
932