Coverage Report

Created: 2024-06-12 07:07

/src/libfsapfs/libfsapfs/libfsapfs_container_key_bag.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The container 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_checksum.h"
28
#include "libfsapfs_container_key_bag.h"
29
#include "libfsapfs_definitions.h"
30
#include "libfsapfs_encryption_context.h"
31
#include "libfsapfs_io_handle.h"
32
#include "libfsapfs_key_bag_entry.h"
33
#include "libfsapfs_key_bag_header.h"
34
#include "libfsapfs_key_encrypted_key.h"
35
#include "libfsapfs_libbfio.h"
36
#include "libfsapfs_libcdata.h"
37
#include "libfsapfs_libcerror.h"
38
#include "libfsapfs_libcnotify.h"
39
40
#include "fsapfs_key_bag.h"
41
#include "fsapfs_object.h"
42
43
/* Creates a container key bag
44
 * Make sure the value container_key_bag is referencing, is set to NULL
45
 * Returns 1 if successful or -1 on error
46
 */
47
int libfsapfs_container_key_bag_initialize(
48
     libfsapfs_container_key_bag_t **container_key_bag,
49
     libcerror_error_t **error )
50
1.20k
{
51
1.20k
  static char *function = "libfsapfs_container_key_bag_initialize";
52
53
1.20k
  if( container_key_bag == NULL )
54
0
  {
55
0
    libcerror_error_set(
56
0
     error,
57
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
58
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
59
0
     "%s: invalid container key bag.",
60
0
     function );
61
62
0
    return( -1 );
63
0
  }
64
1.20k
  if( *container_key_bag != NULL )
65
0
  {
66
0
    libcerror_error_set(
67
0
     error,
68
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
69
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
70
0
     "%s: invalid container key bag value already set.",
71
0
     function );
72
73
0
    return( -1 );
74
0
  }
75
1.20k
  *container_key_bag = memory_allocate_structure(
76
1.20k
                        libfsapfs_container_key_bag_t );
77
78
1.20k
  if( *container_key_bag == NULL )
79
0
  {
80
0
    libcerror_error_set(
81
0
     error,
82
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
83
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
84
0
     "%s: unable to create container key bag.",
85
0
     function );
86
87
0
    goto on_error;
88
0
  }
89
1.20k
  if( memory_set(
90
1.20k
       *container_key_bag,
91
1.20k
       0,
92
1.20k
       sizeof( libfsapfs_container_key_bag_t ) ) == NULL )
93
0
  {
94
0
    libcerror_error_set(
95
0
     error,
96
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
97
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
98
0
     "%s: unable to clear container key bag.",
99
0
     function );
100
101
0
    memory_free(
102
0
     *container_key_bag );
103
104
0
    *container_key_bag = NULL;
105
106
0
    return( -1 );
107
0
  }
108
1.20k
  if( libcdata_array_initialize(
109
1.20k
       &( ( *container_key_bag )->entries_array ),
110
1.20k
       0,
111
1.20k
       error ) != 1 )
112
0
  {
113
0
    libcerror_error_set(
114
0
     error,
115
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
116
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
117
0
     "%s: unable to create entries array.",
118
0
     function );
119
120
0
    goto on_error;
121
0
  }
122
1.20k
  return( 1 );
123
124
0
on_error:
125
0
  if( *container_key_bag != NULL )
126
0
  {
127
0
    memory_free(
128
0
     *container_key_bag );
129
130
0
    *container_key_bag = NULL;
131
0
  }
132
0
  return( -1 );
133
1.20k
}
134
135
/* Frees a container key bag
136
 * Returns 1 if successful or -1 on error
137
 */
138
int libfsapfs_container_key_bag_free(
139
     libfsapfs_container_key_bag_t **container_key_bag,
140
     libcerror_error_t **error )
