Coverage Report

Created: 2025-09-05 06:58

/src/libbde/libbde/libbde_metadata_header.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Metadata 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_libcerror.h"
29
#include "libbde_libcnotify.h"
30
#include "libbde_libfdatetime.h"
31
#include "libbde_libfguid.h"
32
#include "libbde_metadata_header.h"
33
34
#include "bde_metadata.h"
35
36
/* Creates a metadata header
37
 * Make sure the value metadata header is referencing, is set to NULL
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libbde_metadata_header_initialize(
41
     libbde_metadata_header_t **metadata_header,
42
     libcerror_error_t **error )
43
3.76k
{
44
3.76k
  static char *function = "libbde_metadata_header_initialize";
45
46
3.76k
  if( metadata_header == NULL )
47
0
  {
48
0
    libcerror_error_set(
49
0
     error,
50
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52
0
     "%s: invalid metadata header.",
53
0
     function );
54
55
0
    return( -1 );
56
0
  }
57
3.76k
  if( *metadata_header != NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
62
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
63
0
     "%s: invalid metadata header value already set.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
3.76k
  *metadata_header = memory_allocate_structure(
69
3.76k
                            libbde_metadata_header_t );
70
71
3.76k
  if( *metadata_header == NULL )
72
0
  {
73
0
    libcerror_error_set(
74
0
     error,
75
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
76
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
77
0
     "%s: unable to create metadata header.",
78
0
     function );
79
80
0
    goto on_error;
81
0
  }
82
3.76k
  if( memory_set(
83
3.76k
       *metadata_header,
84
3.76k
       0,
85
3.76k
       sizeof( libbde_metadata_header_t ) ) == NULL )
86
0
  {
87
0
    libcerror_error_set(
88
0
     error,
89
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
90
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
91
0
     "%s: unable to clear metadata header.",
92
0
     function );
93
94
0
    goto on_error;
95
0
  }
96
3.76k
  return( 1 );
97
98
0
on_error:
99
0
  if( *metadata_header != NULL )
100
0
  {
101
0
    memory_free(
102
0
     *metadata_header );
103
104
0
    *metadata_header = NULL;
105
0
  }
106
0
  return( -1 );
107
3.76k
}
108
109
/* Frees a metadata header
110
 * Returns 1 if successful or -1 on error
111
 */
112
int libbde_metadata_header_free(
113
     libbde_metadata_header_t **metadata_header,
114
     libcerror_error_t **error )
115
3.76k
{
116
3.76k
  static char *function = "libbde_metadata_header_free";
117
118
3.76k
  if( metadata_header == NULL )
119
0
  {
120
0
    libcerror_error_set(
121
0
     error,
122
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
123
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
124
0
     "%s: invalid metadata header.",
125
0
     function );
126
127
0
    return( -1 );
128
0
  }
129
3.76k
  if( *metadata_header != NULL )
130
3.76k
  {
131
3.76k
    memory_free(
132
3.76k
     *metadata_header );
133
134
3.76k
    *metadata_header = NULL;
135
3.76k
  }
136
3.76k
  return( 1 );
137
3.76k
}
138
139
/* Reads a metadata header
140
 * Returns 1 if successful or -1 on error
141
 */
142
int libbde_metadata_header_read_data(
143
     libbde_metadata_header_t *metadata_header,
144
     const uint8_t *data,
145
     size_t data_size,
146
     libcerror_error_t **error )
