Coverage Report

Created: 2026-05-30 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfvde/libfvde/libfvde_metadata.c
Line
Count
Source
1
/*
2
 * Metadata functions
3
 *
4
 * Copyright (C) 2011-2026, Omar Choudary <choudary.omar@gmail.com>
5
 *                          Joachim Metz <joachim.metz@gmail.com>
6
 *
7
 * Refer to AUTHORS for acknowledgements.
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Lesser General Public License as published by
11
 * the Free Software Foundation, either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
21
 */
22
23
#include <common.h>
24
#include <byte_stream.h>
25
#include <memory.h>
26
#include <narrow_string.h>
27
#include <types.h>
28
29
#include "libfvde_checksum.h"
30
#include "libfvde_io_handle.h"
31
#include "libfvde_libbfio.h"
32
#include "libfvde_libcdata.h"
33
#include "libfvde_libcerror.h"
34
#include "libfvde_libcnotify.h"
35
#include "libfvde_libfplist.h"
36
#include "libfvde_libuna.h"
37
#include "libfvde_metadata.h"
38
#include "libfvde_metadata_block.h"
39
#include "libfvde_physical_volume_descriptor.h"
40
41
#include "fvde_metadata.h"
42
43
/* Creates metadata
44
 * Make sure the value metadata is referencing, is set to NULL
45
 * Returns 1 if successful or -1 on error
46
 */
47
int libfvde_metadata_initialize(
48
     libfvde_metadata_t **metadata,
49
     libcerror_error_t **error )
50
1.17k
{
51
1.17k
  static char *function = "libfvde_metadata_initialize";
52
53
1.17k
  if( metadata == NULL )
54
0
  {
55
0
    libcerror_error_set(
56
0
     error,
57
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
58
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
59
0
     "%s: invalid metadata.",
60
0
     function );
61
62
0
    return( -1 );
63
0
  }
64
1.17k
  if( *metadata != NULL )
65
0
  {
66
0
    libcerror_error_set(
67
0
     error,
68
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
69
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
70
0
     "%s: invalid metadata value already set.",
71
0
     function );
72
73
0
    return( -1 );
74
0
  }
75
1.17k
  *metadata = memory_allocate_structure(
76
1.17k
               libfvde_metadata_t );
77
78
1.17k
  if( *metadata == NULL )
79
0
  {
80
0
    libcerror_error_set(
81
0
     error,
82
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
83
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
84
0
     "%s: unable to create metadata.",
85
0
     function );
86
87
0
    goto on_error;
88
0
  }
89
1.17k
  if( memory_set(
90
1.17k
       *metadata,
91
1.17k
       0,
92
1.17k
       sizeof( libfvde_metadata_t ) ) == NULL )
93
0
  {
94
0
    libcerror_error_set(
95
0
     error,
96
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
97
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
98
0
     "%s: unable to clear metadata.",
99
0
     function );
100
101
0
    memory_free(
102
0
     *metadata );
103
104
0
    *metadata = NULL;
105
106
0
    return( -1 );
107
0
  }
108
1.17k
  if( libcdata_array_initialize(
109
1.17k
       &( ( *metadata )->physical_volume_descriptors ),
110
1.17k
       0,
111
1.17k
       error ) != 1 )
112
0
  {
113
0
    libcerror_error_set(
114
0
     error,
115
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
116
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
117
0
     "%s: unable to create physical volume descriptors array.",
118
0
     function );
119
120
0
    goto on_error;
121
0
  }
122
1.17k
  return( 1 );
123
124
0
on_error:
125
0
  if( *metadata != NULL )
126
0
  {
127
0
    memory_free(
128
0
     *metadata );
129
130
0
    *metadata = NULL;
131
0
  }
132
0
  return( -1 );
133
1.17k
}
134
135
/* Frees metadata
136
 * Returns 1 if successful or -1 on error
137
 */
138
int libfvde_metadata_free(
139
     libfvde_metadata_t **metadata,
140
     libcerror_error_t **error )
141
1.17k
{
142
1.17k
  static char *function = "libfvde_metadata_free";
143
1.17k
  int result            = 1;
144
145
1.17k
  if( metadata == NULL )
146
0
  {
147
0
    libcerror_error_set(
148
0
     error,
149
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
150
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
151
0
     "%s: invalid metadata.",
152
0
     function );
153
154
0
    return( -1 );
155
0
  }
156
1.17k
  if( *metadata != NULL )
157
1.17k
  {
158
1.17k
    if( ( *metadata )->volume_group_name != NULL )
159
4
    {
160
4
      memory_free(
161
4
       ( *metadata )->volume_group_name );
162
4
    }
163
1.17k
    if( libcdata_array_free(
164
1.17k
         &( ( *metadata )->physical_volume_descriptors ),
165
1.17k
         (int (*)(intptr_t **, libcerror_error_t **)) &libfvde_physical_volume_descriptor_free,
166
1.17k
         error ) != 1 )
167
0
    {
168
0
      libcerror_error_set(
169
0
       error,
170
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
171
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
172
0
       "%s: unable to free physical volume descriptors array.",
173
0
       function );
174
175
0
      result = -1;
176
0
    }
177
1.17k
    memory_free(
178
1.17k
     *metadata );
179
180
1.17k
    *metadata = NULL;
181
1.17k
  }
182
1.17k
  return( result );
183
1.17k
}
184
185
/* Reads the metadata block type 0x0011
186
 * Returns 1 if successful or -1 on error
187
 */
188
int libfvde_metadata_read_type_0x0011(
189
     libfvde_metadata_t *metadata,
190
     libfvde_io_handle_t *io_handle,
191
     uint64_t transaction_identifier,
192
     const uint8_t *block_data,
193
     size_t block_data_size,
194
     libcerror_error_t **error )
