Coverage Report

Created: 2026-10-22 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libbde/libbde/libbde_external_key.c
Line
Count
Source
1
/*
2
 * External Key metadata entry functions
3
 *
4
 * Copyright (C) 2011-2026, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <memory.h>
25
#include <system_string.h>
26
#include <types.h>
27
28
#include "libbde_debug.h"
29
#include "libbde_definitions.h"
30
#include "libbde_external_key.h"
31
#include "libbde_io_handle.h"
32
#include "libbde_key.h"
33
#include "libbde_libcdata.h"
34
#include "libbde_libcerror.h"
35
#include "libbde_libcnotify.h"
36
#include "libbde_libfdatetime.h"
37
#include "libbde_libfguid.h"
38
#include "libbde_metadata_entry.h"
39
40
#include "bde_metadata.h"
41
42
/* Creates an external key
43
 * Make sure the value external key is referencing, is set to NULL
44
 * Returns 1 if successful or -1 on error
45
 */
46
int libbde_external_key_initialize(
47
     libbde_external_key_t **external_key,
48
     libcerror_error_t **error )
49
547
{
50
547
  static char *function = "libbde_external_key_initialize";
51
52
547
  if( external_key == NULL )
53
0
  {
54
0
    libcerror_error_set(
55
0
     error,
56
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
57
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
58
0
     "%s: invalid external key.",
59
0
     function );
60
61
0
    return( -1 );
62
0
  }
63
547
  if( *external_key != NULL )
64
0
  {
65
0
    libcerror_error_set(
66
0
     error,
67
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
68
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
69
0
     "%s: invalid external key value already set.",
70
0
     function );
71
72
0
    return( -1 );
73
0
  }
74
547
  *external_key = memory_allocate_structure(
75
547
                   libbde_external_key_t );
76
77
547
  if( *external_key == NULL )
78
0
  {
79
0
    libcerror_error_set(
80
0
     error,
81
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
82
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
83
0
     "%s: unable to create external key.",
84
0
     function );
85
86
0
    goto on_error;
87
0
  }
88
547
  if( memory_set(
89
547
       *external_key,
90
547
       0,
91
547
       sizeof( libbde_external_key_t ) ) == NULL )
92
0
  {
93
0
    libcerror_error_set(
94
0
     error,
95
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
96
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
97
0
     "%s: unable to clear external key.",
98
0
     function );
99
100
0
    goto on_error;
101
0
  }
102
547
  if( libcdata_array_initialize(
103
547
       &( ( *external_key )->entries_array ),
104
547
       0,
105
547
       error ) != 1 )
106
0
  {
107
0
    libcerror_error_set(
108
0
     error,
109
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
110
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
111
0
     "%s: unable to create entries array.",
112
0
     function );
113
114
0
    goto on_error;
115
0
  }
116
547
  return( 1 );
117
118
0
on_error:
119
0
  if( *external_key != NULL )
120
0
  {
121
0
    memory_free(
122
0
     *external_key );
123
124
0
    *external_key = NULL;
125
0
  }
126
0
  return( -1 );
127
547
}
128
129
/* Frees an external key
130
 * Returns 1 if successful or -1 on error
131
 */
132
int libbde_external_key_free(
133
     libbde_external_key_t **external_key,
134
     libcerror_error_t **error )
135
547
{
136
547
  static char *function = "libbde_external_key_free";
137
547
  int result            = 1;
138
139
547
  if( external_key == NULL )
140
0
  {
141
0
    libcerror_error_set(
142
0
     error,
143
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
144
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
145
0
     "%s: invalid external key.",
146
0
     function );
147
148
0
    return( -1 );
149
0
  }
150
547
  if( *external_key != NULL )
151
547
  {
152
547
    if( ( *external_key )->key != NULL )
153
187
    {
154
187
      if( libbde_key_free(
155
187
           &( ( *external_key )->key ),
156
187
           error ) != 1 )
157
0
      {
158
0
        libcerror_error_set(
159
0
         error,
160
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
161
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
162
0
         "%s: unable to free key.",
163
0
         function );
164
165
0
        result = -1;
166
0
      }
167
187
    }
168
547
    if( libcdata_array_free(
169
547
         &( ( *external_key )->entries_array ),
170
547
         (int(*)(intptr_t **, libcerror_error_t **)) &libbde_metadata_entry_free,
171
547
         error ) != 1 )
172
0
    {
173
0
      libcerror_error_set(
174
0
       error,
175
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
176
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
177
0
       "%s: unable to free entries array.",
178
0
       function );
179
180
0
      result = -1;
181
0
    }
182
547
    memory_free(
183
547
     *external_key );
184
185
547
    *external_key = NULL;
186
547
  }
187
547
  return( result );
188
547
}
189
190
/* Reads a external key from the metadata entry
191
 * Returns 1 if successful or -1 on error
192
 */
