Coverage Report

Created: 2026-07-25 07:30

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
3.10k
{
50
3.10k
  static char *function = "libbde_external_key_initialize";
51
52
3.10k
  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
3.10k
  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
3.10k
  *external_key = memory_allocate_structure(
75
3.10k
                   libbde_external_key_t );
76
77
3.10k
  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
3.10k
  if( memory_set(
89
3.10k
       *external_key,
90
3.10k
       0,
91
3.10k
       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
3.10k
  if( libcdata_array_initialize(
103
3.10k
       &( ( *external_key )->entries_array ),
104
3.10k
       0,
105
3.10k
       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
3.10k
  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
3.10k
}
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
3.10k
{
136
3.10k
  static char *function = "libbde_external_key_free";
137
3.10k
  int result            = 1;
138
139
3.10k
  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
3.10k
  if( *external_key != NULL )
151
3.10k
  {
152
3.10k
    if( ( *external_key )->key != NULL )
153
133
    {
154
133
      if( libbde_key_free(
155
133
           &( ( *external_key )->key ),
156
133
           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
133
    }
168
3.10k
    if( libcdata_array_free(
169
3.10k
         &( ( *external_key )->entries_array ),
170
3.10k
         (int(*)(intptr_t **, libcerror_error_t **)) &libbde_metadata_entry_free,
171
3.10k
         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
3.10k
    memory_free(
183
3.10k
     *external_key );
184
185
3.10k
    *external_key = NULL;
186
3.10k
  }
187
3.10k
  return( result );
188
3.10k
}
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
3.10k
{
198
3.10k
  libbde_key_t *key                                = NULL;
199
3.10k
  libbde_metadata_entry_t *property_metadata_entry = NULL;
200
3.10k
  uint8_t *value_data                              = NULL;
201
3.10k
  static char *function                            = "libbde_external_key_read";
202
3.10k
  size_t value_data_size                           = 0;
203
3.10k
  ssize_t read_count                               = 0;
204
3.10k
  int property_metadata_entry_index                = 0;
205
206
3.10k
  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
3.10k
  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
3.10k
  if( metadata_entry->value_type != LIBBDE_VALUE_TYPE_EXTERNAL_KEY )
229
18
  {
230
18
    libcerror_error_set(
231
18
     error,
232
18
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
233
18
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
234
18
     "%s: invalid metadata entry - unsupported value type: 0x%04" PRIx16 ".",
235
18
     function,
236
18
     metadata_entry->value_type );
237
238
18
    return( -1 );
239
18
  }
240
3.08k
  value_data      = metadata_entry->value_data;
241
3.08k
  value_data_size = metadata_entry->value_data_size;
242
243
3.08k
  if( value_data_size < sizeof( bde_metadata_entry_external_key_header_t ) )
244
4
  {
245
4
    libcerror_error_set(
246
4
     error,
247
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
248
4
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
249
4
     "%s: value data size value out of bounds.",
250
4
     function );
251
252
4
    return( -1 );
253
4
  }
254
3.08k
  if( memory_copy(
255
3.08k
       external_key->identifier,
256
3.08k
       ( (bde_metadata_entry_external_key_header_t *) value_data )->identifier,
257
3.08k
       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
3.08k
  value_data      += sizeof( bde_metadata_entry_external_key_header_t );
312
3.08k
  value_data_size -= sizeof( bde_metadata_entry_external_key_header_t );
313
314
7.77k
  while( value_data_size >= sizeof( bde_metadata_entry_v1_t ) )
315
4.95k
  {
316
4.95k
    if( memory_compare(
317
4.95k
         value_data,
318
4.95k
         libbde_metadata_entry_empty,
319
4.95k
         sizeof( bde_metadata_entry_v1_t ) ) == 0 )
320
242
    {
321
242
      break;
322
242
    }
323
4.71k
    if( libbde_metadata_entry_initialize(
324
4.71k
         &property_metadata_entry,
325
4.71k
         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
4.71k
    read_count = libbde_metadata_entry_read(
337
4.71k
            property_metadata_entry,
338
4.71k
            value_data,
339
4.71k
            value_data_size,
340
4.71k
            error );
341
342
4.71k
    if( read_count == -1 )
343
20
    {
344
20
      libcerror_error_set(
345
20
       error,
346
20
       LIBCERROR_ERROR_DOMAIN_IO,
347
20
       LIBCERROR_IO_ERROR_READ_FAILED,
348
20
       "%s: unable to read property metadata entry.",
349
20
       function );
350
351
20
      goto on_error;
352
20
    }
353
4.69k
    value_data      += read_count;
354
4.69k
    value_data_size -= read_count;
355
356
4.69k
    if( property_metadata_entry->value_type == LIBBDE_VALUE_TYPE_KEY )
357
680
    {
358
680
      if( libbde_key_initialize(
359
680
           &key,
360
680
           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
680
      if( libbde_key_read(
372
680
           key,
373
680
           property_metadata_entry,
374
680
           error ) != 1 )
375
1
      {
376
1
        libcerror_error_set(
377
1
         error,
378
1
         LIBCERROR_ERROR_DOMAIN_IO,
379
1
         LIBCERROR_IO_ERROR_READ_FAILED,
380
1
         "%s: unable to read key metadata entry.",
381
1
         function );
382
383
1
        goto on_error;
384
1
      }
385
679
      if( external_key->key == NULL )
386
133
      {
387
133
        external_key->key = key;
388
389
133
        key = NULL;
390
133
      }
391
679
      if( key != NULL )
392
546
      {
393
546
        if( libbde_key_free(
394
546
             &key,
395
546
             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
546
      }
407
679
    }
408
4.01k
    else if( property_metadata_entry->value_type == LIBBDE_VALUE_TYPE_UNICODE_STRING )
409
1.00k
    {
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
1.00k
      if( external_key->string_entry == NULL )
426
429
      {
427
429
        external_key->string_entry = property_metadata_entry;
428
429
      }
429
1.00k
    }
430
4.69k
    if( libcdata_array_append_entry(
431
4.69k
         external_key->entries_array,
432
4.69k
         &property_metadata_entry_index,
433
4.69k
         (intptr_t *) property_metadata_entry,
434
4.69k
         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
4.69k
    property_metadata_entry = NULL;
446
4.69k
  }
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
3.06k
  return( 1 );
463
464
21
on_error:
465
21
  if( key != NULL )
466
1
  {
467
1
    libbde_key_free(
468
1
     &key,
469
1
     NULL );
470
1
  }
471
21
  if( property_metadata_entry != NULL )
472
21
  {
473
21
    libbde_metadata_entry_free(
474
21
     &property_metadata_entry,
475
     NULL );
476
21
  }
477
21
  return( -1 );
478
3.08k
}
479