Coverage Report

Created: 2025-06-24 07:14

/src/libfsapfs/libfsapfs/libfsapfs_volume_key_bag.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The volume key bag functions
3
 *
4
 * Copyright (C) 2018-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 "libfsapfs_definitions.h"
28
#include "libfsapfs_encryption_context.h"
29
#include "libfsapfs_io_handle.h"
30
#include "libfsapfs_key_bag_entry.h"
31
#include "libfsapfs_key_bag_header.h"
32
#include "libfsapfs_key_encrypted_key.h"
33
#include "libfsapfs_libbfio.h"
34
#include "libfsapfs_libcdata.h"
35
#include "libfsapfs_libcerror.h"
36
#include "libfsapfs_libcnotify.h"
37
#include "libfsapfs_volume_key_bag.h"
38
39
#include "fsapfs_key_bag.h"
40
#include "fsapfs_object.h"
41
42
/* Creates a volume key bag
43
 * Make sure the value volume_key_bag is referencing, is set to NULL
44
 * Returns 1 if successful or -1 on error
45
 */
46
int libfsapfs_volume_key_bag_initialize(
47
     libfsapfs_volume_key_bag_t **volume_key_bag,
48
     libcerror_error_t **error )
49
0
{
50
0
  static char *function = "libfsapfs_volume_key_bag_initialize";
51
52
0
  if( volume_key_bag == 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 volume key bag.",
59
0
     function );
60
61
0
    return( -1 );
62
0
  }
63
0
  if( *volume_key_bag != 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 volume key bag value already set.",
70
0
     function );
71
72
0
    return( -1 );
73
0
  }
74
0
  *volume_key_bag = memory_allocate_structure(
75
0
                     libfsapfs_volume_key_bag_t );
76
77
0
  if( *volume_key_bag == 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 volume key bag.",
84
0
     function );
85
86
0
    goto on_error;
87
0
  }
88
0
  if( memory_set(
89
0
       *volume_key_bag,
90
0
       0,
91
0
       sizeof( libfsapfs_volume_key_bag_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 volume key bag.",
98
0
     function );
99
100
0
    memory_free(
101
0
     *volume_key_bag );
102
103
0
    *volume_key_bag = NULL;
104
105
0
    return( -1 );
106
0
  }
107
0
  if( libcdata_array_initialize(
108
0
       &( ( *volume_key_bag )->entries_array ),
109
0
       0,
110
0
       error ) != 1 )
111
0
  {
112
0
    libcerror_error_set(
113
0
     error,
114
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
115
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
116
0
     "%s: unable to create entries array.",
117
0
     function );
118
119
0
    goto on_error;
120
0
  }
121
0
  return( 1 );
122
123
0
on_error:
124
0
  if( *volume_key_bag != NULL )
125
0
  {
126
0
    memory_free(
127
0
     *volume_key_bag );
128
129
0
    *volume_key_bag = NULL;
130
0
  }
131
0
  return( -1 );
132
0
}
133
134
/* Frees a volume key bag
135
 * Returns 1 if successful or -1 on error
136
 */
137
int libfsapfs_volume_key_bag_free(
138
     libfsapfs_volume_key_bag_t **volume_key_bag,
139
     libcerror_error_t **error )
140
0
{
141
0
  static char *function = "libfsapfs_volume_key_bag_free";
142
0
  int result            = 1;
143
144
0
  if( volume_key_bag == NULL )
145
0
  {
146
0
    libcerror_error_set(
147
0
     error,
148
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
149
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
150
0
     "%s: invalid volume key bag.",
151
0
     function );
152
153
0
    return( -1 );
154
0
  }
155
0
  if( *volume_key_bag != NULL )
156
0
  {
157
0
    if( libcdata_array_free(
158
0
         &( ( *volume_key_bag )->entries_array ),
159
0
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_key_bag_entry_free,
160
0
         error ) != 1 )
161
0
    {
162
0
      libcerror_error_set(
163
0
       error,
164
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
165
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
166
0
       "%s: unable to free entries array.",
167
0
       function );
168
169
0
      result = -1;
170
0
    }
171
0
    memory_free(
172
0
     *volume_key_bag );
173
174
0
    *volume_key_bag = NULL;
175
0
  }
176
0
  return( result );
177
0
}
178
179
/* Reads the volume key bag
180
 * Returns 1 if successful or -1 on error
181
 */