195
711
{
196
711
  static char *function                    = "libfvde_metadata_read_type_0x0011";
197
711
  size_t block_data_offset                 = 0;
198
711
  uint32_t entry_index                     = 0;
199
711
  uint32_t metadata_size                   = 0;
200
711
  uint32_t number_of_entries               = 0;
201
711
  uint32_t volume_groups_descriptor_offset = 0;
202
711
  uint32_t xml_offset                      = 0;
203
204
#if defined( HAVE_DEBUG_OUTPUT )
205
  uint64_t value_64bit                     = 0;
206
  uint32_t value_32bit                     = 0;
207
  uint16_t value_16bit                     = 0;
208
#endif
209
210
711
  if( metadata == NULL )
211
0
  {
212
0
    libcerror_error_set(
213
0
     error,
214
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
215
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
216
0
     "%s: invalid metadata.",
217
0
     function );
218
219
0
    return( -1 );
220
0
  }
221
711
  if( io_handle == NULL )
222
0
  {
223
0
    libcerror_error_set(
224
0
     error,
225
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
226
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
227
0
     "%s: invalid IO handle.",
228
0
     function );
229
230
0
    return( -1 );
231
0
  }
232
711
  if( block_data == NULL )
233
0
  {
234
0
    libcerror_error_set(
235
0
     error,
236
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
237
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
238
0
     "%s: invalid block data.",
239
0
     function );
240
241
0
    return( -1 );
242
0
  }
243
711
  if( ( block_data_size < 192 )
244
711
   || ( block_data_size > (size_t) SSIZE_MAX ) )
245
0
  {
246
0
    libcerror_error_set(
247
0
     error,
248
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
249
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
250
0
     "%s: invalid block data size value out of bounds.",
251
0
     function );
252
253
0
    return( -1 );
254
0
  }
255
711
  byte_stream_copy_to_uint32_little_endian(
256
711
   block_data,
257
711
   metadata_size );
258
259
711
  byte_stream_copy_to_uint32_little_endian(
260
711
   &( block_data[ 156 ] ),
261
711
   volume_groups_descriptor_offset );
262
263
711
  byte_stream_copy_to_uint32_little_endian(
264
711
   &( block_data[ 160 ] ),
265
711
   xml_offset );
266
267
711
  byte_stream_copy_to_uint16_little_endian(
268
711
   &( block_data[ 174 ] ),
269
711
   metadata->physical_volume_index );
270
271
#if defined( HAVE_DEBUG_OUTPUT )
272
  if( libcnotify_verbose != 0 )
273
  {
274
    libcnotify_printf(
275
     "%s: metadata size\t\t\t: %" PRIu32 "\n",
276
     function,
277
     metadata_size );
278
279
    byte_stream_copy_to_uint32_little_endian(
280
     &( block_data[ 4 ] ),
281
     value_32bit );
282
    libcnotify_printf(
283
     "%s: unknown1\t\t\t\t: 0x%08" PRIx32 "\n",
284
     function,
285
     value_32bit );
286
287
    byte_stream_copy_to_uint32_little_endian(
288
     &( block_data[ 8 ] ),
289
     value_32bit );
290
    libcnotify_printf(
291
     "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n",
292
     function,
293
     value_32bit );
294
295
    byte_stream_copy_to_uint32_little_endian(
296
     &( block_data[ 12 ] ),
297
     value_32bit );
298
    libcnotify_printf(
299
     "%s: initial value\t\t\t: 0x%08" PRIx32 "\n",
300
     function,
301
     value_32bit );
302
303
    byte_stream_copy_to_uint32_little_endian(
304
     &( block_data[ 16 ] ),
305
     value_32bit );
306
    libcnotify_printf(
307
     "%s: unknown2\t\t\t\t: 0x%08" PRIx32 "\n",
308
     function,
309
     value_32bit );
310
311
    byte_stream_copy_to_uint32_little_endian(
312
     &( block_data[ 20 ] ),
313
     value_32bit );
314
    libcnotify_printf(
315
     "%s: unknown3\t\t\t\t: 0x%08" PRIx32 "\n",
316
     function,
317
     value_32bit );
318
319
    byte_stream_copy_to_uint32_little_endian(
320
     &( block_data[ 24 ] ),
321
     value_32bit );
322
    libcnotify_printf(
323
     "%s: unknown4\t\t\t\t: 0x%08" PRIx32 "\n",
324
     function,
325
     value_32bit );
326
327
    byte_stream_copy_to_uint32_little_endian(
328
     &( block_data[ 28 ] ),
329
     value_32bit );
330
    libcnotify_printf(
331
     "%s: unknown5\t\t\t\t: 0x%08" PRIx32 "\n",
332
     function,
333
     value_32bit );
334
335
    libcnotify_printf(
336
     "%s: unknown6:\n",
337
     function );
338
    libcnotify_print_data(
339
     &( block_data[ 32 ] ),
340
     40,
341
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
342
343
    byte_stream_copy_to_uint32_little_endian(
344
     &( block_data[ 72 ] ),
345
     value_32bit );
346
    libcnotify_printf(
347
     "%s: unknown7\t\t\t\t: 0x%08" PRIx32 "\n",
348
     function,
349
     value_32bit );
350
351
    byte_stream_copy_to_uint32_little_endian(
352
     &( block_data[ 76 ] ),
353
     value_32bit );
354
    libcnotify_printf(
355
     "%s: unknown8\t\t\t\t: 0x%08" PRIx32 "\n",
356
     function,
357
     value_32bit );
358
359
    libcnotify_printf(
360
     "%s: unknown9:\n",
361
     function );
362
    libcnotify_print_data(
363
     &( block_data[ 80 ] ),
364
     24,
365
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
366
367
    byte_stream_copy_to_uint32_little_endian(
368
     &( block_data[ 104 ] ),
369
     value_32bit );
370
    libcnotify_printf(
371
     "%s: unknown10\t\t\t\t: 0x%08" PRIx32 "\n",
372
     function,
373
     value_32bit );
374
375
    byte_stream_copy_to_uint32_little_endian(
376
     &( block_data[ 108 ] ),
377
     value_32bit );
378
    libcnotify_printf(
379
     "%s: unknown11\t\t\t\t: 0x%08" PRIx32 "\n",
380
     function,
381
     value_32bit );
382
383
    byte_stream_copy_to_uint32_little_endian(
384
     &( block_data[ 112 ] ),
385
     value_32bit );
386
    libcnotify_printf(
387
     "%s: unknown12\t\t\t\t: 0x%08" PRIx32 "\n",
388
     function,
389
     value_32bit );
390
391
    byte_stream_copy_to_uint16_little_endian(
392
     &( block_data[ 116 ] ),
393
     value_16bit );
394
    libcnotify_printf(
395
     "%s: unknown13a\t\t\t\t: 0x%04" PRIx16 "\n",
396
     function,
397
     value_16bit );
398
399
    byte_stream_copy_to_uint16_little_endian(
400
     &( block_data[ 118 ] ),
401
     value_16bit );
402
    libcnotify_printf(
403
     "%s: unknown13b\t\t\t\t: 0x%04" PRIx16 "\n",
404
     function,
405
     value_16bit );
406
407
    byte_stream_copy_to_uint32_little_endian(
408
     &( block_data[ 120 ] ),
409
     value_32bit );
410
    libcnotify_printf(
411
     "%s: unknown14\t\t\t\t: 0x%08" PRIx32 "\n",
412
     function,
413
     value_32bit );
414
415
    byte_stream_copy_to_uint16_little_endian(
416
     &( block_data[ 124 ] ),
417
     value_16bit );
418
    libcnotify_printf(
419
     "%s: unknown15a\t\t\t\t: 0x%04" PRIx16 "\n",
420
     function,
421
     value_16bit );
422
423
    byte_stream_copy_to_uint16_little_endian(
424
     &( block_data[ 126 ] ),
425
     value_16bit );
426
    libcnotify_printf(
427
     "%s: unknown15b\t\t\t\t: 0x%04" PRIx16 "\n",
428
     function,
429
     value_16bit );
430
431
    byte_stream_copy_to_uint32_little_endian(
432
     &( block_data[ 128 ] ),
433
     value_32bit );
434
    libcnotify_printf(
435
     "%s: unknown16\t\t\t\t: 0x%08" PRIx32 "\n",
436
     function,
437
     value_32bit );
438
439
    libcnotify_printf(
440
     "%s: unknown17:\n",
441
     function );
442
    libcnotify_print_data(
443
     &( block_data[ 132 ] ),
444
     24,
445
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
446
447
    libcnotify_printf(
448
     "%s: volume groups descriptor offset\t: 0x%08" PRIx32 "\n",
449
     function,
450
     volume_groups_descriptor_offset );
451
452
    libcnotify_printf(
453
     "%s: volume group XML offset\t\t: 0x%08" PRIx32 "\n",
454
     function,
455
     xml_offset );
456
457
    byte_stream_copy_to_uint32_little_endian(
458
     &( block_data[ 164 ] ),
459
     value_32bit );
460
    libcnotify_printf(
461
     "%s: volume group XML size\t\t: %" PRIu32 "\n",
462
     function,
463
     value_32bit );
464
465
    byte_stream_copy_to_uint32_little_endian(
466
     &( block_data[ 168 ] ),
467
     value_32bit );
468
    libcnotify_printf(
469
     "%s: volume group XML size copy\t\t: %" PRIu32 "\n",
470
     function,
471
     value_32bit );
472
473
    byte_stream_copy_to_uint16_little_endian(
474
     &( block_data[ 172 ] ),
475
     value_16bit );
476
    libcnotify_printf(
477
     "%s: unknown18\t\t\t\t: 0x%04" PRIx16 "\n",
478
     function,
479
     value_16bit );
480
481
    libcnotify_printf(
482
     "%s: physical volume index\t\t: %" PRIu16 "\n",
483
     function,
484
     metadata->physical_volume_index );
485
486
    byte_stream_copy_to_uint64_little_endian(
487
     &( block_data[ 176 ] ),
488
     value_64bit );
489
    libcnotify_printf(
490
     "%s: volume group number of blocks\t: %" PRIu64 "\n",
491
     function,
492
     value_64bit );
493
494
    libcnotify_printf(
495
     "\n" );
496
  }
497
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
498
499
711
  byte_stream_copy_to_uint32_little_endian(
500
711
   &( block_data[ 184 ] ),
501
711
   number_of_entries );
502
503
#if defined( HAVE_DEBUG_OUTPUT )
504
  if( libcnotify_verbose != 0 )
505
  {
506
    libcnotify_printf(
507
     "%s: number of entries\t\t\t: %" PRIu32 "\n",
508
     function,
509
     number_of_entries );
510
511
    byte_stream_copy_to_uint32_little_endian(
512
     &( block_data[ 188 ] ),
513
     value_32bit );
514
    libcnotify_printf(
515
     "%s: unknown19\t\t\t\t: 0x%08" PRIx32 "\n",
516
     function,
517
     value_32bit );
518
519
    libcnotify_printf(
520
     "\n" );
521
  }
522
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
523
524
711
  block_data_offset = 192;
525
526
711
  if( number_of_entries > ( ( block_data_size - block_data_offset ) / 24 ) )
527
23
  {
528
23
    libcerror_error_set(
529
23
     error,
530
23
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
531
23
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
532
23
     "%s: invalid number of entries value out of bounds.",
533
23
     function );
534
535
23
    return( -1 );
536
23
  }
537
688
  for( entry_index = 0;
538
32.5k
       entry_index < number_of_entries;
539
31.8k
       entry_index++ )
540
31.8k
  {
541
#if defined( HAVE_DEBUG_OUTPUT )
542
    if( libcnotify_verbose != 0 )
543
    {
544
      byte_stream_copy_to_uint64_little_endian(
545
       &( block_data[ block_data_offset ] ),
546
       value_64bit );
547
      libcnotify_printf(
548
       "%s: entry: %03d transaction identifier\t: %" PRIu64 "\n",
549
       function,
550
       entry_index,
551
       value_64bit );
552
553
      byte_stream_copy_to_uint64_little_endian(
554
       &( block_data[ block_data_offset + 8 ] ),
555
       value_64bit );
556
      libcnotify_printf(
557
       "%s: entry: %03d unknown2\t\t\t: 0x%08" PRIx64 "\n",
558
       function,
559
       entry_index,
560
       value_64bit );
561
562
      byte_stream_copy_to_uint64_little_endian(
563
       &( block_data[ block_data_offset + 16 ] ),
564
       value_64bit );
565
      libcnotify_printf(
566
       "%s: entry: %03d metadata block number\t: %" PRIu64 "\n",
567
       function,
568
       entry_index,
569
       value_64bit );
570
571
      libcnotify_printf(
572
       "\n" );
573
    }
574
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
575
576
31.8k
    block_data_offset += 24;
577
31.8k
  }
578
688
  if( metadata_size != io_handle->metadata_size )
579
51
  {
580
51
    libcerror_error_set(
581
51
     error,
582
51
     LIBCERROR_ERROR_DOMAIN_INPUT,
583
51
     LIBCERROR_INPUT_ERROR_VALUE_MISMATCH,
584
51
     "%s: value mismatch for metadata size.",
585
51
     function );
586
587
51
    return( -1 );
588
51
  }
589
637
  if( ( volume_groups_descriptor_offset < 248 )
590
627
   || ( volume_groups_descriptor_offset > block_data_size ) )
591
58
  {
592
58
    libcerror_error_set(
593
58
     error,
594
58
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
595
58
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
596
58
     "%s: invalid volume groups descriptor offset value out of bounds.",
597
58
     function );
598
599
58
    return( -1 );
600
58
  }
601
#if defined( HAVE_DEBUG_OUTPUT )
602
  if( libcnotify_verbose != 0 )
603
  {
604
    if( block_data_offset < ( block_data_size - 64 ) )
605
    {
606
      libcnotify_printf(
607
       "%s: remaining data:\n",
608
       function );
609
      libcnotify_print_data(
610
       &( block_data[ block_data_offset ] ),
611
       block_data_size - ( block_data_offset + 64 ),
612
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
613
    }
614
  }
615
#endif
616
  /* The offset is relative to the start of the metadata block */
617
579
  volume_groups_descriptor_offset -= 64;
618
619
579
  byte_stream_copy_to_uint64_little_endian(
620
579
   &( block_data[ volume_groups_descriptor_offset + 8 ] ),
621
579
   metadata->encrypted_metadata_size );
622
623
579
  byte_stream_copy_to_uint64_little_endian(
624
579
   &( block_data[ volume_groups_descriptor_offset + 32 ] ),
625
579
   metadata->encrypted_metadata1_offset );
626
627
579
  metadata->encrypted_metadata1_volume_index = (uint16_t) ( metadata->encrypted_metadata1_offset >> 48 );
628
579
  metadata->encrypted_metadata1_offset      &= 0x0000ffffffffffffUL;
629
630
579
  byte_stream_copy_to_uint64_little_endian(
631
579
   &( block_data[ volume_groups_descriptor_offset + 40 ] ),
632
579
   metadata->encrypted_metadata2_offset );
633
634
579
  metadata->encrypted_metadata2_volume_index = (uint16_t) ( metadata->encrypted_metadata2_offset >> 48 );
635
579
  metadata->encrypted_metadata2_offset      &= 0x0000ffffffffffffUL;
636
637
#if defined( HAVE_DEBUG_OUTPUT )
638
  if( libcnotify_verbose != 0 )
639
  {
640
    byte_stream_copy_to_uint64_little_endian(
641
     &( block_data[ volume_groups_descriptor_offset ] ),
642
     value_64bit );
643
    libcnotify_printf(
644
     "%s: unknown1\t\t\t\t: 0x%08" PRIx64 "\n",
645
     function,
646
     value_64bit );
647
648
    libcnotify_printf(
649
     "%s: encrypted metadata number of blocks\t: %" PRIu64 "\n",
650
     function,
651
     metadata->encrypted_metadata_size );
652
653
    byte_stream_copy_to_uint64_little_endian(
654
     &( block_data[ volume_groups_descriptor_offset + 16 ] ),
655
     value_64bit );
656
    libcnotify_printf(
657
     "%s: unknown3\t\t\t\t: 0x%08" PRIx64 "\n",
658
     function,
659
     value_64bit );
660
661
    byte_stream_copy_to_uint64_little_endian(
662
     &( block_data[ volume_groups_descriptor_offset + 24 ] ),
663
     value_64bit );
664
    libcnotify_printf(
665
     "%s: unknown4\t\t\t\t: 0x%08" PRIx64 "\n",
666
     function,
667
     value_64bit );
668
669
    libcnotify_printf(
670
     "%s: encrypted metadata: 1 block number\t: %" PRIu64 "\n",
671
     function,
672
     metadata->encrypted_metadata1_offset );
673
674
    libcnotify_printf(
675
     "%s: encrypted metadata: 1 volume index\t: %" PRIu16 "\n",
676
     function,
677
     metadata->encrypted_metadata1_volume_index );
678
679
    libcnotify_printf(
680
     "%s: encrypted metadata: 2 block number\t: %" PRIu64 "\n",
681
     function,
682
     metadata->encrypted_metadata2_offset );
683
684
    libcnotify_printf(
685
     "%s: encrypted metadata: 2 volume index\t: %" PRIu16 "\n",
686
     function,
687
     metadata->encrypted_metadata2_volume_index );
688
689
    libcnotify_printf(
690
     "\n" );
691
  }
692
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
693
694
579
  metadata->encrypted_metadata_size *= io_handle->block_size;
695
696
579
  if( ( xml_offset < 248 )
697
567
   || ( xml_offset > block_data_size ) )
698
63
  {
699
63
    libcerror_error_set(
700
63
     error,
701
63
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
702
63
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
703
63
     "%s: invalid XML offset value out of bounds.",
704
63
     function );
705
706
63
    return( -1 );
707
63
  }
708
  /* The offset is relative to the start of the metadata block */
709
516
  if( libfvde_metadata_read_volume_group_plist(
710
516
       metadata,
711
516
       &( block_data[ xml_offset - 64 ] ),
712
516
       block_data_size - xml_offset,
713
516
       error ) != 1 )
714
455
  {
715
455
    libcerror_error_set(
716
455
     error,
717
455
     LIBCERROR_ERROR_DOMAIN_IO,
718
455
     LIBCERROR_IO_ERROR_READ_FAILED,
719
455
     "%s: unable to read metadata block type 0x0011.",
720
455
     function );
721
722
455
    return( -1 );
723
455
  }
724
/* TODO add bounds check */
725
61
  metadata->encrypted_metadata1_offset &= 0x0000ffffffffffffUL;
726
61
  metadata->encrypted_metadata1_offset *= io_handle->block_size;
727
728
61
  metadata->encrypted_metadata2_offset &= 0x0000ffffffffffffUL;
729
61
  metadata->encrypted_metadata2_offset *= io_handle->block_size;
730
731
61
  metadata->transaction_identifier = transaction_identifier;
732
733
61
  return( 1 );
734
516
}
735
736
/* Reads the volume group (XML) plist
737
 * Returns 1 if successful or -1 on error
738
 */
739
int libfvde_metadata_read_volume_group_plist(
740
     libfvde_metadata_t *metadata,
741
     const uint8_t *xml_plist_data,
742
     size_t xml_plist_data_size,
743
     libcerror_error_t **error )
744
516
{
745
516
  libfplist_property_t *array_entry_property                       = NULL;
746
516
  libfplist_property_t *root_property                              = NULL;
747
516
  libfplist_property_t *sub_property                               = NULL;
748
516
  libfplist_property_list_t *property_list                         = NULL;
749
516
  libfvde_physical_volume_descriptor_t *physical_volume_descriptor = NULL;
750
516
  static char *function                                            = "libfvde_metadata_read_volume_group_plist";
751
516
  size_t xml_length                                                = 0;
752
516
  int entry_index                                                  = 0;
753
516
  int number_of_entries                                            = 0;
754
516
  int physical_volume_descriptor_index                             = 0;
755
756
#if defined( HAVE_DEBUG_OUTPUT )
757
  uint8_t *string                                                  = NULL;
758
  size_t string_size                                               = 0;
759
#endif
760
761
516
  if( metadata == NULL )
762
0
  {
763
0
    libcerror_error_set(
764
0
     error,
765
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
766
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
767
0
     "%s: invalid metadata.",
768
0
     function );
769
770
0
    return( -1 );
771
0
  }
772
516
  if( metadata->volume_group_name != NULL )
773
0
  {
774
0
    libcerror_error_set(
775
0
     error,
776
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
777
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
778
0
     "%s: invalid metadata - volume group name value already set.",
779
0
     function );
780
781
0
    return( -1 );
782
0
  }
783
516
  if( xml_plist_data == NULL )
784
0
  {
785
0
    libcerror_error_set(
786
0
     error,
787
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
788
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
789
0
     "%s: invalid XML plist data.",
790
0
     function );
791
792
0
    return( -1 );
793
0
  }
794
516
  if( ( xml_plist_data_size < 5 )
795
512
   || ( xml_plist_data_size > (size_t) SSIZE_MAX ) )
796
4
  {
797
4
    libcerror_error_set(
798
4
     error,
799
4
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
800
4
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
801
4
     "%s: invalid XML plist data size value out of bounds.",
802
4
     function );
803
804
4
    return( -1 );
805
4
  }
806
/* TODO return 0 if not a valid plist? */
807
512
  if( ( xml_plist_data[ 0 ] == (uint8_t) '<' )
808
483
   && ( xml_plist_data[ 1 ] == (uint8_t) 'd' )
809
475
   && ( xml_plist_data[ 2 ] == (uint8_t) 'i' )
810
472
   && ( xml_plist_data[ 3 ] == (uint8_t) 'c' )
811
465
   && ( xml_plist_data[ 4 ] == (uint8_t) 't' ) )
812
455
  {
813
#if defined( HAVE_DEBUG_OUTPUT )
814
    if( libcnotify_verbose != 0 )
815
    {
816
      libcnotify_printf(
817
       "%s: XML:\n%s\n",
818
       function,
819
       (char *) xml_plist_data );
820
    }
821
#endif
822
/* TODO for now determine the XML string length */
823
/* TODO refactor this to a separate function */
824
455
    xml_length = strnlen(
825
455
            (char *) xml_plist_data,
826
455
                  xml_plist_data_size );
827
828
455
    if( libfplist_property_list_initialize(
829
455
         &property_list,
830
455
         error ) != 1 )
831
0
    {
832
0
      libcerror_error_set(
833
0
       error,
834
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
835
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
836
0
       "%s: unable to create property list.",
837
0
       function );
838
839
0
      goto on_error;
840
0
    }
841
455
    if( libfplist_property_list_copy_from_byte_stream(
842
455
         property_list,
843
455
         xml_plist_data,
844
455
         xml_length + 1,
845
455
         error ) != 1 )
846
157
    {
847
157
      libcerror_error_set(
848
157
       error,
849
157
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
850
157
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
851
157
       "%s: unable to copy property list from byte stream.",
852
157
       function );
853
854
157
      goto on_error;
855
157
    }
856
298
    if( libfplist_property_list_get_root_property(
857
298
         property_list,
858
298
         &root_property,
859
298
         error ) != 1 )
860
0
    {
861
0
      libcerror_error_set(
862
0
       error,
863
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
864
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
865
0
       "%s: unable to retrieve root property.",
866
0
       function );
867
868
0
      goto on_error;
869
0
    }
870
298
    if( libfplist_property_get_sub_property_by_utf8_name(
871
298
         root_property,
872
298
         (uint8_t *) "com.apple.corestorage.lvg.uuid",
873
298
         30,
874
298
         &sub_property,
875
298
         error ) != 1 )
876
10
    {
877
10
      libcerror_error_set(
878
10
       error,
879
10
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
880
10
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
881
10
       "%s: unable to retrieve com.apple.corestorage.lvg.uuid sub property.",
882
10
       function );
883
884
10
      goto on_error;
885
10
    }
886
#if defined( HAVE_DEBUG_OUTPUT )
887
    if( libcnotify_verbose != 0 )
888
    {
889
      if( libfplist_property_get_value_string(
890
           sub_property,
891
           &string,
892
           &string_size,
893
           error ) != 1 )
894
      {
895
        libcerror_error_set(
896
         error,
897
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
898
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
899
         "%s: unable to retrieve logical volume group identifier.",
900
         function );
901
902
        goto on_error;
903
      }
904
      libcnotify_printf(
905
       "%s: logical volume group identifier\t: %s\n",
906
       function,
907
       string );
908
909
      memory_free(
910
       string );
911
912
      string = NULL;
913
    }
914
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
915
916
288
    if( libfplist_property_free(
917
288
         &sub_property,
918
288
         error ) != 1 )
919
0
    {
920
0
      libcerror_error_set(
921
0
       error,
922
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
923
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
924
0
       "%s: unable to free com.apple.corestorage.lvg.uuid property.",
925
0
       function );
926
927
0
      goto on_error;
928
0
    }
929
288
    if( libfplist_property_get_sub_property_by_utf8_name(
930
288
         root_property,
931
288
         (uint8_t *) "com.apple.corestorage.lvg.name",
932
288
         30,
933
288
         &sub_property,
934
288
         error ) != 1 )
935
9
    {
936
9
      libcerror_error_set(
937
9
       error,
938
9
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
939
9
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
940
9
       "%s: unable to retrieve com.apple.corestorage.lvg.name sub property.",
941
9
       function );
942
943
9
      goto on_error;
944
9
    }
945
279
    if( libfplist_property_get_value_string(
946
279
         sub_property,
947
279
         &( metadata->volume_group_name ),
948
279
         &( metadata->volume_group_name_size ),
949
279
         error ) != 1 )
950
4
    {
951
4
      libcerror_error_set(
952
4
       error,
953
4
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
954
4
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
955
4
       "%s: unable to retrieve logical volume group name.",
956
4
       function );
957
958
4
      goto on_error;
959
4
    }
960
#if defined( HAVE_DEBUG_OUTPUT )
961
    if( libcnotify_verbose != 0 )
962
    {
963
      libcnotify_printf(
964
       "%s: logical volume group name\t\t: %s\n",
965
       function,
966
       metadata->volume_group_name );
967
    }
968
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
969
970
275
    if( libfplist_property_free(
971
275
         &sub_property,
972
275
         error ) != 1 )
973
0
    {
974
0
      libcerror_error_set(
975
0
       error,
976
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
977
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
978
0
       "%s: unable to free com.apple.corestorage.lvg.uuid property.",
979
0
       function );
980
981
0
      goto on_error;
982
0
    }
983
275
    if( libfplist_property_get_sub_property_by_utf8_name(
984
275
         root_property,
985
275
         (uint8_t *) "com.apple.corestorage.lvg.physicalVolumes",
986
275
         41,
987
275
         &sub_property,
988
275
         error ) != 1 )
989
11
    {
990
11
      libcerror_error_set(
991
11
       error,
992
11
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
993
11
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
994
11
       "%s: unable to retrieve com.apple.corestorage.lvg.physicalVolumes sub property.",
995
11
       function );
996
997
11
      goto on_error;
998
11
    }
999
264
    if( libfplist_property_get_array_number_of_entries(
1000
264
         sub_property,
1001
264
         &number_of_entries,
1002
264
         error ) != 1 )
1003
26
    {
1004
26
      libcerror_error_set(
1005
26
       error,
1006
26
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1007
26
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1008
26
       "%s: unable to retrieve number of physical volumes array entries.",
1009
26
       function );
1010
1011
26
      goto on_error;
1012
26
    }
1013
238
    for( entry_index = 0;
1014
22.2k
         entry_index < number_of_entries;
1015
22.0k
         entry_index++ )
1016
22.2k
    {
1017
22.2k
      if( libfplist_property_get_array_entry_by_index(
1018
22.2k
           sub_property,
1019
22.2k
           entry_index,
1020
22.2k
           &array_entry_property,
1021
22.2k
           error ) != 1 )
1022
0
      {
1023
0
        libcerror_error_set(
1024
0
         error,
1025
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1026
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1027
0
         "%s: unable to retrieve physical volumes array entry: %d.",
1028
0
         function,
1029
0
         entry_index );
1030
1031
0
        goto on_error;
1032
0
      }
1033
#if defined( HAVE_DEBUG_OUTPUT )
1034
      if( libcnotify_verbose != 0 )
1035
      {
1036
        if( libfplist_property_get_value_string(
1037
             array_entry_property,
1038
             &string,
1039
             &string_size,
1040
             error ) != 1 )
1041
        {
1042
          libcerror_error_set(
1043
           error,
1044
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1045
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1046
           "%s: unable to retrieve physical volume: %d identifier.",
1047
           function,
1048
           entry_index );
1049
1050
          goto on_error;
1051
        }
1052
        libcnotify_printf(
1053
         "%s: physical volume: %d identifier\t\t: %s\n",
1054
         function,
1055
         entry_index + 1,
1056
         string );
1057
1058
        memory_free(
1059
         string );
1060
1061
        string = NULL;
1062
      }
1063
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1064
1065
22.2k
      if( libfvde_physical_volume_descriptor_initialize(
1066
22.2k
           &physical_volume_descriptor,
1067
22.2k
           error ) != 1 )
1068
0
      {
1069
0
        libcerror_error_set(
1070
0
         error,
1071
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1072
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1073
0
         "%s: unable to create physical volume: %d descriptor.",
1074
0
         function,
1075
0
         entry_index );
1076
1077
0
        goto on_error;
1078
0
      }
1079
22.2k
      if( libfplist_property_value_uuid_string_copy_to_byte_stream(
1080
22.2k
           array_entry_property,
1081
22.2k
           physical_volume_descriptor->identifier,
1082
22.2k
           16,
1083
22.2k
           error ) != 1 )
1084
234
      {
1085
234
        libcerror_error_set(
1086
234
         error,
1087
234
         LIBCERROR_ERROR_DOMAIN_CONVERSION,
1088
234
         LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1089
234
         "%s: unable to copy physical volume: %d identifier string to byte stream.",
1090
234
         function,
1091
234
         entry_index );
1092
1093
234
        goto on_error;
1094
234
      }
1095
22.0k
      if( libcdata_array_append_entry(
1096
22.0k
           metadata->physical_volume_descriptors,
1097
22.0k
           &physical_volume_descriptor_index,
1098
22.0k
           (intptr_t *) physical_volume_descriptor,
1099
22.0k
           error ) != 1 )
1100
0
      {
1101
0
        libcerror_error_set(
1102
0
         error,
1103
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1104
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1105
0
         "%s: unable to append physical volume: %d descriptor to array.",
1106
0
         function,
1107
0
         entry_index );
1108
1109
0
        goto on_error;
1110
0
      }
1111
22.0k
      physical_volume_descriptor = NULL;
1112
1113
22.0k
      if( libfplist_property_free(
1114
22.0k
           &array_entry_property,
1115
22.0k
           error ) != 1 )
1116
0
      {
1117
0
        libcerror_error_set(
1118
0
         error,
1119
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1120
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1121
0
         "%s: unable to free physical volumes array entry: %d.",
1122
0
         function,
1123
0
         entry_index );
1124
1125
0
        goto on_error;
1126
0
      }
1127
22.0k
    }
1128
4
    if( libfplist_property_free(
1129
4
         &sub_property,
1130
4
         error ) != 1 )
1131
0
    {
1132
0
      libcerror_error_set(
1133
0
       error,
1134
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1135
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1136
0
       "%s: unable to free com.apple.corestorage.lvg.physicalVolumes property.",
1137
0
       function );
1138
1139
0
      goto on_error;
1140
0
    }
1141
4
    if( libfplist_property_free(
1142
4
         &root_property,
1143
4
         error ) != 1 )
1144
0
    {
1145
0
      libcerror_error_set(
1146
0
       error,
1147
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1148
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1149
0
       "%s: unable to free root property.",
1150
0
       function );
1151
1152
0
      goto on_error;
1153
0
    }
1154
4
    if( libfplist_property_list_free(
1155
4
         &property_list,
1156
4
         error ) != 1 )
1157
0
    {
1158
0
      libcerror_error_set(
1159
0
       error,
1160
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1161
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1162
0
       "%s: unable to free property list.",
1163
0
       function );
1164
1165
0
      goto on_error;
1166
0
    }
1167
4
  }
1168
#if defined( HAVE_DEBUG_OUTPUT )
1169
  if( libcnotify_verbose != 0 )
1170
  {
1171
    libcnotify_printf(
1172
     "\n" );
1173
  }
1174
#endif
1175
61
  return( 1 );
1176
1177
451
on_error:
1178
#if defined( HAVE_DEBUG_OUTPUT )
1179
  if( string != NULL )
1180
  {
1181
    memory_free(
1182
     string );
1183
  }
1184
#endif
1185
451
  if( physical_volume_descriptor != NULL )
1186
234
  {
1187
234
    libfvde_physical_volume_descriptor_free(
1188
234
     &physical_volume_descriptor,
1189
234
     NULL );
1190
234
  }
1191
451
  if( array_entry_property != NULL )
1192
234
  {
1193
234
    libfplist_property_free(
1194
234
     &array_entry_property,
1195
234
     NULL );
1196
234
  }
1197
451
  if( sub_property != NULL )
1198
264
  {
1199
264
    libfplist_property_free(
1200
264
     &sub_property,
1201
264
     NULL );
1202
264
  }
1203
451
  if( root_property != NULL )
1204
294
  {
1205
294
    libfplist_property_free(
1206
294
     &root_property,
1207
294
     NULL );
1208
294
  }
1209
451
  if( property_list != NULL )
1210
451
  {
1211
451
    libfplist_property_list_free(
1212
451
     &property_list,
1213
451
     NULL );
1214
451
  }
1215
451
  if( metadata->volume_group_name != NULL )
1216
271
  {
1217
271
    memory_free(
1218
271
     metadata->volume_group_name );
1219
1220
271
    metadata->volume_group_name = NULL;
1221
271
  }
1222
451
  metadata->volume_group_name_size = 0;
1223
1224
451
  return( -1 );
1225
512
}
1226
1227
/* Reads the metadata
1228
 * Returns 1 if successful or -1 on error
1229
 */
1230
int libfvde_metadata_read_file_io_handle(
1231
     libfvde_metadata_t *metadata,
1232
     libfvde_io_handle_t *io_handle,
1233
     libbfio_handle_t *file_io_handle,
1234
     off64_t file_offset,
1235
     libcerror_error_t **error )
1236
1.17k
{
1237
1.17k
  libfvde_metadata_block_t *metadata_block = NULL;
1238
1.17k
  uint8_t *metadata_block_data             = NULL;
1239
1.17k
  static char *function                    = "libfvde_metadata_read_file_io_handle";
1240
1.17k
  ssize_t read_count                       = 0;
1241
1242
1.17k
  if( metadata == NULL )
1243
0
  {
1244
0
    libcerror_error_set(
1245
0
     error,
1246
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1247
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1248
0
     "%s: invalid metadata.",
1249
0
     function );
1250
1251
0
    return( -1 );
1252
0
  }
1253
1.17k
  if( io_handle == NULL )
1254
0
  {
1255
0
    libcerror_error_set(
1256
0
     error,
1257
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1258
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1259
0
     "%s: invalid IO handle.",
1260
0
     function );
1261
1262
0
    return( -1 );
1263
0
  }
1264
1.17k
  if( io_handle->block_size == 0 )
1265
0
  {
1266
0
    libcerror_error_set(
1267
0
     error,
1268
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1269
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1270
0
     "%s: invalid IO handle - missing block size.",
1271
0
     function );
1272
1273
0
    return( -1 );
1274
0
  }
1275
1.17k
  if( ( io_handle->metadata_size < 8192 )
1276
1.17k
   || ( io_handle->metadata_size > (uint32_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
1277
32
  {
1278
32
    libcerror_error_set(
1279
32
     error,
1280
32
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1281
32
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1282
32
     "%s: invalid IO handle - metadata size value out of bounds.",
1283
32
     function );
1284
1285
32
    return( -1 );
1286
32
  }
1287
1.14k
  metadata_block_data = (uint8_t *) memory_allocate(
1288
1.14k
                                     sizeof( uint8_t ) * (size_t) io_handle->metadata_size );
1289
1290
1.14k
  if( metadata_block_data == NULL )
1291
0
  {
1292
0
    libcerror_error_set(
1293
0
     error,
1294
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1295
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1296
0
     "%s: unable to create metadata block data.",
1297
0
     function );
1298
1299
0
    goto on_error;
1300
0
  }
1301
#if defined( HAVE_DEBUG_OUTPUT )
1302
  if( libcnotify_verbose != 0 )
1303
  {
1304
    libcnotify_printf(
1305
     "%s: reading metadata at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
1306
     function,
1307
     file_offset,
1308
     file_offset );
1309
  }
1310
#endif
1311
1.14k
  read_count = libbfio_handle_read_buffer_at_offset(
1312
1.14k
                file_io_handle,
1313
1.14k
                metadata_block_data,
1314
1.14k
                (size_t) io_handle->metadata_size,
1315
1.14k
                file_offset,
1316
1.14k
                error );
1317
1318
1.14k
  if( read_count != (ssize_t) io_handle->metadata_size )
1319
220
  {
1320
220
    libcerror_error_set(
1321
220
     error,
1322
220
     LIBCERROR_ERROR_DOMAIN_IO,
1323
220
     LIBCERROR_IO_ERROR_READ_FAILED,
1324
220
     "%s: unable to read metadata block data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1325
220
     function,
1326
220
     file_offset,
1327
220
     file_offset );
1328
1329
220
    goto on_error;
1330
220
  }
1331
/* TODO move data allocation into metadata_block? */
1332
924
  if( libfvde_metadata_block_initialize(
1333
924
       &metadata_block,
1334
924
       error ) != 1 )
1335
0
  {
1336
0
    libcerror_error_set(
1337
0
     error,
1338
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1339
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1340
0
     "%s: unable to create metadata block.",
1341
0
     function );
1342
1343
0
    goto on_error;
1344
0
  }
1345
924
  if( libfvde_metadata_block_read_data(
1346
924
       metadata_block,
1347
924
       metadata_block_data,
1348
924
       (size_t) io_handle->metadata_size,
1349
924
       error ) != 1 )
1350
195
  {
1351
195
    libcerror_error_set(
1352
195
     error,
1353
195
     LIBCERROR_ERROR_DOMAIN_IO,
1354
195
     LIBCERROR_IO_ERROR_READ_FAILED,
1355
195
     "%s: unable to read metadata block.",
1356
195
     function );
1357
1358
195
    goto on_error;
1359
195
  }
1360
729
  if( metadata_block->type != 0x0011 )
1361
18
  {
1362
18
    libcerror_error_set(
1363
18
     error,
1364
18
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1365
18
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1366
18
     "%s: unsupported metadata block type: 0x%04" PRIx16 ".",
1367
18
     function,
1368
18
     metadata_block->type );
1369
1370
18
    goto on_error;
1371
18
  }
1372
#if defined( HAVE_DEBUG_OUTPUT )
1373
  if( libcnotify_verbose != 0 )
1374
  {
1375
    if( metadata_block->serial_number != io_handle->serial_number )
1376
    {
1377
      libcnotify_printf(
1378
       "%s: mismatch in serial number ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n",
1379
       function,
1380
       metadata_block->serial_number,
1381
       io_handle->serial_number );
1382
    }
1383
  }
1384
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1385
1386
711
  if( libfvde_metadata_read_type_0x0011(
1387
711
       metadata,
1388
711
       io_handle,
1389
711
       metadata_block->transaction_identifier,
1390
711
       metadata_block->data,
1391
711
       metadata_block->data_size,
1392
711
       error ) != 1 )
1393
650
  {
1394
650
    libcerror_error_set(
1395
650
     error,
1396
650
     LIBCERROR_ERROR_DOMAIN_IO,
1397
650
     LIBCERROR_IO_ERROR_READ_FAILED,
1398
650
     "%s: unable to read metadata block type 0x%04" PRIx16 ".",
1399
650
     function,
1400
650
     metadata_block->type );
1401
1402
650
    goto on_error;
1403
650
  }
1404
61
  if( libfvde_metadata_block_free(
1405
61
       &metadata_block,
1406
61
       error ) != 1 )
1407
0
  {
1408
0
    libcerror_error_set(
1409
0
     error,
1410
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1411
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1412
0
     "%s: unable to free metadata block.",
1413
0
     function );
1414
1415
0
    goto on_error;
1416
0
  }
1417
61
  memory_free(
1418
61
   metadata_block_data );
1419
1420
61
  metadata_block_data = NULL;
1421
1422
61
  return( 1 );
1423
1424
1.08k
on_error:
1425
1.08k
  if( metadata_block != NULL )
1426
863
  {
1427
863
    libfvde_metadata_block_free(
1428
863
     &metadata_block,
1429
863
     NULL );
1430
863
  }
1431
1.08k
  if( metadata_block_data != NULL )
1432
1.08k
  {
1433
1.08k
    memory_free(
1434
1.08k
     metadata_block_data );
1435
1.08k
  }
1436
1.08k
  return( -1 );
1437
61
}
1438
1439
/* Retrieves the size of the UTF-8 encoded volume group name
1440
 * The returned size includes the end of string character
1441
 * Returns 1 if successful, 0 if not available or -1 on error
1442
 */
1443
int libfvde_metadata_get_utf8_volume_group_name_size(
1444
     libfvde_metadata_t *metadata,
1445
     size_t *utf8_string_size,
1446
     libcerror_error_t **error )
1447
0
{
1448
0
  static char *function = "libfvde_metadata_get_utf8_volume_group_name_size";
1449
1450
0
  if( metadata == NULL )
1451
0
  {
1452
0
    libcerror_error_set(
1453
0
     error,
1454
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1455
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1456
0
     "%s: invalid metadata.",
1457
0
     function );
1458
1459
0
    return( -1 );
1460
0
  }
1461
0
  if( ( metadata->volume_group_name == NULL )
1462
0
   || ( metadata->volume_group_name_size == 0 ) )
1463
0
  {
1464
0
    return( 0 );
1465
0
  }
1466
0
  if( libuna_utf8_string_size_from_utf8_stream(
1467
0
       metadata->volume_group_name,
1468
0
       metadata->volume_group_name_size,
1469
0
       utf8_string_size,
1470
0
       error ) != 1 )
1471
0
  {
1472
0
    libcerror_error_set(
1473
0
     error,
1474
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1475
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1476
0
     "%s: unable to retrieve UTF-8 string size.",
1477
0
     function );
1478
1479
0
    return( -1 );
1480
0
  }
1481
0
  return( 1 );
1482
0
}
1483
1484
/* Retrieves the UTF-8 encoded volume group name
1485
 * The size should include the end of string character
1486
 * Returns 1 if successful, 0 if not available or -1 on error
1487
 */
1488
int libfvde_metadata_get_utf8_volume_group_name(
1489
     libfvde_metadata_t *metadata,
1490
     uint8_t *utf8_string,
1491
     size_t utf8_string_size,
1492
     libcerror_error_t **error )
1493
0
{
1494
0
  static char *function = "libfvde_metadata_get_utf8_volume_group_name";
1495
1496
0
  if( metadata == NULL )
1497
0
  {
1498
0
    libcerror_error_set(
1499
0
     error,
1500
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1501
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1502
0
     "%s: invalid metadata.",
1503
0
     function );
1504
1505
0
    return( -1 );
1506
0
  }
1507
0
  if( ( metadata->volume_group_name == NULL )
1508
0
   || ( metadata->volume_group_name_size == 0 ) )
1509
0
  {
1510
0
    return( 0 );
1511
0
  }
1512
0
  if( libuna_utf8_string_copy_from_utf8_stream(
1513
0
       utf8_string,
1514
0
       utf8_string_size,
1515
0
       metadata->volume_group_name,
1516
0
       metadata->volume_group_name_size,
1517
0
       error ) != 1 )
1518
0
  {
1519
0
    libcerror_error_set(
1520
0
     error,
1521
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1522
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1523
0
     "%s: unable to retrieve UTF-8 string.",
1524
0
     function );
1525
1526
0
    return( -1 );
1527
0
  }
1528
0
  return( 1 );
1529
0
}
1530
1531
/* Retrieves the size of the UTF-16 encoded volume group name
1532
 * The returned size includes the end of string character
1533
 * Returns 1 if successful, 0 if not available or -1 on error
1534
 */
1535
int libfvde_metadata_get_utf16_volume_group_name_size(
1536
     libfvde_metadata_t *metadata,
1537
     size_t *utf16_string_size,
1538
     libcerror_error_t **error )
1539
0
{
1540
0
  static char *function = "libfvde_metadata_get_utf16_volume_group_name_size";
1541
1542
0
  if( metadata == NULL )
1543
0
  {
1544
0
    libcerror_error_set(
1545
0
     error,
1546
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1547
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1548
0
     "%s: invalid metadata.",
1549
0
     function );
1550
1551
0
    return( -1 );
1552
0
  }
1553
0
  if( ( metadata->volume_group_name == NULL )
1554
0
   || ( metadata->volume_group_name_size == 0 ) )
1555
0
  {
1556
0
    return( 0 );
1557
0
  }
1558
0
  if( libuna_utf16_string_size_from_utf8_stream(
1559
0
       metadata->volume_group_name,
1560
0
       metadata->volume_group_name_size,
1561
0
       utf16_string_size,
1562
0
       error ) != 1 )
1563
0
  {
1564
0
    libcerror_error_set(
1565
0
     error,
1566
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1567
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1568
0
     "%s: unable to retrieve UTF-16 string size.",
1569
0
     function );
1570
1571
0
    return( -1 );
1572
0
  }
1573
0
  return( 1 );
1574
0
}
1575
1576
/* Retrieves the UTF-16 encoded volume group name
1577
 * The size should include the end of string character
1578
 * Returns 1 if successful, 0 if not available or -1 on error
1579
 */
1580
int libfvde_metadata_get_utf16_volume_group_name(
1581
     libfvde_metadata_t *metadata,
1582
     uint16_t *utf16_string,
1583
     size_t utf16_string_size,
1584
     libcerror_error_t **error )
1585
0
{
1586
0
  static char *function = "libfvde_metadata_get_utf16_volume_group_name";
1587
1588
0
  if( metadata == NULL )
1589
0
  {
1590
0
    libcerror_error_set(
1591
0
     error,
1592
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1593
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1594
0
     "%s: invalid metadata.",
1595
0
     function );
1596
1597
0
    return( -1 );
1598
0
  }
1599
0
  if( ( metadata->volume_group_name == NULL )
1600
0
   || ( metadata->volume_group_name_size == 0 ) )
1601
0
  {
1602
0
    return( 0 );
1603
0
  }
1604
0
  if( libuna_utf16_string_copy_from_utf8_stream(
1605
0
       utf16_string,
1606
0
       utf16_string_size,
1607
0
       metadata->volume_group_name,
1608
0
       metadata->volume_group_name_size,
1609
0
       error ) != 1 )
1610
0
  {
1611
0
    libcerror_error_set(
1612
0
     error,
1613
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1614
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1615
0
     "%s: unable to retrieve UTF-16 string.",
1616
0
     function );
1617
1618
0
    return( -1 );
1619
0
  }
1620
0
  return( 1 );
1621
0
}
1622
1623
/* Retrieves the number of physical volume descriptors
1624
 * Returns 1 if successful or -1 on error
1625
 */
1626
int libfvde_metadata_get_number_of_physical_volume_descriptors(
1627
     libfvde_metadata_t *metadata,
1628
     int *number_of_physical_volume_descriptors,
1629
     libcerror_error_t **error )
1630
0
{
1631
0
  static char *function = "libfvde_metadata_get_number_of_physical_volume_descriptors";
1632
1633
0
  if( metadata == NULL )
1634
0
  {
1635
0
    libcerror_error_set(
1636
0
     error,
1637
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1638
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1639
0
     "%s: invalid metadata.",
1640
0
     function );
1641
1642
0
    return( -1 );
1643
0
  }
1644
0
  if( libcdata_array_get_number_of_entries(
1645
0
       metadata->physical_volume_descriptors,
1646
0
       number_of_physical_volume_descriptors,
1647
0
       error ) != 1 )
1648
0
  {
1649
0
    libcerror_error_set(
1650
0
     error,
1651
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1652
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1653
0
     "%s: unable to retrieve number of physical volume descriptors.",
1654
0
     function );
1655
1656
0
    return( -1 );
1657
0
  }
1658
0
  return( 1 );
1659
0
}
1660
1661
/* Retrieves a specific physical volume descriptor
1662
 * Returns 1 if successful or -1 on error
1663
 */
1664
int libfvde_metadata_get_physical_volume_descriptor_by_index(
1665
     libfvde_metadata_t *metadata,
1666
     int physical_volume_descriptor_index,
1667
     libfvde_physical_volume_descriptor_t **physical_volume_descriptor,
1668
     libcerror_error_t **error )
1669
0
{
1670
0
  static char *function = "libfvde_metadata_get_physical_volume_descriptor_by_index";
1671
1672
0
  if( metadata == NULL )
1673
0
  {
1674
0
    libcerror_error_set(
1675
0
     error,
1676
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1677
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1678
0
     "%s: invalid metadata.",
1679
0
     function );
1680
1681
0
    return( -1 );
1682
0
  }
1683
0
  if( libcdata_array_get_entry_by_index(
1684
0
       metadata->physical_volume_descriptors,
1685
0
       physical_volume_descriptor_index,
1686
0
       (intptr_t **) physical_volume_descriptor,
1687
0
       error ) != 1 )
1688
0
  {
1689
0
    libcerror_error_set(
1690
0
     error,
1691
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1692
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1693
0
     "%s: unable to retrieve physical volume descriptor: %d.",
1694
0
     function,
1695
0
     physical_volume_descriptor_index );
1696
1697
0
    return( -1 );
1698
0
  }
1699
0
  return( 1 );
1700
0
}
1701