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