147
3.75k
{
148
3.75k
  static char *function           = "libbde_metadata_header_read_data";
149
3.75k
  uint32_t format_version         = 0;
150
3.75k
  uint32_t header_size            = 0;
151
3.75k
  uint32_t metadata_size_copy     = 0;
152
3.75k
  uint16_t encryption_method_copy = 0;
153
154
#if defined( HAVE_DEBUG_OUTPUT )
155
  uint32_t value_32bit            = 0;
156
#endif
157
158
3.75k
  if( metadata_header == NULL )
159
0
  {
160
0
    libcerror_error_set(
161
0
     error,
162
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
163
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
164
0
     "%s: invalid metadata header.",
165
0
     function );
166
167
0
    return( -1 );
168
0
  }
169
3.75k
  if( data == NULL )
170
0
  {
171
0
    libcerror_error_set(
172
0
     error,
173
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
174
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
175
0
     "%s: invalid data.",
176
0
     function );
177
178
0
    return( -1 );
179
0
  }
180
3.75k
  if( ( data_size < sizeof( bde_metadata_header_v1_t ) )
181
3.75k
   || ( data_size > (size_t) SSIZE_MAX ) )
182
0
  {
183
0
    libcerror_error_set(
184
0
     error,
185
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
186
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
187
0
     "%s: invalid data size value out of bounds.",
188
0
     function );
189
190
0
    return( -1 );
191
0
  }
192
#if defined( HAVE_DEBUG_OUTPUT )
193
  if( libcnotify_verbose != 0 )
194
  {
195
    libcnotify_printf(
196
     "%s: FVE metadata header:\n",
197
     function );
198
    libcnotify_print_data(
199
     data,
200
     sizeof( bde_metadata_header_v1_t ),
201
     0 );
202
  }
203
#endif
204
3.75k
  byte_stream_copy_to_uint32_little_endian(
205
3.75k
   ( (bde_metadata_header_v1_t *) data )->metadata_size,
206
3.75k
   metadata_header->metadata_size );
207
208
3.75k
  byte_stream_copy_to_uint32_little_endian(
209
3.75k
   ( (bde_metadata_header_v1_t *) data )->version,
210
3.75k
   format_version );
211
212
3.75k
  byte_stream_copy_to_uint32_little_endian(
213
3.75k
   ( (bde_metadata_header_v1_t *) data )->metadata_header_size,
214
3.75k
   header_size );
215
216
3.75k
  byte_stream_copy_to_uint32_little_endian(
217
3.75k
   ( (bde_metadata_header_v1_t *) data )->metadata_size_copy,
218
3.75k
   metadata_size_copy );
219
220
3.75k
  if( memory_copy(
221
3.75k
       metadata_header->volume_identifier,
222
3.75k
       ( (bde_metadata_header_v1_t *) data )->volume_identifier,
223
3.75k
       16 ) == NULL )
224
0
  {
225
0
    libcerror_error_set(
226
0
     error,
227
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
228
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
229
0
     "%s: unable to copy volume identifier.",
230
0
     function );
231
232
0
    return( -1 );
233
0
  }
234
3.75k
  byte_stream_copy_to_uint16_little_endian(
235
3.75k
   ( (bde_metadata_header_v1_t *) data )->encryption_method,
236
3.75k
   metadata_header->encryption_method );
237
238
3.75k
  byte_stream_copy_to_uint16_little_endian(
239
3.75k
   ( (bde_metadata_header_v1_t *) data )->encryption_method_copy,
240
3.75k
   encryption_method_copy );
241
242
3.75k
  byte_stream_copy_to_uint64_little_endian(
243
3.75k
   ( (bde_metadata_header_v1_t *) data )->creation_time,
244
3.75k
   metadata_header->creation_time );
245
246
#if defined( HAVE_DEBUG_OUTPUT )
247
  if( libcnotify_verbose != 0 )
248
  {
249
    libcnotify_printf(
250
     "%s: metadata size\t\t\t\t: %" PRIu32 "\n",
251
     function,
252
     metadata_header->metadata_size );
253
254
    libcnotify_printf(
255
     "%s: format version\t\t\t: %" PRIu32 "\n",
256
     function,
257
     format_version );
258
259
    libcnotify_printf(
260
     "%s: header size\t\t\t\t: %" PRIu32 "\n",
261
     function,
262
     header_size );
263
264
    libcnotify_printf(
265
     "%s: metadata size copy\t\t\t: %" PRIu32 "\n",
266
     function,
267
     metadata_size_copy );
268
269
    if( libbde_debug_print_guid_value(
270
         function,
271
         "volume identifier\t\t\t",
272
         metadata_header->volume_identifier,
273
         16,
274
         LIBFGUID_ENDIAN_LITTLE,
275
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
276
         error ) != 1 )
277
    {
278
      libcerror_error_set(
279
       error,
280
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
281
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
282
       "%s: unable to print GUID value.",
283
       function );
284
285
      return( -1 );
286
    }
287
    byte_stream_copy_to_uint32_little_endian(
288
     ( (bde_metadata_header_v1_t *) data )->next_nonce_counter,
289
     value_32bit );
290
    libcnotify_printf(
291
     "%s: next nonce counter\t\t\t: 0x%08" PRIx32 "\n",
292
     function,
293
     value_32bit );
294
295
    libcnotify_printf(
296
     "%s: encryption method\t\t\t: 0x%08" PRIx32 " (%s)\n",
297
     function,
298
     metadata_header->encryption_method,
299
     libbde_debug_print_encryption_method(
300
      metadata_header->encryption_method ) );
301
302
    libcnotify_printf(
303
     "%s: encryption method copy\t\t: 0x%08" PRIx32 " (%s)\n",
304
     function,
305
     encryption_method_copy,
306
     libbde_debug_print_encryption_method(
307
      encryption_method_copy ) );
308
309
    if( libbde_debug_print_filetime_value(
310
         function,
311
         "creation time\t\t\t\t",
312
         ( (bde_metadata_header_v1_t *) data )->creation_time,
313
         8,
314
         LIBFDATETIME_ENDIAN_LITTLE,
315
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
316
         error ) != 1 )
317
    {
318
      libcerror_error_set(
319
       error,
320
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
321
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
322
       "%s: unable to print FILETIME value.",
323
       function );
324
325
      return( -1 );
326
    }
327
    libcnotify_printf(
328
     "\n" );
329
  }
330
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
331
332
3.75k
  if( format_version != 1 )
333
36
  {
334
36
    libcerror_error_set(
335
36
     error,
336
36
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
337
36
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
338
36
     "%s: unsupported format version.",
339
36
     function );
340
341
36
    return( -1 );
342
36
  }
343
3.71k
  if( header_size != sizeof( bde_metadata_header_v1_t ) )
344
32
  {
345
32
    libcerror_error_set(
346
32
     error,
347
32
     LIBCERROR_ERROR_DOMAIN_INPUT,
348
32
     LIBCERROR_INPUT_ERROR_VALUE_MISMATCH,
349
32
     "%s: value mismatch for header size.",
350
32
     function );
351
352
32
    return( -1 );
353
32
  }
354
3.68k
  if( metadata_header->metadata_size != metadata_size_copy )
355
40
  {
356
40
    libcerror_error_set(
357
40
     error,
358
40
     LIBCERROR_ERROR_DOMAIN_INPUT,
359
40
     LIBCERROR_INPUT_ERROR_VALUE_MISMATCH,
360
40
     "%s: value mismatch for metadata size and copy.",
361
40
     function );
362
363
40
    return( -1 );
364
40
  }
365
3.64k
  return( 1 );
366
3.68k
}
367
368
/* Reads a metadata header
369
 * Returns 1 if successful or -1 on error
370
 */
