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