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