141
1.20k
{
142
1.20k
  static char *function = "libfsapfs_container_key_bag_free";
143
1.20k
  int result            = 1;
144
145
1.20k
  if( container_key_bag == NULL )
146
0
  {
147
0
    libcerror_error_set(
148
0
     error,
149
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
150
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
151
0
     "%s: invalid container key bag.",
152
0
     function );
153
154
0
    return( -1 );
155
0
  }
156
1.20k
  if( *container_key_bag != NULL )
157
1.20k
  {
158
1.20k
    if( libcdata_array_free(
159
1.20k
         &( ( *container_key_bag )->entries_array ),
160
1.20k
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_key_bag_entry_free,
161
1.20k
         error ) != 1 )
162
0
    {
163
0
      libcerror_error_set(
164
0
       error,
165
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
166
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
167
0
       "%s: unable to free entries array.",
168
0
       function );
169
170
0
      result = -1;
171
0
    }
172
1.20k
    memory_free(
173
1.20k
     *container_key_bag );
174
175
1.20k
    *container_key_bag = NULL;
176
1.20k
  }
177
1.20k
  return( result );
178
1.20k
}
179
180
/* Reads the container key bag
181
 * Returns 1 if successful, 0 if the object type does not match or -1 on error
182
 */
183
int libfsapfs_container_key_bag_read_file_io_handle(
184
     libfsapfs_container_key_bag_t *container_key_bag,
185
     libfsapfs_io_handle_t *io_handle,
186
     libbfio_handle_t *file_io_handle,
187
     off64_t file_offset,
188
     size64_t data_size,
189
     const uint8_t *container_identifier,
190
     libcerror_error_t **error )
