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