Coverage Report

Created: 2024-10-02 06:58

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