191
1.20k
{
192
1.20k
  libfsapfs_encryption_context_t *encryption_context = NULL;
193
1.20k
  uint8_t *data                                      = NULL;
194
1.20k
  uint8_t *encrypted_data                            = NULL;
195
1.20k
  static char *function                              = "libfsapfs_container_key_bag_read_file_io_handle";
196
1.20k
  ssize_t read_count                                 = 0;
197
1.20k
  int result                                         = 0;
198
199
1.20k
  if( container_key_bag == NULL )
200
0
  {
201
0
    libcerror_error_set(
202
0
     error,
203
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
204
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
205
0
     "%s: invalid container key bag.",
206
0
     function );
207
208
0
    return( -1 );
209
0
  }
210
1.20k
  if( io_handle == NULL )
211
0
  {
212
0
    libcerror_error_set(
213
0
     error,
214
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
215
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
216
0
     "%s: invalid IO handle.",
217
0
     function );
218
219
0
    return( -1 );
220
0
  }
221
1.20k
  if( io_handle->bytes_per_sector == 0 )
222
0
  {
223
0
    libcerror_error_set(
224
0
     error,
225
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
226
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
227
0
     "%s: invalid IO handle - missing bytes per sector.",
228
0
     function );
229
230
0
    return( -1 );
231
0
  }
232
1.20k
  if( ( data_size == 0 )
233
1.20k
   || ( data_size > (size64_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
234
206
  {
235
206
    libcerror_error_set(
236
206
     error,
237
206
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
238
206
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
239
206
     "%s: invalid container key bag size value out of bounds.",
240
206
     function );
241
242
206
    return( -1 );
243
206
  }
244
1.00k
  encrypted_data = (uint8_t *) memory_allocate(
245
1.00k
                                sizeof( uint8_t ) * (size_t) data_size );
246
247
1.00k
  if( encrypted_data == NULL )
248
0
  {
249
0
    libcerror_error_set(
250
0
     error,
251
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
252
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
253
0
     "%s: unable to create enrypted data.",
254
0
     function );
255
256
0
    goto on_error;
257
0
  }
258
#if defined( HAVE_DEBUG_OUTPUT )
259
  if( libcnotify_verbose != 0 )
260
  {
261
    libcnotify_printf(
262
     "%s: reading container key bag data at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
263
     function,
264
     file_offset,
265
     file_offset );
266
  }
267
#endif
268
1.00k
  read_count = libbfio_handle_read_buffer_at_offset(
269
1.00k
                file_io_handle,
270
1.00k
                encrypted_data,
271
1.00k
                (size_t) data_size,
272
1.00k
                file_offset,
273
1.00k
                error );
274
275
1.00k
  if( read_count != (ssize_t) data_size )
276
197
  {
277
197
    libcerror_error_set(
278
197
     error,
279
197
     LIBCERROR_ERROR_DOMAIN_IO,
280
197
     LIBCERROR_IO_ERROR_READ_FAILED,
281
197
     "%s: unable to read encrypted data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
282
197
     function,
283
197
     file_offset,
284
197
     file_offset );
285
286
197
    goto on_error;
287
197
  }
288
805
  data = (uint8_t *) memory_allocate(
289
805
                      sizeof( uint8_t ) * (size_t) data_size );
290
291
805
  if( data == NULL )
292
0
  {
293
0
    libcerror_error_set(
294
0
     error,
295
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
296
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
297
0
     "%s: unable to create data.",
298
0
     function );
299
300
0
    goto on_error;
301
0
  }
302
805
  if( libfsapfs_encryption_context_initialize(
303
805
       &encryption_context,
304
805
       LIBFSAPFS_ENCRYPTION_METHOD_AES_128_XTS,
305
805
       error ) != 1 )
306
0
  {
307
0
    libcerror_error_set(
308
0
     error,
309
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
310
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
311
0
     "%s: unable to initialize encryption context.",
312
0
     function );
313
314
0
    goto on_error;
315
0
  }
316
805
  if( libfsapfs_encryption_context_set_keys(
317
805
       encryption_context,
318
805
       container_identifier,
319
805
       16,
320
805
       container_identifier,
321
805
       16,
322
805
       error ) != 1 )
323
0
  {
324
0
    libcerror_error_set(
325
0
     error,
326
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
327
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
328
0
     "%s: unable to set keys in encryption context.",
329
0
     function );
330
331
0
    goto on_error;
332
0
  }
333
805
  if( libfsapfs_encryption_context_crypt(
334
805
       encryption_context,
335
805
       LIBCAES_CRYPT_MODE_DECRYPT,
336
805
       encrypted_data,
337
805
       (size_t) data_size,
338
805
       data,
339
805
       (size_t) data_size,
340
805
       (uint64_t) ( file_offset / io_handle->bytes_per_sector ),
341
805
       io_handle->bytes_per_sector,
342
805
       error ) != 1 )
343
0
  {
344
0
    libcerror_error_set(
345
0
     error,
346
0
     LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
347
0
     LIBCERROR_ENCRYPTION_ERROR_DECRYPT_FAILED,
348
0
     "%s: unable to decrypt data.",
349
0
     function );
350
351
0
    goto on_error;
352
0
  }
353
805
  if( libfsapfs_encryption_context_free(
354
805
       &encryption_context,
355
805
       error ) != 1 )
356
0
  {
357
0
    libcerror_error_set(
358
0
     error,
359
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
360
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
361
0
     "%s: unable to free encryption context.",
362
0
     function );
363
364
0
    goto on_error;
365
0
  }
366
805
  memory_free(
367
805
   encrypted_data );
368
369
805
  encrypted_data = NULL;
370
371
#if defined( HAVE_DEBUG_OUTPUT )
372
  if( libcnotify_verbose != 0 )
373
  {
374
    libcnotify_printf(
375
     "%s: unencrypted container key bag data:\n",
376
     function );
377
    libcnotify_print_data(
378
     data,
379
     (size_t) data_size,
380
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
381
  }
382
#endif
383
805
  result = libfsapfs_container_key_bag_read_data(
384
805
            container_key_bag,
385
805
            data,
386
805
            (size_t) data_size,
387
805
            error );
388
389
805
  if( result == -1 )
390
0
  {
391
0
    libcerror_error_set(
392
0
     error,
393
0
     LIBCERROR_ERROR_DOMAIN_IO,
394
0
     LIBCERROR_IO_ERROR_READ_FAILED,
395
0
     "%s: unable to read container key bag.",
396
0
     function );
397
398
0
    goto on_error;
399
0
  }
400
805
  memory_free(
401
805
   data );
402
403
805
  return( result );
404
405
197
on_error:
406
197
  if( encryption_context != NULL )
407
0
  {
408
0
    libfsapfs_encryption_context_free(
409
0
     &encryption_context,
410
0
     NULL );
411
0
  }
412
197
  if( data != NULL )
413
0
  {
414
0
    memory_free(
415
0
     data );
416
0
  }
417
197
  if( encrypted_data != NULL )
418
197
  {
419
197
    memory_free(
420
197
     encrypted_data );
421
197
  }
422
197
  return( -1 );
423
805
}
424
425
/* Reads the container key bag
426
 * Returns 1 if successful, 0 if the object type does not match or -1 on error
427
 */
428
int libfsapfs_container_key_bag_read_data(
429
     libfsapfs_container_key_bag_t *container_key_bag,
430
     const uint8_t *data,
431
     size_t data_size,
432
     libcerror_error_t **error )
433
805
{
434
805
  libfsapfs_key_bag_entry_t *bag_entry   = NULL;
435
805
  libfsapfs_key_bag_header_t *bag_header = NULL;
436
805
  static char *function                  = "libfsapfs_container_key_bag_read_data";
437
805
  size_t alignment_padding_size          = 0;
438
805
  size_t data_offset                     = 0;
439
805
  uint64_t calculated_checksum           = 0;
440
805
  uint64_t object_subtype                = 0;
441
805
  uint64_t object_type                   = 0;
442
805
  uint64_t stored_checksum               = 0;
443
805
  uint16_t bag_entry_index               = 0;
444
805
  int entry_index                        = 0;
445
446
#if defined( HAVE_DEBUG_OUTPUT )
447
  uint64_t value_64bit                   = 0;
448
#endif
449
450
805
  if( container_key_bag == NULL )
451
0
  {
452
0
    libcerror_error_set(
453
0
     error,
454
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
455
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
456
0
     "%s: invalid container key bag.",
457
0
     function );
458
459
0
    return( -1 );
460
0
  }
461
805
  if( data == NULL )
462
0
  {
463
0
    libcerror_error_set(
464
0
     error,
465
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
466
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
467
0
     "%s: invalid data.",
468
0
     function );
469
470
0
    return( -1 );
471
0
  }
472
805
  if( ( data_size < sizeof( fsapfs_object_t ) )
473
805
   || ( data_size > (size_t) SSIZE_MAX ) )
474
0
  {
475
0
    libcerror_error_set(
476
0
     error,
477
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
478
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
479
0
     "%s: invalid data size value out of bounds.",
480
0
     function );
481
482
0
    return( -1 );
483
0
  }
484
#if defined( HAVE_DEBUG_OUTPUT )
485
  if( libcnotify_verbose != 0 )
486
  {
487
    libcnotify_printf(
488
     "%s: container key bag object data:\n",
489
     function );
490
    libcnotify_print_data(
491
     data,
492
     sizeof( fsapfs_object_t ),
493
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
494
  }
495
#endif
496
805
  byte_stream_copy_to_uint64_little_endian(
497
805
   ( (fsapfs_object_t *) data )->checksum,
498
805
   stored_checksum );
499
500
805
  byte_stream_copy_to_uint32_little_endian(
501
805
   ( (fsapfs_object_t *) data )->type,
502
805
   object_type );
503
504
805
  if( object_type != 0x6b657973UL )
505
805
  {
506
#if defined( HAVE_DEBUG_OUTPUT )
507
    if( libcnotify_verbose != 0 )
508
    {
509
      libcnotify_printf(
510
       "%s: invalid object type: 0x%08" PRIx32 "\n.",
511
       function,
512
       object_type );
513
    }
514
#endif
515
805
    return( 0 );
516
805
  }
517
0
  byte_stream_copy_to_uint32_little_endian(
518
0
   ( (fsapfs_object_t *) data )->subtype,
519
0
   object_subtype );
520
521
0
  if( object_subtype != 0x00000000UL )
522
0
  {
523
0
    libcerror_error_set(
524
0
     error,
525
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
526
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
527
0
     "%s: invalid object subtype: 0x%08" PRIx32 ".",
528
0
     function,
529
0
     object_subtype );
530
531
0
    goto on_error;
532
0
  }
533
#if defined( HAVE_DEBUG_OUTPUT )
534
  if( libcnotify_verbose != 0 )
535
  {
536
    libcnotify_printf(
537
     "%s: object checksum\t\t\t: 0x%08" PRIx64 "\n",
538
     function,
539
     stored_checksum );
540
541
    byte_stream_copy_to_uint64_little_endian(
542
     ( (fsapfs_object_t *) data )->identifier,
543
     value_64bit );
544
    libcnotify_printf(
545
     "%s: object identifier\t\t: %" PRIu64 "\n",
546
     function,
547
     value_64bit );
548
549
    byte_stream_copy_to_uint64_little_endian(
550
     ( (fsapfs_object_t *) data )->transaction_identifier,
551
     value_64bit );
552
    libcnotify_printf(
553
     "%s: object transaction identifier\t: %" PRIu64 "\n",
554
     function,
555
     value_64bit );
556
557
    libcnotify_printf(
558
     "%s: object type\t\t\t: 0x%08" PRIx32 "\n",
559
     function,
560
     object_type );
561
562
    libcnotify_printf(
563
     "%s: object subtype\t\t\t: 0x%08" PRIx32 "\n",
564
     function,
565
     object_subtype );
566
567
    libcnotify_printf(
568
     "\n" );
569
  }
570
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
571
572
0
  if( libfsapfs_checksum_calculate_fletcher64(
573
0
       &calculated_checksum,
574
0
       &( data[ 8 ] ),
575
0
       data_size - 8,
576
0
       0,
577
0
       error ) != 1 )
578
0
  {
579
0
    libcerror_error_set(
580
0
     error,
581
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
582
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
583
0
     "%s: unable to calculate Fletcher-64 checksum.",
584
0
     function );
585
586
0
    return( -1 );
587
0
  }
588
0
  if( stored_checksum != calculated_checksum )
589
0
  {
590
0
    libcerror_error_set(
591
0
     error,
592
0
     LIBCERROR_ERROR_DOMAIN_INPUT,
593
0
     LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
594
0
     "%s: mismatch in checksum ( 0x%08" PRIx64 " != 0x%08" PRIx64 " ).\n",
595
0
     function,
596
0
     stored_checksum,
597
0
     calculated_checksum );
598
599
0
    return( -1 );
600
0
  }
601
0
  data_offset = sizeof( fsapfs_object_t );
602
603
0
  if( libfsapfs_key_bag_header_initialize(
604
0
       &bag_header,
605
0
       error ) != 1 )
606
0
  {
607
0
    libcerror_error_set(
608
0
     error,
609
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
610
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
611
0
     "%s: unable to create key bag header.",
612
0
     function );
613
614
0
    goto on_error;
615
0
  }
616
0
  if( libfsapfs_key_bag_header_read_data(
617
0
       bag_header,
618
0
       &( data[ data_offset ] ),
619
0
       data_size - data_offset,
620
0
       error ) != 1 )
621
0
  {
622
0
    libcerror_error_set(
623
0
     error,
624
0
     LIBCERROR_ERROR_DOMAIN_IO,
625
0
     LIBCERROR_IO_ERROR_READ_FAILED,
626
0
     "%s: unable to read key bag header.",
627
0
     function );
628
629
0
    goto on_error;
630
0
  }
631
0
  if( (size_t) bag_header->data_size > ( data_size - data_offset ) )
632
0
  {
633
0
    libcerror_error_set(
634
0
     error,
635
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
636
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
637
0
     "%s: invalid key bag header data size value out of bounds.",
638
0
     function );
639
640
0
    goto on_error;
641
0
  }
642
/* TODO bounds check number of entries ? */
643
644
0
  data_offset += 16;
645
646
0
  for( bag_entry_index = 0;
647
0
       bag_entry_index < bag_header->number_of_entries;
648
0
       bag_entry_index++ )
649
0
  {
650
0
    if( libfsapfs_key_bag_entry_initialize(
651
0
         &bag_entry,
652
0
         error ) != 1 )
653
0
    {
654
0
      libcerror_error_set(
655
0
       error,
656
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
657
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
658
0
       "%s: unable to create key bag entry: %" PRIu16 ".",
659
0
       function,
660
0
       bag_entry_index );
661
662
0
      goto on_error;
663
0
    }
664
0
    if( libfsapfs_key_bag_entry_read_data(
665
0
         bag_entry,
666
0
         &( data[ data_offset ] ),
667
0
         data_size - data_offset,
668
0
         error ) != 1 )
669
0
    {
670
0
      libcerror_error_set(
671
0
       error,
672
0
       LIBCERROR_ERROR_DOMAIN_IO,
673
0
       LIBCERROR_IO_ERROR_READ_FAILED,
674
0
       "%s: unable to read key bag entry: %" PRIu16 ".",
675
0
       function,
676
0
       bag_entry_index );
677
678
0
      goto on_error;
679
0
    }
680
0
    if( libcdata_array_append_entry(
681
0
         container_key_bag->entries_array,
682
0
         &entry_index,
683
0
         (intptr_t *) bag_entry,
684
0
         error ) != 1 )
685
0
    {
686
0
      libcerror_error_set(
687
0
       error,
688
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
689
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
690
0
       "%s: unable to append bag entry: %" PRIu32 " to array.",
691
0
       function,
692
0
       bag_entry_index );
693
694
0
      goto on_error;
695
0
    }
696
0
    data_offset += bag_entry->size;
697
698
0
    bag_entry = NULL;
699
700
0
    alignment_padding_size = data_offset % 16;
701
702
0
    if( alignment_padding_size != 0 )
703
0
    {
704
0
      alignment_padding_size = 16 - alignment_padding_size;
705
706
0
      if( ( alignment_padding_size > data_size )
707
0
       || ( data_offset > ( data_size - alignment_padding_size ) ) )
708
0
      {
709
0
        libcerror_error_set(
710
0
         error,
711
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
712
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
713
0
         "%s: invalid data size value out of bounds.",
714
0
         function );
715
716
0
        goto on_error;
717
0
      }
718
#if defined( HAVE_DEBUG_OUTPUT )
719
      if( libcnotify_verbose != 0 )
720
      {
721
        libcnotify_printf(
722
         "%s: alignment padding data:\n",
723
         function );
724
        libcnotify_print_data(
725
         &( data[ data_offset ] ),
726
         alignment_padding_size,
727
         LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
728
      }
729
#endif
730
0
      data_offset += alignment_padding_size;
731
0
    }
732
0
  }
733
0
  if( libfsapfs_key_bag_header_free(
734
0
       &bag_header,
735
0
       error ) != 1 )
736
0
  {
737
0
    libcerror_error_set(
738
0
     error,
739
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
740
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
741
0
     "%s: unable to free key bag header.",
742
0
     function );
743
744
0
    goto on_error;
745
0
  }
746
0
  return( 1 );
747
748
0
on_error:
749
0
  if( bag_entry != NULL )
750
0
  {
751
0
    libfsapfs_key_bag_entry_free(
752
0
     &bag_entry,
753
0
     NULL );
754
0
  }
755
0
  if( bag_header != NULL )
756
0
  {
757
0
    libfsapfs_key_bag_header_free(
758
0
     &bag_header,
759
0
     NULL );
760
0
  }
761
0
  return( -1 );
762
0
}
763
764
/* Retrieves the volume key extent for a specific volume
765
 * Returns 1 if successful, 0 if no such volume or -1 on error
766
 */
767
int libfsapfs_container_key_bag_get_volume_key_bag_extent_by_identifier(
768
     libfsapfs_container_key_bag_t *container_key_bag,
769
     const uint8_t *volume_identifier,
770
     uint64_t *volume_key_bag_block_number,
771
     uint64_t *volume_key_bag_number_of_blocks,
772
     libcerror_error_t **error )
773
0
{
774
0
  libfsapfs_key_bag_entry_t *bag_entry = NULL;
775
0
  static char *function                = "libfsapfs_container_key_bag_get_volume_key_bag_extent_by_identifier";
776
0
  uint64_t block_number                = 0;
777
0
  uint64_t number_of_blocks            = 0;
778
0
  int entry_index                      = 0;
779
0
  int number_of_entries                = 0;
780
781
0
  if( container_key_bag == NULL )
782
0
  {
783
0
    libcerror_error_set(
784
0
     error,
785
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
786
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
787
0
     "%s: invalid container key bag.",
788
0
     function );
789
790
0
    return( -1 );
791
0
  }
792
0
  if( volume_identifier == 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: invalid volume identifier.",
799
0
     function );
800
801
0
    return( -1 );
802
0
  }
803
0
  if( volume_key_bag_block_number == NULL )
804
0
  {
805
0
    libcerror_error_set(
806
0
     error,
807
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
808
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
809
0
     "%s: invalid volume key bag block number.",
810
0
     function );
811
812
0
    return( -1 );
813
0
  }
814
0
  if( volume_key_bag_number_of_blocks == NULL )
815
0
  {
816
0
    libcerror_error_set(
817
0
     error,
818
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
819
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
820
0
     "%s: invalid volume key bag number of blocks.",
821
0
     function );
822
823
0
    return( -1 );
824
0
  }
825
0
  if( libcdata_array_get_number_of_entries(
826
0
       container_key_bag->entries_array,
827
0
       &number_of_entries,
828
0
       error ) != 1 )
829
0
  {
830
0
    libcerror_error_set(
831
0
     error,
832
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
833
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
834
0
     "%s: unable to retrieve number of entries from array.",
835
0
     function );
836
837
0
    return( -1 );
838
0
  }
839
0
  for( entry_index = 0;
840
0
       entry_index < number_of_entries;
841
0
       entry_index++ )
842
0
  {
843
0
    if( libcdata_array_get_entry_by_index(
844
0
         container_key_bag->entries_array,
845
0
         entry_index,
846
0
         (intptr_t **) &bag_entry,
847
0
         error ) != 1 )
848
0
    {
849
0
      libcerror_error_set(
850
0
       error,
851
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
852
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
853
0
       "%s: unable to retrieve entry: %d from array.",
854
0
       function,
855
0
       entry_index );
856
857
0
      return( -1 );
858
0
    }
859
0
    if( bag_entry == NULL )
860
0
    {
861
0
      libcerror_error_set(
862
0
       error,
863
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
864
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
865
0
       "%s: missing entry: %d.",
866
0
       function,
867
0
       entry_index );
868
869
0
      return( -1 );
870
0
    }
871
0
    if( bag_entry->type != 3 )
872
0
    {
873
0
      continue;
874
0
    }
875
0
    if( memory_compare(
876
0
         bag_entry->identifier,
877
0
         volume_identifier,
878
0
         16 ) != 0 )
879
0
    {
880
0
      continue;
881
0
    }
882
0
    if( bag_entry->data == NULL )
883
0
    {
884
0
      libcerror_error_set(
885
0
       error,
886
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
887
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
888
0
       "%s: invalid entry: %d - missing data.",
889
0
       function,
890
0
       entry_index );
891
892
0
      return( -1 );
893
0
    }
894
0
    if( bag_entry->data_size != 16 )
895
0
    {
896
0
      libcerror_error_set(
897
0
       error,
898
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
899
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
900
0
       "%s: invalid entry: %d - unsupported data size.",
901
0
       function,
902
0
       entry_index );
903
904
0
      return( -1 );
905
0
    }
906
0
    byte_stream_copy_to_uint64_little_endian(
907
0
     ( (fsapfs_key_bag_extent_t * ) bag_entry->data )->block_number,
908
0
     block_number );
909
910
0
    byte_stream_copy_to_uint64_little_endian(
911
0
     ( (fsapfs_key_bag_extent_t * ) bag_entry->data )->number_of_blocks,
912
0
     number_of_blocks );
913
914
#if defined( HAVE_DEBUG_OUTPUT )
915
    if( libcnotify_verbose != 0 )
916
    {
917
      libcnotify_printf(
918
       "%s: key bag extent block number\t: %" PRIu64 "\n",
919
       function,
920
       block_number );
921
922
      libcnotify_printf(
923
       "%s: key bag extent number of blocks\t: %" PRIu64 "\n",
924
       function,
925
       number_of_blocks );
926
927
      libcnotify_printf(
928
       "\n" );
929
    }
930
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
931
932
0
    *volume_key_bag_block_number     = block_number;
933
0
    *volume_key_bag_number_of_blocks = number_of_blocks;
934
935
0
    return( 1 );
936
0
  }
937
0
  return( 0 );
938
0
}
939
940
/* Retrieves the volume master key for a specific volume
941
 * Returns 1 if successful, 0 if no such volume or -1 on error
942
 */
943
int libfsapfs_container_key_bag_get_volume_master_key_by_identifier(
944
     libfsapfs_container_key_bag_t *container_key_bag,
945
     const uint8_t *volume_identifier,
946
     const uint8_t *volume_key,
947
     size_t volume_key_size,
948
     uint8_t *key,
949
     size_t key_size,
950
     libcerror_error_t **error )
951
0
{
952
0
  libfsapfs_key_bag_entry_t *bag_entry             = NULL;
953
0
  libfsapfs_key_encrypted_key_t *key_encrypted_key = NULL;
954
0
  static char *function                            = "libfsapfs_container_key_bag_get_volume_master_key_by_identifier";
955
0
  int entry_index                                  = 0;
956
0
  int number_of_entries                            = 0;
957
0
  int result                                       = 0;
958
959
0
  if( container_key_bag == NULL )
960
0
  {
961
0
    libcerror_error_set(
962
0
     error,
963
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
964
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
965
0
     "%s: invalid container key bag.",
966
0
     function );
967
968
0
    return( -1 );
969
0
  }
970
0
  if( volume_identifier == NULL )
971
0
  {
972
0
    libcerror_error_set(
973
0
     error,
974
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
975
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
976
0
     "%s: invalid volume identifier.",
977
0
     function );
978
979
0
    return( -1 );
980
0
  }
981
0
  if( libcdata_array_get_number_of_entries(
982
0
       container_key_bag->entries_array,
983
0
       &number_of_entries,
984
0
       error ) != 1 )
985
0
  {
986
0
    libcerror_error_set(
987
0
     error,
988
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
989
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
990
0
     "%s: unable to retrieve number of entries from array.",
991
0
     function );
992
993
0
    goto on_error;
994
0
  }
995
0
  for( entry_index = 0;
996
0
       entry_index < number_of_entries;
997
0
       entry_index++ )
998
0
  {
999
0
    if( libcdata_array_get_entry_by_index(
1000
0
         container_key_bag->entries_array,
1001
0
         entry_index,
1002
0
         (intptr_t **) &bag_entry,
1003
0
         error ) != 1 )
1004
0
    {
1005
0
      libcerror_error_set(
1006
0
       error,
1007
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1008
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1009
0
       "%s: unable to retrieve entry: %d from array.",
1010
0
       function,
1011
0
       entry_index );
1012
1013
0
      goto on_error;
1014
0
    }
1015
0
    if( bag_entry == NULL )
1016
0
    {
1017
0
      libcerror_error_set(
1018
0
       error,
1019
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1020
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1021
0
       "%s: missing entry: %d.",
1022
0
       function,
1023
0
       entry_index );
1024
1025
0
      goto on_error;
1026
0
    }
1027
0
    if( bag_entry->type != 2 )
1028
0
    {
1029
0
      continue;
1030
0
    }
1031
0
    if( memory_compare(
1032
0
         bag_entry->identifier,
1033
0
         volume_identifier,
1034
0
         16 ) != 0 )
1035
0
    {
1036
0
      continue;
1037
0
    }
1038
0
    if( libfsapfs_key_encrypted_key_initialize(
1039
0
         &key_encrypted_key,
1040
0
         error ) != 1 )
1041
0
    {
1042
0
      libcerror_error_set(
1043
0
       error,
1044
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1045
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1046
0
       "%s: unable to create key encrypted key.",
1047
0
       function );
1048
1049
0
      goto on_error;
1050
0
    }
1051
0
    if( libfsapfs_key_encrypted_key_read_data(
1052
0
         key_encrypted_key,
1053
0
         bag_entry->data,
1054
0
         (size_t) bag_entry->data_size,
1055
0
         error ) != 1 )
1056
0
    {
1057
0
      libcerror_error_set(
1058
0
       error,
1059
0
       LIBCERROR_ERROR_DOMAIN_IO,
1060
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1061
0
       "%s: unable to read key encrypted key.",
1062
0
       function );
1063
1064
0
      goto on_error;
1065
0
    }
1066
0
    result = libfsapfs_key_encrypted_key_unlock_with_key(
1067
0
             key_encrypted_key,
1068
0
             volume_key,
1069
0
             volume_key_size,
1070
0
             key,
1071
0
             key_size,
1072
0
             error );
1073
1074
0
    if( result == -1 )
1075
0
    {
1076
0
      libcerror_error_set(
1077
0
       error,
1078
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1079
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1080
0
       "%s: unable to unlock key encrypted key with volume key.",
1081
0
       function );
1082
1083
0
      goto on_error;
1084
0
    }
1085
0
    if( libfsapfs_key_encrypted_key_free(
1086
0
         &key_encrypted_key,
1087
0
         error ) != 1 )
1088
0
    {
1089
0
      libcerror_error_set(
1090
0
       error,
1091
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1092
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1093
0
       "%s: unable to free key encrypted key.",
1094
0
       function );
1095
1096
0
      goto on_error;
1097
0
    }
1098
0
    if( result == 1 )
1099
0
    {
1100
0
      break;
1101
0
    }
1102
0
  }
1103
0
  return( result );
1104
1105
0
on_error:
1106
0
  if( key_encrypted_key != NULL )
1107
0
  {
1108
0
    libfsapfs_key_encrypted_key_free(
1109
0
     &key_encrypted_key,
1110
0
     NULL );
1111
0
  }
1112
0
  return( -1 );
1113
0
}
1114