182
int libfsapfs_volume_key_bag_read_file_io_handle(
183
     libfsapfs_volume_key_bag_t *volume_key_bag,
184
     libfsapfs_io_handle_t *io_handle,
185
     libbfio_handle_t *file_io_handle,
186
     off64_t file_offset,
187
     size64_t data_size,
188
     const uint8_t *volume_identifier,
189
     libcerror_error_t **error )
190
0
{
191
0
  libfsapfs_encryption_context_t *encryption_context = NULL;
192
0
  uint8_t *data                                      = NULL;
193
0
  uint8_t *encrypted_data                            = NULL;
194
0
  static char *function                              = "libfsapfs_volume_key_bag_read_file_io_handle";
195
0
  ssize_t read_count                                 = 0;
196
197
0
  if( volume_key_bag == NULL )
198
0
  {
199
0
    libcerror_error_set(
200
0
     error,
201
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
202
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
203
0
     "%s: invalid volume key bag.",
204
0
     function );
205
206
0
    return( -1 );
207
0
  }
208
0
  if( io_handle == NULL )
209
0
  {
210
0
    libcerror_error_set(
211
0
     error,
212
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
213
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
214
0
     "%s: invalid IO handle.",
215
0
     function );
216
217
0
    return( -1 );
218
0
  }
219
0
  if( io_handle->bytes_per_sector == 0 )
220
0
  {
221
0
    libcerror_error_set(
222
0
     error,
223
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
224
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
225
0
     "%s: invalid IO handle - missing bytes per sector.",
226
0
     function );
227
228
0
    return( -1 );
229
0
  }
230
0
  if( ( data_size == 0 )
231
0
   || ( data_size > (size64_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
232
0
  {
233
0
    libcerror_error_set(
234
0
     error,
235
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
236
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
237
0
     "%s: invalid volume key bag size value out of bounds.",
238
0
     function );
239
240
0
    return( -1 );
241
0
  }
242
0
  encrypted_data = (uint8_t *) memory_allocate(
243
0
                                sizeof( uint8_t ) * (size_t) data_size );
244
245
0
  if( encrypted_data == NULL )
246
0
  {
247
0
    libcerror_error_set(
248
0
     error,
249
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
250
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
251
0
     "%s: unable to create enrypted data.",
252
0
     function );
253
254
0
    goto on_error;
255
0
  }
256
#if defined( HAVE_DEBUG_OUTPUT )
257
  if( libcnotify_verbose != 0 )
258
  {
259
    libcnotify_printf(
260
     "%s: reading volume key bag data at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
261
     function,
262
     file_offset,
263
     file_offset );
264
  }
265
#endif
266
0
  read_count = libbfio_handle_read_buffer_at_offset(
267
0
                file_io_handle,
268
0
                encrypted_data,
269
0
                (size_t) data_size,
270
0
                file_offset,
271
0
                error );
272
273
0
  if( read_count != (ssize_t) data_size )
274
0
  {
275
0
    libcerror_error_set(
276
0
     error,
277
0
     LIBCERROR_ERROR_DOMAIN_IO,
278
0
     LIBCERROR_IO_ERROR_READ_FAILED,
279
0
     "%s: unable to read encrypted data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
280
0
     function,
281
0
     file_offset,
282
0
     file_offset );
283
284
0
    goto on_error;
285
0
  }
286
0
  data = (uint8_t *) memory_allocate(
287
0
                      sizeof( uint8_t ) * (size_t) data_size );
288
289
0
  if( data == NULL )
290
0
  {
291
0
    libcerror_error_set(
292
0
     error,
293
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
294
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
295
0
     "%s: unable to create data.",
296
0
     function );
297
298
0
    goto on_error;
299
0
  }
300
0
  if( libfsapfs_encryption_context_initialize(
301
0
       &encryption_context,
302
0
       LIBFSAPFS_ENCRYPTION_METHOD_AES_128_XTS,
303
0
       error ) != 1 )
304
0
  {
305
0
    libcerror_error_set(
306
0
     error,
307
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
308
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
309
0
     "%s: unable to initialize encryption context.",
310
0
     function );
311
312
0
    goto on_error;
313
0
  }
314
0
  if( libfsapfs_encryption_context_set_keys(
315
0
       encryption_context,
316
0
       volume_identifier,
317
0
       16,
318
0
       volume_identifier,
319
0
       16,
320
0
       error ) != 1 )
321
0
  {
322
0
    libcerror_error_set(
323
0
     error,
324
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
325
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
326
0
     "%s: unable to set keys in encryption context.",
327
0
     function );
328
329
0
    goto on_error;
330
0
  }
331
0
  if( libfsapfs_encryption_context_crypt(
332
0
       encryption_context,
333
0
       LIBCAES_CRYPT_MODE_DECRYPT,
334
0
       encrypted_data,
335
0
       (size_t) data_size,
336
0
       data,
337
0
       (size_t) data_size,
338
0
       (uint64_t) ( file_offset / io_handle->bytes_per_sector ),
339
0
       io_handle->bytes_per_sector,
340
0
       error ) != 1 )
341
0
  {
342
0
    libcerror_error_set(
343
0
     error,
344
0
     LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
345
0
     LIBCERROR_ENCRYPTION_ERROR_DECRYPT_FAILED,
346
0
     "%s: unable to decrypt data.",
347
0
     function );
348
349
0
    goto on_error;
350
0
  }
351
0
  if( libfsapfs_encryption_context_free(
352
0
       &encryption_context,
353
0
       error ) != 1 )
354
0
  {
355
0
    libcerror_error_set(
356
0
     error,
357
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
358
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
359
0
     "%s: unable to free encryption context.",
360
0
     function );
361
362
0
    goto on_error;
363
0
  }
364
0
  memory_free(
365
0
   encrypted_data );
366
367
0
  encrypted_data = NULL;
368
369
#if defined( HAVE_DEBUG_OUTPUT )
370
  if( libcnotify_verbose != 0 )
371
  {
372
    libcnotify_printf(
373
     "%s: unencrypted volume key bag data:\n",
374
     function );
375
    libcnotify_print_data(
376
     data,
377
     (size_t) data_size,
378
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
379
  }
380
#endif
381
0
  if( libfsapfs_volume_key_bag_read_data(
382
0
       volume_key_bag,
383
0
       data,
384
0
       (size_t) data_size,
385
0
       error ) != 1 )
386
0
  {
387
0
    libcerror_error_set(
388
0
     error,
389
0
     LIBCERROR_ERROR_DOMAIN_IO,
390
0
     LIBCERROR_IO_ERROR_READ_FAILED,
391
0
     "%s: unable to read volume key bag.",
392
0
     function );
393
394
0
    goto on_error;
395
0
  }
396
0
  memory_free(
397
0
   data );
398
399
0
  return( 1 );
400
401
0
on_error:
402
0
  if( encryption_context != NULL )
403
0
  {
404
0
    libfsapfs_encryption_context_free(
405
0
     &encryption_context,
406
0
     NULL );
407
0
  }
408
0
  if( data != NULL )
409
0
  {
410
0
    memory_free(
411
0
     data );
412
0
  }
413
0
  if( encrypted_data != NULL )
414
0
  {
415
0
    memory_free(
416
0
     encrypted_data );
417
0
  }
418
0
  return( -1 );
419
0
}
420
421
/* Reads the volume key bag
422
 * Returns 1 if successful or -1 on error
423
 */
424
int libfsapfs_volume_key_bag_read_data(
425
     libfsapfs_volume_key_bag_t *volume_key_bag,
426
     const uint8_t *data,
427
     size_t data_size,
428
     libcerror_error_t **error )
429
0
{
430
0
  libfsapfs_key_bag_entry_t *bag_entry   = NULL;
431
0
  libfsapfs_key_bag_header_t *bag_header = NULL;
432
0
  static char *function                  = "libfsapfs_volume_key_bag_read_data";
433
0
  size_t alignment_padding_size          = 0;
434
0
  size_t data_offset                     = 0;
435
0
  uint64_t object_subtype                = 0;
436
0
  uint64_t object_type                   = 0;
437
0
  uint16_t bag_entry_index               = 0;
438
0
  int entry_index                        = 0;
439
440
#if defined( HAVE_DEBUG_OUTPUT )
441
  uint64_t value_64bit                   = 0;
442
#endif
443
444
0
  if( volume_key_bag == NULL )
445
0
  {
446
0
    libcerror_error_set(
447
0
     error,
448
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
449
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
450
0
     "%s: invalid volume key bag.",
451
0
     function );
452
453
0
    return( -1 );
454
0
  }
455
0
  if( data == NULL )
456
0
  {
457
0
    libcerror_error_set(
458
0
     error,
459
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
460
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
461
0
     "%s: invalid data.",
462
0
     function );
463
464
0
    return( -1 );
465
0
  }
466
0
  if( ( data_size < sizeof( fsapfs_object_t ) )
467
0
   || ( data_size > (size_t) SSIZE_MAX ) )
468
0
  {
469
0
    libcerror_error_set(
470
0
     error,
471
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
472
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
473
0
     "%s: invalid data size value out of bounds.",
474
0
     function );
475
476
0
    return( -1 );
477
0
  }
478
#if defined( HAVE_DEBUG_OUTPUT )
479
  if( libcnotify_verbose != 0 )
480
  {
481
    libcnotify_printf(
482
     "%s: volume key bag object data:\n",
483
     function );
484
    libcnotify_print_data(
485
     data,
486
     sizeof( fsapfs_object_t ),
487
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
488
  }
489
#endif
490
0
  byte_stream_copy_to_uint32_little_endian(
491
0
   ( (fsapfs_object_t *) data )->type,
492
0
   object_type );
493
494
0
  if( object_type != 0x72656373 )
495
0
  {
496
0
    libcerror_error_set(
497
0
     error,
498
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
499
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
500
0
     "%s: invalid object type: 0x%08" PRIx32 ".",
501
0
     function,
502
0
     object_type );
503
504
0
    goto on_error;
505
0
  }
506
0
  byte_stream_copy_to_uint32_little_endian(
507
0
   ( (fsapfs_object_t *) data )->subtype,
508
0
   object_subtype );
509
510
0
  if( object_subtype != 0x00000000UL )
511
0
  {
512
0
    libcerror_error_set(
513
0
     error,
514
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
515
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
516
0
     "%s: invalid object subtype: 0x%08" PRIx32 ".",
517
0
     function,
518
0
     object_subtype );
519
520
0
    goto on_error;
521
0
  }
522
#if defined( HAVE_DEBUG_OUTPUT )
523
  if( libcnotify_verbose != 0 )
524
  {
525
    byte_stream_copy_to_uint64_little_endian(
526
     ( (fsapfs_object_t *) data )->checksum,
527
     value_64bit );
528
    libcnotify_printf(
529
     "%s: object checksum\t\t\t: 0x%08" PRIx64 "\n",
530
     function,
531
     value_64bit );
532
533
    byte_stream_copy_to_uint64_little_endian(
534
     ( (fsapfs_object_t *) data )->identifier,
535
     value_64bit );
536
    libcnotify_printf(
537
     "%s: object identifier\t\t\t: %" PRIu64 "\n",
538
     function,
539
     value_64bit );
540
541
    byte_stream_copy_to_uint64_little_endian(
542
     ( (fsapfs_object_t *) data )->transaction_identifier,
543
     value_64bit );
544
    libcnotify_printf(
545
     "%s: object transaction identifier\t: %" PRIu64 "\n",
546
     function,
547
     value_64bit );
548
549
    libcnotify_printf(
550
     "%s: object type\t\t\t\t: 0x%08" PRIx32 "\n",
551
     function,
552
     object_type );
553
554
    libcnotify_printf(
555
     "%s: object subtype\t\t\t: 0x%08" PRIx32 "\n",
556
     function,
557
     object_subtype );
558
559
    libcnotify_printf(
560
     "\n" );
561
  }
562
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
563
564
0
  data_offset = sizeof( fsapfs_object_t );
565
566
0
  if( libfsapfs_key_bag_header_initialize(
567
0
       &bag_header,
568
0
       error ) != 1 )
569
0
  {
570
0
    libcerror_error_set(
571
0
     error,
572
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
573
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
574
0
     "%s: unable to create key bag header.",
575
0
     function );
576
577
0
    goto on_error;
578
0
  }
579
0
  if( libfsapfs_key_bag_header_read_data(
580
0
       bag_header,
581
0
       &( data[ data_offset ] ),
582
0
       data_size - data_offset,
583
0
       error ) != 1 )
584
0
  {
585
0
    libcerror_error_set(
586
0
     error,
587
0
     LIBCERROR_ERROR_DOMAIN_IO,
588
0
     LIBCERROR_IO_ERROR_READ_FAILED,
589
0
     "%s: unable to read key bag header.",
590
0
     function );
591
592
0
    goto on_error;
593
0
  }
594
0
  if( (size_t) bag_header->data_size > ( data_size - data_offset ) )
595
0
  {
596
0
    libcerror_error_set(
597
0
     error,
598
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
599
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
600
0
     "%s: invalid key bag header data size value out of bounds.",
601
0
     function );
602
603
0
    goto on_error;
604
0
  }
605
/* TODO bounds check number of entries ? */
606
607
0
  data_offset += 16;
608
609
0
  for( bag_entry_index = 0;
610
0
       bag_entry_index < bag_header->number_of_entries;
611
0
       bag_entry_index++ )
612
0
  {
613
0
    if( libfsapfs_key_bag_entry_initialize(
614
0
         &bag_entry,
615
0
         error ) != 1 )
616
0
    {
617
0
      libcerror_error_set(
618
0
       error,
619
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
620
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
621
0
       "%s: unable to create key bag entry: %" PRIu16 ".",
622
0
       function,
623
0
       bag_entry_index );
624
625
0
      goto on_error;
626
0
    }
627
0
    if( libfsapfs_key_bag_entry_read_data(
628
0
         bag_entry,
629
0
         &( data[ data_offset ] ),
630
0
         data_size - data_offset,
631
0
         error ) != 1 )
632
0
    {
633
0
      libcerror_error_set(
634
0
       error,
635
0
       LIBCERROR_ERROR_DOMAIN_IO,
636
0
       LIBCERROR_IO_ERROR_READ_FAILED,
637
0
       "%s: unable to read key bag entry: %" PRIu16 ".",
638
0
       function,
639
0
       bag_entry_index );
640
641
0
      goto on_error;
642
0
    }
643
0
    if( libcdata_array_append_entry(
644
0
         volume_key_bag->entries_array,
645
0
         &entry_index,
646
0
         (intptr_t *) bag_entry,
647
0
         error ) != 1 )
648
0
    {
649
0
      libcerror_error_set(
650
0
       error,
651
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
652
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
653
0
       "%s: unable to append bag entry: %" PRIu32 " to array.",
654
0
       function,
655
0
       bag_entry_index );
656
657
0
      goto on_error;
658
0
    }
659
0
    data_offset += bag_entry->size;
660
661
0
    bag_entry = NULL;
662
663
0
    alignment_padding_size = data_offset % 16;
664
665
0
    if( alignment_padding_size != 0 )
666
0
    {
667
0
      alignment_padding_size = 16 - alignment_padding_size;
668
669
0
      if( ( alignment_padding_size > data_size )
670
0
       || ( data_offset > ( data_size - alignment_padding_size ) ) )
671
0
      {
672
0
        libcerror_error_set(
673
0
         error,
674
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
675
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
676
0
         "%s: invalid data size value out of bounds.",
677
0
         function );
678
679
0
        goto on_error;
680
0
      }
681
#if defined( HAVE_DEBUG_OUTPUT )
682
      if( libcnotify_verbose != 0 )
683
      {
684
        libcnotify_printf(
685
         "%s: alignment padding data:\n",
686
         function );
687
        libcnotify_print_data(
688
         &( data[ data_offset ] ),
689
         alignment_padding_size,
690
         LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
691
      }
692
#endif
693
0
      data_offset += alignment_padding_size;
694
0
    }
695
0
  }
696
0
  if( libfsapfs_key_bag_header_free(
697
0
       &bag_header,
698
0
       error ) != 1 )
699
0
  {
700
0
    libcerror_error_set(
701
0
     error,
702
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
703
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
704
0
     "%s: unable to free key bag header.",
705
0
     function );
706
707
0
    goto on_error;
708
0
  }
709
0
  return( 1 );
710
711
0
on_error:
712
0
  if( bag_entry != NULL )
713
0
  {
714
0
    libfsapfs_key_bag_entry_free(
715
0
     &bag_entry,
716
0
     NULL );
717
0
  }
718
0
  if( bag_header != NULL )
719
0
  {
720
0
    libfsapfs_key_bag_header_free(
721
0
     &bag_header,
722
0
     NULL );
723
0
  }
724
0
  return( -1 );
725
0
}
726
727
/* Retrieves the volume key that can be unlocked
728
 * Returns 1 if successful, 0 if no such volume key or -1 on error
729
 */
730
int libfsapfs_volume_key_bag_get_volume_key(
731
     libfsapfs_volume_key_bag_t *volume_key_bag,
732
     const uint8_t *user_password,
733
     size_t user_password_length,
734
     const uint8_t *recovery_password,
735
     size_t recovery_password_length,
736
     uint8_t *key,
737
     size_t key_size,
738
     libcerror_error_t **error )
739
0
{
740
0
  libfsapfs_key_bag_entry_t *bag_entry             = NULL;
741
0
  libfsapfs_key_encrypted_key_t *key_encrypted_key = NULL;
742
0
  static char *function                            = "libfsapfs_volume_key_bag_get_volume_key";
743
0
  int entry_index                                  = 0;
744
0
  int number_of_entries                            = 0;
745
0
  int result                                       = 0;
746
747
0
  if( volume_key_bag == NULL )
748
0
  {
749
0
    libcerror_error_set(
750
0
     error,
751
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
752
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
753
0
     "%s: invalid volume key bag.",
754
0
     function );
755
756
0
    return( -1 );
757
0
  }
758
0
  if( libcdata_array_get_number_of_entries(
759
0
       volume_key_bag->entries_array,
760
0
       &number_of_entries,
761
0
       error ) != 1 )
762
0
  {
763
0
    libcerror_error_set(
764
0
     error,
765
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
766
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
767
0
     "%s: unable to retrieve number of entries from array.",
768
0
     function );
769
770
0
    goto on_error;
771
0
  }
772
0
  for( entry_index = 0;
773
0
       entry_index < number_of_entries;
774
0
       entry_index++ )
775
0
  {
776
0
    if( libcdata_array_get_entry_by_index(
777
0
         volume_key_bag->entries_array,
778
0
         entry_index,
779
0
         (intptr_t **) &bag_entry,
780
0
         error ) != 1 )
781
0
    {
782
0
      libcerror_error_set(
783
0
       error,
784
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
785
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
786
0
       "%s: unable to retrieve entry: %d from array.",
787
0
       function,
788
0
       entry_index );
789
790
0
      goto on_error;
791
0
    }
792
0
    if( bag_entry == NULL )
793
0
    {
794
0
      libcerror_error_set(
795
0
       error,
796
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
797
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
798
0
       "%s: missing entry: %d.",
799
0
       function,
800
0
       entry_index );
801
802
0
      goto on_error;
803
0
    }
804
0
    if( bag_entry->type != 3 )
805
0
    {
806
0
      continue;
807
0
    }
808
0
    if( libfsapfs_key_encrypted_key_initialize(
809
0
         &key_encrypted_key,
810
0
         error ) != 1 )
811
0
    {
812
0
      libcerror_error_set(
813
0
       error,
814
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
815
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
816
0
       "%s: unable to create key encrypted key.",
817
0
       function );
818
819
0
      goto on_error;
820
0
    }
821
0
    if( libfsapfs_key_encrypted_key_read_data(
822
0
         key_encrypted_key,
823
0
         bag_entry->data,
824
0
         (size_t) bag_entry->data_size,
825
0
         error ) != 1 )
826
0
    {
827
0
      libcerror_error_set(
828
0
       error,
829
0
       LIBCERROR_ERROR_DOMAIN_IO,
830
0
       LIBCERROR_IO_ERROR_READ_FAILED,
831
0
       "%s: unable to read key encrypted key.",
832
0
       function );
833
834
0
      goto on_error;
835
0
    }
836
0
    if( user_password != NULL )
837
0
    {
838
0
      result = libfsapfs_key_encrypted_key_unlock_with_password(
839
0
                key_encrypted_key,
840
0
                user_password,
841
0
                user_password_length,
842
0
                key,
843
0
                key_size,
844
0
                error );
845
846
0
      if( result == -1 )
847
0
      {
848
0
        libcerror_error_set(
849
0
         error,
850
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
851
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
852
0
         "%s: unable to unlock key encrypted key with user password.",
853
0
         function );
854
855
0
        goto on_error;
856
0
      }
857
0
    }
858
0
    if( ( result == 0 )
859
0
     && ( recovery_password != NULL ) )
860
0
    {
861
0
      result = libfsapfs_key_encrypted_key_unlock_with_password(
862
0
                key_encrypted_key,
863
0
                recovery_password,
864
0
                recovery_password_length,
865
0
                key,
866
0
                key_size,
867
0
                error );
868
869
0
      if( result == -1 )
870
0
      {
871
0
        libcerror_error_set(
872
0
         error,
873
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
874
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
875
0
         "%s: unable to unlock key encrypted key with recovery password.",
876
0
         function );
877
878
0
        goto on_error;
879
0
      }
880
0
    }
881
0
    if( libfsapfs_key_encrypted_key_free(
882
0
         &key_encrypted_key,
883
0
         error ) != 1 )
884
0
    {
885
0
      libcerror_error_set(
886
0
       error,
887
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
888
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
889
0
       "%s: unable to free key encrypted key.",
890
0
       function );
891
892
0
      goto on_error;
893
0
    }
894
0
    if( result == 1 )
895
0
    {
896
0
      break;
897
0
    }
898
0
  }
899
0
  return( result );
900
901
0
on_error:
902
0
  if( key_encrypted_key != NULL )
903
0
  {
904
0
    libfsapfs_key_encrypted_key_free(
905
0
     &key_encrypted_key,
906
0
     NULL );
907
0
  }
908
0
  return( -1 );
909
0
}
910