193
int libbde_external_key_read(
194
     libbde_external_key_t *external_key,
195
     libbde_metadata_entry_t *metadata_entry,
196
     libcerror_error_t **error )
197
547
{
198
547
  libbde_key_t *key                                = NULL;
199
547
  libbde_metadata_entry_t *property_metadata_entry = NULL;
200
547
  uint8_t *value_data                              = NULL;
201
547
  static char *function                            = "libbde_external_key_read";
202
547
  size_t value_data_size                           = 0;
203
547
  ssize_t read_count                               = 0;
204
547
  int property_metadata_entry_index                = 0;
205
206
547
  if( external_key == NULL )
207
0
  {
208
0
    libcerror_error_set(
209
0
     error,
210
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
211
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
212
0
     "%s: invalid external key.",
213
0
     function );
214
215
0
    return( -1 );
216
0
  }
217
547
  if( metadata_entry == NULL )
218
0
  {
219
0
    libcerror_error_set(
220
0
     error,
221
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
222
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
223
0
     "%s: invalid metadata entry.",
224
0
     function );
225
226
0
    return( -1 );
227
0
  }
228
547
  if( metadata_entry->value_type != LIBBDE_VALUE_TYPE_EXTERNAL_KEY )
229
17
  {
230
17
    libcerror_error_set(
231
17
     error,
232
17
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
233
17
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
234
17
     "%s: invalid metadata entry - unsupported value type: 0x%04" PRIx16 ".",
235
17
     function,
236
17
     metadata_entry->value_type );
237
238
17
    return( -1 );
239
17
  }
240
530
  value_data      = metadata_entry->value_data;
241
530
  value_data_size = metadata_entry->value_data_size;
242
243
530
  if( value_data_size < sizeof( bde_metadata_entry_external_key_header_t ) )
244
5
  {
245
5
    libcerror_error_set(
246
5
     error,
247
5
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
248
5
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
249
5
     "%s: value data size value out of bounds.",
250
5
     function );
251
252
5
    return( -1 );
253
5
  }
254
525
  if( memory_copy(
255
525
       external_key->identifier,
256
525
       ( (bde_metadata_entry_external_key_header_t *) value_data )->identifier,
257
525
       16 ) == NULL )
258
0
  {
259
0
    libcerror_error_set(
260
0
     error,
261
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
262
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
263
0
     "%s: unable to copy volume identifier.",
264
0
     function );
265
266
0
    goto on_error;
267
0
  }
268
#if defined( HAVE_DEBUG_OUTPUT )
269
  if( libcnotify_verbose != 0 )
270
  {
271
    if( libbde_debug_print_guid_value(
272
         function,
273
         "identifier\t\t\t\t\t",
274
         ( (bde_metadata_entry_external_key_header_t *) value_data )->identifier,
275
         16,
276
         LIBFGUID_ENDIAN_LITTLE,
277
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
278
         error ) != 1 )
279
    {
280
      libcerror_error_set(
281
       error,
282
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
283
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
284
       "%s: unable to print GUID value.",
285
       function );
286
287
      goto on_error;
288
    }
289
    if( libbde_debug_print_filetime_value(
290
         function,
291
         "modification time\t\t\t\t",
292
         ( (bde_metadata_entry_external_key_header_t *) value_data )->modification_time,
293
         8,
294
         LIBFDATETIME_ENDIAN_LITTLE,
295
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
296
         error ) != 1 )
297
    {
298
      libcerror_error_set(
299
       error,
300
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
301
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
302
       "%s: unable to print FILETIME value.",
303
       function );
304
305
      goto on_error;
306
    }
307
    libcnotify_printf(
308
     "\n" );
309
  }
310
#endif
311
525
  value_data      += sizeof( bde_metadata_entry_external_key_header_t );
312
525
  value_data_size -= sizeof( bde_metadata_entry_external_key_header_t );
313
314
3.44k
  while( value_data_size >= sizeof( bde_metadata_entry_v1_t ) )
315
3.06k
  {
316
3.06k
    if( memory_compare(
317
3.06k
         value_data,
318
3.06k
         libbde_metadata_entry_empty,
319
3.06k
         sizeof( bde_metadata_entry_v1_t ) ) == 0 )
320
121
    {
321
121
      break;
322
121
    }
323
2.94k
    if( libbde_metadata_entry_initialize(
324
2.94k
         &property_metadata_entry,
325
2.94k
         error ) != 1 )
326
0
    {
327
0
      libcerror_error_set(
328
0
       error,
329
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
330
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
331
0
       "%s: unable to create property metadata entry.",
332
0
       function );
333
334
0
      goto on_error;
335
0
    }
336
2.94k
    read_count = libbde_metadata_entry_read(
337
2.94k
            property_metadata_entry,
338
2.94k
            value_data,
339
2.94k
            value_data_size,
340
2.94k
            error );
341
342
2.94k
    if( read_count == -1 )
343
24
    {
344
24
      libcerror_error_set(
345
24
       error,
346
24
       LIBCERROR_ERROR_DOMAIN_IO,
347
24
       LIBCERROR_IO_ERROR_READ_FAILED,
348
24
       "%s: unable to read property metadata entry.",
349
24
       function );
350
351
24
      goto on_error;
352
24
    }
353
2.92k
    value_data      += read_count;
354
2.92k
    value_data_size -= read_count;
355
356
2.92k
    if( property_metadata_entry->value_type == LIBBDE_VALUE_TYPE_KEY )
357
579
    {
358
579
      if( libbde_key_initialize(
359
579
           &key,
360
579
           error ) != 1 )
361
0
      {
362
0
        libcerror_error_set(
363
0
         error,
364
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
365
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
366
0
         "%s: unable to create key.",
367
0
         function );
368
369
0
        goto on_error;
370
0
      }
371
579
      if( libbde_key_read(
372
579
           key,
373
579
           property_metadata_entry,
374
579
           error ) != 1 )
375
2
      {
376
2
        libcerror_error_set(
377
2
         error,
378
2
         LIBCERROR_ERROR_DOMAIN_IO,
379
2
         LIBCERROR_IO_ERROR_READ_FAILED,
380
2
         "%s: unable to read key metadata entry.",
381
2
         function );
382
383
2
        goto on_error;
384
2
      }
385
577
      if( external_key->key == NULL )
386
187
      {
387
187
        external_key->key = key;
388
389
187
        key = NULL;
390
187
      }
391
577
      if( key != NULL )
392
390
      {
393
390
        if( libbde_key_free(
394
390
             &key,
395
390
             error ) != 1 )
396
0
        {
397
0
          libcerror_error_set(
398
0
           error,
399
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
400
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
401
0
           "%s: unable to free key.",
402
0
           function );
403
404
0
          goto on_error;
405
0
        }
406
390
      }
407
577
    }
408
2.34k
    else if( property_metadata_entry->value_type == LIBBDE_VALUE_TYPE_UNICODE_STRING )
409
761
    {
410
#if defined( HAVE_DEBUG_OUTPUT )
411
      if( libbde_metadata_entry_read_string(
412
           property_metadata_entry,
413
           error ) != 1 )
414
      {
415
        libcerror_error_set(
416
         error,
417
         LIBCERROR_ERROR_DOMAIN_IO,
418
         LIBCERROR_IO_ERROR_READ_FAILED,
419
         "%s: unable to read string from property metadata entry.",
420
         function );
421
422
        goto on_error;
423
      }
424
#endif
425
761
      if( external_key->string_entry == NULL )
426
234
      {
427
234
        external_key->string_entry = property_metadata_entry;
428
234
      }
429
761
    }
430
2.92k
    if( libcdata_array_append_entry(
431
2.92k
         external_key->entries_array,
432
2.92k
         &property_metadata_entry_index,
433
2.92k
         (intptr_t *) property_metadata_entry,
434
2.92k
         error ) != 1 )
435
0
    {
436
0
      libcerror_error_set(
437
0
       error,
438
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
439
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
440
0
       "%s: unable to append property metadata entry to entries array.",
441
0
       function );
442
443
0
      goto on_error;
444
0
    }
445
2.92k
    property_metadata_entry = NULL;
446
2.92k
  }
447
#if defined( HAVE_DEBUG_OUTPUT )
448
  if( libcnotify_verbose != 0 )
449
  {
450
    if( value_data_size > 0 )
451
    {
452
      libcnotify_printf(
453
       "%s: trailing data:\n",
454
       function );
455
      libcnotify_print_data(
456
       value_data,
457
       value_data_size,
458
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
459
    }
460
  }
461
#endif
462
499
  return( 1 );
463
464
26
on_error:
465
26
  if( key != NULL )
466
2
  {
467
2
    libbde_key_free(
468
2
     &key,
469
2
     NULL );
470
2
  }
471
26
  if( property_metadata_entry != NULL )
472
26
  {
473
26
    libbde_metadata_entry_free(
474
26
     &property_metadata_entry,
475
     NULL );
476
26
  }
477
26
  return( -1 );
478
525
}
479