371
int libbde_metadata_header_read_file_io_handle(
372
     libbde_metadata_header_t *metadata_header,
373
     libbfio_handle_t *file_io_handle,
374
     off64_t file_offset,
375
     libcerror_error_t **error )
376
3.76k
{
377
3.76k
  uint8_t metadata_header_data[ sizeof( bde_metadata_header_v1_t ) ];
378
379
3.76k
  static char *function = "libbde_metadata_header_read_file_io_handle";
380
3.76k
  ssize_t read_count    = 0;
381
382
3.76k
  if( metadata_header == NULL )
383
0
  {
384
0
    libcerror_error_set(
385
0
     error,
386
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
387
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
388
0
     "%s: invalid metadata header.",
389
0
     function );
390
391
0
    return( -1 );
392
0
  }
393
3.76k
  read_count = libbfio_handle_read_buffer_at_offset(
394
3.76k
                file_io_handle,
395
3.76k
                metadata_header_data,
396
3.76k
                sizeof( bde_metadata_header_v1_t ),
397
3.76k
                file_offset,
398
3.76k
                error );
399
400
3.76k
  if( read_count != (ssize_t) sizeof( bde_metadata_header_v1_t ) )
401
11
  {
402
11
    libcerror_error_set(
403
11
     error,
404
11
     LIBCERROR_ERROR_DOMAIN_IO,
405
11
     LIBCERROR_IO_ERROR_READ_FAILED,
406
11
     "%s: unable to read FVE metadata header data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
407
11
     function,
408
11
     file_offset,
409
11
     file_offset );
410
411
11
    return( -1 );
412
11
  }
413
3.75k
  if( libbde_metadata_header_read_data(
414
3.75k
       metadata_header,
415
3.75k
       metadata_header_data,
416
3.75k
       sizeof( bde_metadata_header_v1_t ),
417
3.75k
       error ) != 1 )
418
108
  {
419
108
    libcerror_error_set(
420
108
     error,
421
108
     LIBCERROR_ERROR_DOMAIN_IO,
422
108
     LIBCERROR_IO_ERROR_READ_FAILED,
423
108
     "%s: unable to read FVE metadata header.",
424
108
     function );
425
426
108
    return( -1 );
427
108
  }
428
3.64k
  return( 1 );
429
3.75k
}
430