1 /*
2  * Volume functions
3  *
4  * Copyright (C) 2013-2020, 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 <memory.h>
24 #include <narrow_string.h>
25 #include <types.h>
26 #include <wide_string.h>
27 
28 #include "libluksde_codepage.h"
29 #include "libluksde_debug.h"
30 #include "libluksde_definitions.h"
31 #include "libluksde_diffuser.h"
32 #include "libluksde_io_handle.h"
33 #include "libluksde_key_slot.h"
34 #include "libluksde_libbfio.h"
35 #include "libluksde_libcerror.h"
36 #include "libluksde_libcnotify.h"
37 #include "libluksde_libcthreads.h"
38 #include "libluksde_libfcache.h"
39 #include "libluksde_libfdata.h"
40 #include "libluksde_libhmac.h"
41 #include "libluksde_libuna.h"
42 #include "libluksde_password.h"
43 #include "libluksde_sector_data.h"
44 #include "libluksde_volume.h"
45 #include "libluksde_volume_header.h"
46 
47 /* Creates a volume
48  * Make sure the value volume is referencing, is set to NULL
49  * Returns 1 if successful or -1 on error
50  */
libluksde_volume_initialize(libluksde_volume_t ** volume,libcerror_error_t ** error)51 int libluksde_volume_initialize(
52      libluksde_volume_t **volume,
53      libcerror_error_t **error )
54 {
55 	libluksde_internal_volume_t *internal_volume = NULL;
56 	static char *function                        = "libluksde_volume_initialize";
57 
58 	if( volume == NULL )
59 	{
60 		libcerror_error_set(
61 		 error,
62 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
63 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
64 		 "%s: invalid volume.",
65 		 function );
66 
67 		return( -1 );
68 	}
69 	if( *volume != NULL )
70 	{
71 		libcerror_error_set(
72 		 error,
73 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
74 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
75 		 "%s: invalid volume value already set.",
76 		 function );
77 
78 		return( -1 );
79 	}
80 	internal_volume = memory_allocate_structure(
81 	                   libluksde_internal_volume_t );
82 
83 	if( internal_volume == NULL )
84 	{
85 		libcerror_error_set(
86 		 error,
87 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
88 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
89 		 "%s: unable to create volume.",
90 		 function );
91 
92 		goto on_error;
93 	}
94 	if( memory_set(
95 	     internal_volume,
96 	     0,
97 	     sizeof( libluksde_internal_volume_t ) ) == NULL )
98 	{
99 		libcerror_error_set(
100 		 error,
101 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
102 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
103 		 "%s: unable to clear volume.",
104 		 function );
105 
106 		memory_free(
107 		 internal_volume );
108 
109 		return( -1 );
110 	}
111 	if( libluksde_io_handle_initialize(
112 	     &( internal_volume->io_handle ),
113 	     error ) != 1 )
114 	{
115 		libcerror_error_set(
116 		 error,
117 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
118 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
119 		 "%s: unable to create IO handle.",
120 		 function );
121 
122 		goto on_error;
123 	}
124 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
125 	if( libcthreads_read_write_lock_initialize(
126 	     &( internal_volume->read_write_lock ),
127 	     error ) != 1 )
128 	{
129 		libcerror_error_set(
130 		 error,
131 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
132 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
133 		 "%s: unable to initialize read/write lock.",
134 		 function );
135 
136 		goto on_error;
137 	}
138 #endif
139 	internal_volume->is_locked = 1;
140 
141 	*volume = (libluksde_volume_t *) internal_volume;
142 
143 	return( 1 );
144 
145 on_error:
146 	if( internal_volume != NULL )
147 	{
148 		if( internal_volume->io_handle != NULL )
149 		{
150 			libluksde_io_handle_free(
151 			 &( internal_volume->io_handle ),
152 			 NULL );
153 		}
154 		memory_free(
155 		 internal_volume );
156 	}
157 	return( -1 );
158 }
159 
160 /* Frees a volume
161  * Returns 1 if successful or -1 on error
162  */
libluksde_volume_free(libluksde_volume_t ** volume,libcerror_error_t ** error)163 int libluksde_volume_free(
164      libluksde_volume_t **volume,
165      libcerror_error_t **error )
166 {
167 	libluksde_internal_volume_t *internal_volume = NULL;
168 	static char *function                        = "libluksde_volume_free";
169 	int result                                   = 1;
170 
171 	if( volume == NULL )
172 	{
173 		libcerror_error_set(
174 		 error,
175 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
176 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
177 		 "%s: invalid volume.",
178 		 function );
179 
180 		return( -1 );
181 	}
182 	if( *volume != NULL )
183 	{
184 		internal_volume = (libluksde_internal_volume_t *) *volume;
185 
186 		if( internal_volume->file_io_handle != NULL )
187 		{
188 			if( libluksde_volume_close(
189 			     *volume,
190 			     error ) != 0 )
191 			{
192 				libcerror_error_set(
193 				 error,
194 				 LIBCERROR_ERROR_DOMAIN_IO,
195 				 LIBCERROR_IO_ERROR_CLOSE_FAILED,
196 				 "%s: unable to close volume.",
197 				 function );
198 
199 				result = -1;
200 			}
201 		}
202 		*volume = NULL;
203 
204 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
205 		if( libcthreads_read_write_lock_free(
206 		     &( internal_volume->read_write_lock ),
207 		     error ) != 1 )
208 		{
209 			libcerror_error_set(
210 			 error,
211 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
212 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
213 			 "%s: unable to free read/write lock.",
214 			 function );
215 
216 			result = -1;
217 		}
218 #endif
219 		if( libluksde_io_handle_free(
220 		     &( internal_volume->io_handle ),
221 		     error ) != 1 )
222 		{
223 			libcerror_error_set(
224 			 error,
225 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
226 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
227 			 "%s: unable to free IO handle.",
228 			 function );
229 
230 			result = -1;
231 		}
232 		if( internal_volume->user_password != NULL )
233 		{
234 			if( memory_set(
235 			     internal_volume->user_password,
236 			     0,
237 			     internal_volume->user_password_size ) == NULL )
238 			{
239 				libcerror_error_set(
240 				 error,
241 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
242 				 LIBCERROR_MEMORY_ERROR_SET_FAILED,
243 				 "%s: unable to clear user password.",
244 				 function );
245 
246 				result = -1;
247 			}
248 			memory_free(
249 			 internal_volume->user_password );
250 		}
251 		memory_free(
252 		 internal_volume );
253 	}
254 	return( result );
255 }
256 
257 /* Signals the volume to abort its current activity
258  * Returns 1 if successful or -1 on error
259  */
libluksde_volume_signal_abort(libluksde_volume_t * volume,libcerror_error_t ** error)260 int libluksde_volume_signal_abort(
261      libluksde_volume_t *volume,
262      libcerror_error_t **error )
263 {
264 	libluksde_internal_volume_t *internal_volume = NULL;
265 	static char *function                        = "libluksde_volume_signal_abort";
266 
267 	if( volume == NULL )
268 	{
269 		libcerror_error_set(
270 		 error,
271 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
272 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
273 		 "%s: invalid volume.",
274 		 function );
275 
276 		return( -1 );
277 	}
278 	internal_volume = (libluksde_internal_volume_t *) volume;
279 
280 	if( internal_volume->io_handle == NULL )
281 	{
282 		libcerror_error_set(
283 		 error,
284 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
285 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
286 		 "%s: invalid volume - missing IO handle.",
287 		 function );
288 
289 		return( -1 );
290 	}
291 	internal_volume->io_handle->abort = 1;
292 
293 	return( 1 );
294 }
295 
296 /* Opens a volume
297  * Returns 1 if successful, 0 if the keys could not be read or -1 on error
298  */
libluksde_volume_open(libluksde_volume_t * volume,const char * filename,int access_flags,libcerror_error_t ** error)299 int libluksde_volume_open(
300      libluksde_volume_t *volume,
301      const char *filename,
302      int access_flags,
303      libcerror_error_t **error )
304 {
305 	libbfio_handle_t *file_io_handle             = NULL;
306 	libluksde_internal_volume_t *internal_volume = NULL;
307 	static char *function                        = "libluksde_volume_open";
308 	size_t filename_length                       = 0;
309 	int result                                   = 0;
310 
311 	if( volume == NULL )
312 	{
313 		libcerror_error_set(
314 		 error,
315 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
316 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
317 		 "%s: invalid volume.",
318 		 function );
319 
320 		return( -1 );
321 	}
322 	internal_volume = (libluksde_internal_volume_t *) volume;
323 
324 	if( filename == NULL )
325 	{
326 		libcerror_error_set(
327 		 error,
328 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
329 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
330 		 "%s: invalid filename.",
331 		 function );
332 
333 		return( -1 );
334 	}
335 	if( ( ( access_flags & LIBLUKSDE_ACCESS_FLAG_READ ) == 0 )
336 	 && ( ( access_flags & LIBLUKSDE_ACCESS_FLAG_WRITE ) == 0 ) )
337 	{
338 		libcerror_error_set(
339 		 error,
340 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
341 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
342 		 "%s: unsupported access flags.",
343 		 function );
344 
345 		return( -1 );
346 	}
347 	if( ( access_flags & LIBLUKSDE_ACCESS_FLAG_WRITE ) != 0 )
348 	{
349 		libcerror_error_set(
350 		 error,
351 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
352 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
353 		 "%s: write access currently not supported.",
354 		 function );
355 
356 		return( -1 );
357 	}
358 	filename_length = narrow_string_length(
359 	                   filename );
360 
361 	if( filename_length == 0 )
362 	{
363 		libcerror_error_set(
364 		 error,
365 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
366 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
367 		 "%s: invalid filename.",
368 		 function );
369 
370 		goto on_error;
371 	}
372 	if( libbfio_file_initialize(
373 	     &file_io_handle,
374 	     error ) != 1 )
375 	{
376 		libcerror_error_set(
377 		 error,
378 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
379 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
380 		 "%s: unable to create file IO handle.",
381 		 function );
382 
383 		goto on_error;
384 	}
385 #if defined( HAVE_DEBUG_OUTPUT )
386 	if( libbfio_handle_set_track_offsets_read(
387 	     file_io_handle,
388 	     1,
389 	     error ) != 1 )
390 	{
391                 libcerror_error_set(
392                  error,
393                  LIBCERROR_ERROR_DOMAIN_RUNTIME,
394                  LIBCERROR_RUNTIME_ERROR_SET_FAILED,
395                  "%s: unable to set track offsets read in file IO handle.",
396                  function );
397 
398 		goto on_error;
399 	}
400 #endif
401 	if( libbfio_file_set_name(
402 	     file_io_handle,
403 	     filename,
404 	     filename_length,
405 	     error ) != 1 )
406 	{
407                 libcerror_error_set(
408                  error,
409                  LIBCERROR_ERROR_DOMAIN_RUNTIME,
410                  LIBCERROR_RUNTIME_ERROR_SET_FAILED,
411                  "%s: unable to set filename in file IO handle.",
412                  function );
413 
414 		goto on_error;
415 	}
416 	result = libluksde_volume_open_file_io_handle(
417 	          volume,
418 	          file_io_handle,
419 	          access_flags,
420 	          error );
421 
422 	if( result == -1 )
423 	{
424 		libcerror_error_set(
425 		 error,
426 		 LIBCERROR_ERROR_DOMAIN_IO,
427 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
428 		 "%s: unable to open volume: %s.",
429 		 function,
430 		 filename );
431 
432 		goto on_error;
433 	}
434 	else
435 	{
436 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
437 		if( libcthreads_read_write_lock_grab_for_write(
438 		     internal_volume->read_write_lock,
439 		     error ) != 1 )
440 		{
441 			libcerror_error_set(
442 			 error,
443 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
444 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
445 			 "%s: unable to grab read/write lock for writing.",
446 			 function );
447 
448 			return( -1 );
449 		}
450 #endif
451 		internal_volume->file_io_handle_created_in_library = 1;
452 
453 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
454 		if( libcthreads_read_write_lock_release_for_write(
455 		     internal_volume->read_write_lock,
456 		     error ) != 1 )
457 		{
458 			libcerror_error_set(
459 			 error,
460 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
461 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
462 			 "%s: unable to release read/write lock for writing.",
463 			 function );
464 
465 			return( -1 );
466 		}
467 #endif
468 	}
469 	return( result );
470 
471 on_error:
472 	if( file_io_handle != NULL )
473 	{
474 		libbfio_handle_free(
475 		 &file_io_handle,
476 		 NULL );
477 	}
478         return( -1 );
479 }
480 
481 #if defined( HAVE_WIDE_CHARACTER_TYPE )
482 
483 /* Opens a volume
484  * Returns 1 if successful, 0 if the keys could not be read or -1 on error
485  */
libluksde_volume_open_wide(libluksde_volume_t * volume,const wchar_t * filename,int access_flags,libcerror_error_t ** error)486 int libluksde_volume_open_wide(
487      libluksde_volume_t *volume,
488      const wchar_t *filename,
489      int access_flags,
490      libcerror_error_t **error )
491 {
492 	libbfio_handle_t *file_io_handle             = NULL;
493 	libluksde_internal_volume_t *internal_volume = NULL;
494 	static char *function                        = "libluksde_volume_open_wide";
495 	size_t filename_length                       = 0;
496 	int result                                   = 0;
497 
498 	if( volume == NULL )
499 	{
500 		libcerror_error_set(
501 		 error,
502 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
503 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
504 		 "%s: invalid volume.",
505 		 function );
506 
507 		return( -1 );
508 	}
509 	internal_volume = (libluksde_internal_volume_t *) volume;
510 
511 	if( filename == NULL )
512 	{
513 		libcerror_error_set(
514 		 error,
515 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
516 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
517 		 "%s: invalid filename.",
518 		 function );
519 
520 		return( -1 );
521 	}
522 	if( ( ( access_flags & LIBLUKSDE_ACCESS_FLAG_READ ) == 0 )
523 	 && ( ( access_flags & LIBLUKSDE_ACCESS_FLAG_WRITE ) == 0 ) )
524 	{
525 		libcerror_error_set(
526 		 error,
527 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
528 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
529 		 "%s: unsupported access flags.",
530 		 function );
531 
532 		return( -1 );
533 	}
534 	if( ( access_flags & LIBLUKSDE_ACCESS_FLAG_WRITE ) != 0 )
535 	{
536 		libcerror_error_set(
537 		 error,
538 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
539 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
540 		 "%s: write access currently not supported.",
541 		 function );
542 
543 		return( -1 );
544 	}
545 	filename_length = wide_string_length(
546 	                   filename );
547 
548 	if( filename_length == 0 )
549 	{
550 		libcerror_error_set(
551 		 error,
552 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
553 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
554 		 "%s: invalid filename.",
555 		 function );
556 
557 		goto on_error;
558 	}
559 	if( libbfio_file_initialize(
560 	     &file_io_handle,
561 	     error ) != 1 )
562 	{
563 		libcerror_error_set(
564 		 error,
565 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
566 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
567 		 "%s: unable to create file IO handle.",
568 		 function );
569 
570 		goto on_error;
571 	}
572 #if defined( HAVE_DEBUG_OUTPUT )
573 	if( libbfio_handle_set_track_offsets_read(
574 	     file_io_handle,
575 	     1,
576 	     error ) != 1 )
577 	{
578                 libcerror_error_set(
579                  error,
580                  LIBCERROR_ERROR_DOMAIN_RUNTIME,
581                  LIBCERROR_RUNTIME_ERROR_SET_FAILED,
582                  "%s: unable to set track offsets read in file IO handle.",
583                  function );
584 
585 		goto on_error;
586 	}
587 #endif
588 	if( libbfio_file_set_name_wide(
589 	     file_io_handle,
590 	     filename,
591 	     filename_length,
592 	     error ) != 1 )
593 	{
594                 libcerror_error_set(
595                  error,
596                  LIBCERROR_ERROR_DOMAIN_RUNTIME,
597                  LIBCERROR_RUNTIME_ERROR_SET_FAILED,
598                  "%s: unable to set filename in file IO handle.",
599                  function );
600 
601 		goto on_error;
602 	}
603 	result = libluksde_volume_open_file_io_handle(
604 	          volume,
605 	          file_io_handle,
606 	          access_flags,
607 	          error );
608 
609 	if( result == -1 )
610 	{
611 		libcerror_error_set(
612 		 error,
613 		 LIBCERROR_ERROR_DOMAIN_IO,
614 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
615 		 "%s: unable to open volume: %ls.",
616 		 function,
617 		 filename );
618 
619 		goto on_error;
620 	}
621 	else
622 	{
623 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
624 		if( libcthreads_read_write_lock_grab_for_write(
625 		     internal_volume->read_write_lock,
626 		     error ) != 1 )
627 		{
628 			libcerror_error_set(
629 			 error,
630 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
631 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
632 			 "%s: unable to grab read/write lock for writing.",
633 			 function );
634 
635 			return( -1 );
636 		}
637 #endif
638 		internal_volume->file_io_handle_created_in_library = 1;
639 
640 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
641 		if( libcthreads_read_write_lock_release_for_write(
642 		     internal_volume->read_write_lock,
643 		     error ) != 1 )
644 		{
645 			libcerror_error_set(
646 			 error,
647 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
648 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
649 			 "%s: unable to release read/write lock for writing.",
650 			 function );
651 
652 			return( -1 );
653 		}
654 #endif
655 	}
656 	return( result );
657 
658 on_error:
659 	if( file_io_handle != NULL )
660 	{
661 		libbfio_handle_free(
662 		 &file_io_handle,
663 		 NULL );
664 	}
665         return( -1 );
666 }
667 
668 #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
669 
670 /* Opens a volume using a Basic File IO (bfio) handle
671  * Returns 1 if successful, 0 if the keys could not be read or -1 on error
672  */
libluksde_volume_open_file_io_handle(libluksde_volume_t * volume,libbfio_handle_t * file_io_handle,int access_flags,libcerror_error_t ** error)673 int libluksde_volume_open_file_io_handle(
674      libluksde_volume_t *volume,
675      libbfio_handle_t *file_io_handle,
676      int access_flags,
677      libcerror_error_t **error )
678 {
679 	libluksde_internal_volume_t *internal_volume = NULL;
680 	static char *function                        = "libluksde_volume_open_file_io_handle";
681 	int bfio_access_flags                        = 0;
682 	int file_io_handle_is_open                   = 0;
683 	int file_io_handle_opened_in_library         = 0;
684 	int result                                   = 0;
685 
686 	if( volume == NULL )
687 	{
688 		libcerror_error_set(
689 		 error,
690 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
691 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
692 		 "%s: invalid volume.",
693 		 function );
694 
695 		return( -1 );
696 	}
697 	internal_volume = (libluksde_internal_volume_t *) volume;
698 
699 	if( internal_volume->file_io_handle != NULL )
700 	{
701 		libcerror_error_set(
702 		 error,
703 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
704 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
705 		 "%s: invalid volume - file IO handle already set.",
706 		 function );
707 
708 		return( -1 );
709 	}
710 	if( file_io_handle == NULL )
711 	{
712 		libcerror_error_set(
713 		 error,
714 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
715 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
716 		 "%s: invalid file IO handle.",
717 		 function );
718 
719 		return( -1 );
720 	}
721 	if( ( ( access_flags & LIBLUKSDE_ACCESS_FLAG_READ ) == 0 )
722 	 && ( ( access_flags & LIBLUKSDE_ACCESS_FLAG_WRITE ) == 0 ) )
723 	{
724 		libcerror_error_set(
725 		 error,
726 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
727 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
728 		 "%s: unsupported access flags.",
729 		 function );
730 
731 		return( -1 );
732 	}
733 	if( ( access_flags & LIBLUKSDE_ACCESS_FLAG_WRITE ) != 0 )
734 	{
735 		libcerror_error_set(
736 		 error,
737 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
738 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
739 		 "%s: write access currently not supported.",
740 		 function );
741 
742 		return( -1 );
743 	}
744 	if( ( access_flags & LIBLUKSDE_ACCESS_FLAG_READ ) != 0 )
745 	{
746 		bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
747 	}
748 	file_io_handle_is_open = libbfio_handle_is_open(
749 	                          file_io_handle,
750 	                          error );
751 
752 	if( file_io_handle_is_open == -1 )
753 	{
754 		libcerror_error_set(
755 		 error,
756 		 LIBCERROR_ERROR_DOMAIN_IO,
757 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
758 		 "%s: unable to determine if file IO handle is open.",
759 		 function );
760 
761 		goto on_error;
762 	}
763 	else if( file_io_handle_is_open == 0 )
764 	{
765 		if( libbfio_handle_open(
766 		     file_io_handle,
767 		     bfio_access_flags,
768 		     error ) != 1 )
769 		{
770 			libcerror_error_set(
771 			 error,
772 			 LIBCERROR_ERROR_DOMAIN_IO,
773 			 LIBCERROR_IO_ERROR_OPEN_FAILED,
774 			 "%s: unable to open file IO handle.",
775 			 function );
776 
777 			goto on_error;
778 		}
779 		file_io_handle_opened_in_library = 1;
780 	}
781 	result = libluksde_volume_open_read(
782 	          internal_volume,
783 	          file_io_handle,
784 	          error );
785 
786 	if( result == -1 )
787 	{
788 		libcerror_error_set(
789 		 error,
790 		 LIBCERROR_ERROR_DOMAIN_IO,
791 		 LIBCERROR_IO_ERROR_READ_FAILED,
792 		 "%s: unable to read from volume handle.",
793 		 function );
794 
795 		goto on_error;
796 	}
797 	else
798 	{
799 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
800 		if( libcthreads_read_write_lock_grab_for_write(
801 		     internal_volume->read_write_lock,
802 		     error ) != 1 )
803 		{
804 			libcerror_error_set(
805 			 error,
806 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
807 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
808 			 "%s: unable to grab read/write lock for writing.",
809 			 function );
810 
811 			return( -1 );
812 		}
813 #endif
814 		internal_volume->file_io_handle                   = file_io_handle;
815 		internal_volume->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
816 
817 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
818 		if( libcthreads_read_write_lock_release_for_write(
819 		     internal_volume->read_write_lock,
820 		     error ) != 1 )
821 		{
822 			libcerror_error_set(
823 			 error,
824 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
825 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
826 			 "%s: unable to release read/write lock for writing.",
827 			 function );
828 
829 			return( -1 );
830 		}
831 #endif
832 	}
833 	return( result );
834 
835 on_error:
836 	if( file_io_handle_opened_in_library == 0 )
837 	{
838 		libbfio_handle_close(
839 		 file_io_handle,
840 		 error );
841 	}
842 	return( -1 );
843 }
844 
845 /* Closes a volume
846  * Returns 0 if successful or -1 on error
847  */
libluksde_volume_close(libluksde_volume_t * volume,libcerror_error_t ** error)848 int libluksde_volume_close(
849      libluksde_volume_t *volume,
850      libcerror_error_t **error )
851 {
852 	libluksde_internal_volume_t *internal_volume = NULL;
853 	static char *function                        = "libluksde_volume_close";
854 	int result                                   = 0;
855 
856 	if( volume == NULL )
857 	{
858 		libcerror_error_set(
859 		 error,
860 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
861 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
862 		 "%s: invalid volume.",
863 		 function );
864 
865 		return( -1 );
866 	}
867 	internal_volume = (libluksde_internal_volume_t *) volume;
868 
869 	if( internal_volume->io_handle == NULL )
870 	{
871 		libcerror_error_set(
872 		 error,
873 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
874 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
875 		 "%s: invalid volume - missing IO handle.",
876 		 function );
877 
878 		return( -1 );
879 	}
880 	if( internal_volume->file_io_handle == NULL )
881 	{
882 		libcerror_error_set(
883 		 error,
884 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
885 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
886 		 "%s: invalid volume - missing file IO handle.",
887 		 function );
888 
889 		return( -1 );
890 	}
891 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
892 	if( libcthreads_read_write_lock_grab_for_write(
893 	     internal_volume->read_write_lock,
894 	     error ) != 1 )
895 	{
896 		libcerror_error_set(
897 		 error,
898 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
899 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
900 		 "%s: unable to grab read/write lock for writing.",
901 		 function );
902 
903 		return( -1 );
904 	}
905 #endif
906 #if defined( HAVE_DEBUG_OUTPUT )
907 	if( libcnotify_verbose != 0 )
908 	{
909 		if( internal_volume->file_io_handle_created_in_library != 0 )
910 		{
911 			if( libluksde_debug_print_read_offsets(
912 			     internal_volume->file_io_handle,
913 			     error ) != 1 )
914 			{
915 				libcerror_error_set(
916 				 error,
917 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
918 				 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
919 				 "%s: unable to print the read offsets.",
920 				 function );
921 			}
922 		}
923 	}
924 #endif
925 	if( internal_volume->file_io_handle_opened_in_library != 0 )
926 	{
927 		if( libbfio_handle_close(
928 		     internal_volume->file_io_handle,
929 		     error ) != 0 )
930 		{
931 			libcerror_error_set(
932 			 error,
933 			 LIBCERROR_ERROR_DOMAIN_IO,
934 			 LIBCERROR_IO_ERROR_CLOSE_FAILED,
935 			 "%s: unable to close file IO handle.",
936 			 function );
937 
938 			result = -1;
939 		}
940 		internal_volume->file_io_handle_opened_in_library = 0;
941 	}
942 	if( internal_volume->file_io_handle_created_in_library != 0 )
943 	{
944 		if( libbfio_handle_free(
945 		     &( internal_volume->file_io_handle ),
946 		     error ) != 1 )
947 		{
948 			libcerror_error_set(
949 			 error,
950 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
951 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
952 			 "%s: unable to free file IO handle.",
953 			 function );
954 
955 			result = -1;
956 		}
957 		internal_volume->file_io_handle_created_in_library = 0;
958 	}
959 	internal_volume->file_io_handle = NULL;
960 	internal_volume->current_offset = 0;
961 	internal_volume->is_locked      = 1;
962 
963 	if( libluksde_io_handle_clear(
964 	     internal_volume->io_handle,
965 	     error ) != 1 )
966 	{
967 		libcerror_error_set(
968 		 error,
969 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
970 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
971 		 "%s: unable to clear IO handle.",
972 		 function );
973 
974 		result = -1;
975 	}
976 	if( libluksde_volume_header_free(
977 	     &( internal_volume->header ),
978 	     error ) != 1 )
979 	{
980 		libcerror_error_set(
981 		 error,
982 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
983 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
984 		 "%s: unable to free header.",
985 		 function );
986 
987 		result = -1;
988 	}
989 	if( memory_set(
990 	     internal_volume->master_key,
991 	     0,
992 	     32 ) == NULL )
993 	{
994 		libcerror_error_set(
995 		 error,
996 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
997 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
998 		 "%s: unable to clear master key.",
999 		 function );
1000 
1001 		result = -1;
1002 	}
1003 	if( libfdata_vector_free(
1004 	     &( internal_volume->sectors_vector ),
1005 	     error ) != 1 )
1006 	{
1007 		libcerror_error_set(
1008 		 error,
1009 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1010 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1011 		 "%s: unable to free sectors vector.",
1012 		 function );
1013 
1014 		result = -1;
1015 	}
1016 	if( libfcache_cache_free(
1017 	     &( internal_volume->sectors_cache ),
1018 	     error ) != 1 )
1019 	{
1020 		libcerror_error_set(
1021 		 error,
1022 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1023 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1024 		 "%s: unable to free sectors cache.",
1025 		 function );
1026 
1027 		result = -1;
1028 	}
1029 	if( internal_volume->io_handle->encryption_context != NULL )
1030 	{
1031 		if( libluksde_encryption_free(
1032 		     &( internal_volume->io_handle->encryption_context ),
1033 		     error ) != 1 )
1034 		{
1035 			libcerror_error_set(
1036 			 error,
1037 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1038 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1039 			 "%s: unable to free encryption context.",
1040 			 function );
1041 
1042 			result = -1;
1043 		}
1044 	}
1045 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
1046 	if( libcthreads_read_write_lock_release_for_write(
1047 	     internal_volume->read_write_lock,
1048 	     error ) != 1 )
1049 	{
1050 		libcerror_error_set(
1051 		 error,
1052 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1053 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1054 		 "%s: unable to release read/write lock for writing.",
1055 		 function );
1056 
1057 		return( -1 );
1058 	}
1059 #endif
1060 	return( result );
1061 }
1062 
1063 /* Opens a volume for reading
1064  * Returns 1 if successful, 0 if the keys could not be read or -1 on error
1065  */
libluksde_volume_open_read(libluksde_internal_volume_t * internal_volume,libbfio_handle_t * file_io_handle,libcerror_error_t ** error)1066 int libluksde_volume_open_read(
1067      libluksde_internal_volume_t *internal_volume,
1068      libbfio_handle_t *file_io_handle,
1069      libcerror_error_t **error )
1070 {
1071 	uint8_t master_key_validation_hash[ 20 ];
1072 	uint8_t user_key[ 32 ];
1073 
1074 	libluksde_encryption_context_t *user_key_encryption_context = NULL;
1075 	libluksde_key_slot_t *key_slot                              = NULL;
1076 	uint8_t *key_material_data                                  = NULL;
1077 	uint8_t *split_master_key_data                              = NULL;
1078 	static char *function                                       = "libluksde_volume_open_read";
1079 	size_t key_material_data_offset                             = 0;
1080 	size_t key_material_size                                    = 0;
1081 	ssize_t read_count                                          = 0;
1082 	uint64_t key_material_block_key                             = 0;
1083 	int element_index                                           = 0;
1084 	int key_slot_index                                          = 0;
1085 	int result                                                  = 0;
1086 
1087 	if( internal_volume == NULL )
1088 	{
1089 		libcerror_error_set(
1090 		 error,
1091 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1092 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1093 		 "%s: invalid volume.",
1094 		 function );
1095 
1096 		return( -1 );
1097 	}
1098 	if( internal_volume->io_handle == NULL )
1099 	{
1100 		libcerror_error_set(
1101 		 error,
1102 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1103 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1104 		 "%s: invalid volume - missing IO handle.",
1105 		 function );
1106 
1107 		return( -1 );
1108 	}
1109 	if( internal_volume->io_handle->bytes_per_sector == 0 )
1110 	{
1111 		libcerror_error_set(
1112 		 error,
1113 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1114 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1115 		 "%s: invalid volume - invalid IO handle - missing bytes per sector.",
1116 		 function );
1117 
1118 		return( -1 );
1119 	}
1120 	if( internal_volume->header != NULL )
1121 	{
1122 		libcerror_error_set(
1123 		 error,
1124 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1125 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1126 		 "%s: invalid volume - header value already set.",
1127 		 function );
1128 
1129 		return( -1 );
1130 	}
1131 	if( internal_volume->sectors_vector != NULL )
1132 	{
1133 		libcerror_error_set(
1134 		 error,
1135 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1136 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1137 		 "%s: invalid volume - sectors vector value already set.",
1138 		 function );
1139 
1140 		return( -1 );
1141 	}
1142 	if( internal_volume->sectors_cache != NULL )
1143 	{
1144 		libcerror_error_set(
1145 		 error,
1146 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1147 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1148 		 "%s: invalid volume - sectors cache value already set.",
1149 		 function );
1150 
1151 		return( -1 );
1152 	}
1153 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
1154 	if( libcthreads_read_write_lock_grab_for_write(
1155 	     internal_volume->read_write_lock,
1156 	     error ) != 1 )
1157 	{
1158 		libcerror_error_set(
1159 		 error,
1160 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1161 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1162 		 "%s: unable to grab read/write lock for writing.",
1163 		 function );
1164 
1165 		return( -1 );
1166 	}
1167 #endif
1168 	if( libbfio_handle_get_size(
1169 	     file_io_handle,
1170 	     &( internal_volume->io_handle->volume_size ),
1171 	     error ) == -1 )
1172 	{
1173 		libcerror_error_set(
1174 		 error,
1175 		 LIBCERROR_ERROR_DOMAIN_IO,
1176 		 LIBCERROR_IO_ERROR_SEEK_FAILED,
1177 		 "%s: unable to determine volume size.",
1178 		 function );
1179 
1180 		goto on_error;
1181 	}
1182 #if defined( HAVE_DEBUG_OUTPUT )
1183 	if( libcnotify_verbose != 0 )
1184 	{
1185 		libcnotify_printf(
1186 		 "Reading LUKS volume header:\n" );
1187 	}
1188 #endif
1189 	if( libluksde_volume_header_initialize(
1190 	     &( internal_volume->header ),
1191 	     error ) != 1 )
1192 	{
1193 		libcerror_error_set(
1194 		 error,
1195 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1196 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1197 		 "%s: unable to create volume header.",
1198 		 function );
1199 
1200 		goto on_error;
1201 	}
1202 	if( libluksde_volume_header_read_file_io_handle(
1203 	     internal_volume->header,
1204 	     file_io_handle,
1205 	     0,
1206 	     error ) != 1 )
1207 	{
1208 		libcerror_error_set(
1209 		 error,
1210 		 LIBCERROR_ERROR_DOMAIN_IO,
1211 		 LIBCERROR_IO_ERROR_READ_FAILED,
1212 		 "%s: unable to read volume header.",
1213 		 function );
1214 
1215 		goto on_error;
1216 	}
1217 	if( ( internal_volume->header->master_key_size == 0 )
1218 	 || ( internal_volume->header->master_key_size > 64 ) )
1219 	{
1220 		libcerror_error_set(
1221 		 error,
1222 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1223 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1224 		 "%s: invalid master key size value out of bounds.",
1225 		 function );
1226 
1227 		return( -1 );
1228 	}
1229 	internal_volume->master_key_size = internal_volume->header->master_key_size;
1230 
1231 	if( internal_volume->header->encrypted_volume_start_sector >= ( internal_volume->io_handle->volume_size / internal_volume->io_handle->bytes_per_sector ) )
1232 	{
1233 		libcerror_error_set(
1234 		 error,
1235 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1236 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1237 		 "%s: invalid encrypted volume start sector value out of bounds.",
1238 		 function );
1239 
1240 		return( -1 );
1241 	}
1242 	internal_volume->io_handle->encrypted_volume_offset = internal_volume->header->encrypted_volume_start_sector
1243 	                                                    * internal_volume->io_handle->bytes_per_sector;
1244 
1245 	internal_volume->io_handle->encrypted_volume_size = internal_volume->io_handle->volume_size
1246 	                                                  - internal_volume->io_handle->encrypted_volume_offset;
1247 
1248 	if( internal_volume->keys_are_set != 0 )
1249 	{
1250 		if( libluksde_password_pbkdf2(
1251 		     internal_volume->master_key,
1252 		     internal_volume->master_key_size,
1253 		     internal_volume->header->hashing_method,
1254 		     internal_volume->header->master_key_salt,
1255 		     32,
1256 		     internal_volume->header->master_key_number_of_iterations,
1257 		     master_key_validation_hash,
1258 		     20,
1259 		     error ) == -1 )
1260 		{
1261 			libcerror_error_set(
1262 			 error,
1263 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1264 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1265 			 "%s: unable to determine master key validation hash.",
1266 			 function );
1267 
1268 			goto on_error;
1269 		}
1270 #if defined( HAVE_DEBUG_OUTPUT )
1271 		if( libcnotify_verbose != 0 )
1272 		{
1273 			libcnotify_printf(
1274 			 "%s: master key validation hash data:\n",
1275 			 function );
1276 			libcnotify_print_data(
1277 			 master_key_validation_hash,
1278 			 20,
1279 			 0 );
1280 		}
1281 #endif
1282 		if( memory_compare(
1283 		     master_key_validation_hash,
1284 		     internal_volume->header->master_key_validation_hash,
1285 		     20 ) == 0 )
1286 		{
1287 			internal_volume->is_locked = 0;
1288 		}
1289 	}
1290 	if( ( internal_volume->is_locked != 0 )
1291 	 && ( internal_volume->user_password_is_set != 0 ) )
1292 	{
1293 		for( key_slot_index = 0;
1294 		     key_slot_index < 8;
1295 		     key_slot_index++ )
1296 		{
1297 			if( libcdata_array_get_entry_by_index(
1298 			     internal_volume->header->key_slots_array,
1299 			     key_slot_index,
1300 			     (intptr_t **) &key_slot,
1301 			     error ) != 1 )
1302 			{
1303 				libcerror_error_set(
1304 				 error,
1305 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1306 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1307 				 "%s: unable to retrieve key slot: %d.",
1308 				 function,
1309 				 key_slot_index );
1310 
1311 				goto on_error;
1312 			}
1313 			if( key_slot == NULL )
1314 			{
1315 				libcerror_error_set(
1316 				 error,
1317 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1318 				 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1319 				 "%s: missing key slot: %d.",
1320 				 function,
1321 				 key_slot_index );
1322 
1323 				goto on_error;
1324 			}
1325 			if( key_slot->state != 0x00ac71f3 )
1326 			{
1327 				continue;
1328 			}
1329 			if( internal_volume->user_password_is_set != 0 )
1330 			{
1331 				if( libluksde_password_pbkdf2(
1332 				     internal_volume->user_password,
1333 				     internal_volume->user_password_size - 1,
1334 				     internal_volume->header->hashing_method,
1335 				     key_slot->salt,
1336 				     32,
1337 				     key_slot->number_of_iterations,
1338 				     user_key,
1339 				     internal_volume->master_key_size,
1340 				     error ) != 1 )
1341 				{
1342 					libcerror_error_set(
1343 					 error,
1344 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1345 					 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1346 					 "%s: unable to determine user key.",
1347 					 function );
1348 
1349 					goto on_error;
1350 				}
1351 				key_slot->key_material_offset *= internal_volume->io_handle->bytes_per_sector;
1352 
1353 #if defined( HAVE_DEBUG_OUTPUT )
1354 				if( libcnotify_verbose != 0 )
1355 				{
1356 					libcnotify_printf(
1357 					 "%s: reading key material at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
1358 					 function,
1359 					 key_slot->key_material_offset,
1360 					 key_slot->key_material_offset );
1361 				}
1362 #endif
1363 				if( libbfio_handle_seek_offset(
1364 				     file_io_handle,
1365 				     key_slot->key_material_offset,
1366 				     SEEK_SET,
1367 				     error ) == -1 )
1368 				{
1369 					libcerror_error_set(
1370 					 error,
1371 					 LIBCERROR_ERROR_DOMAIN_IO,
1372 					 LIBCERROR_IO_ERROR_SEEK_FAILED,
1373 					 "%s: unable to seek key material offset: %" PRIi64 ".",
1374 					 function,
1375 					 key_slot->key_material_offset );
1376 
1377 					goto on_error;
1378 				}
1379 /* TODO add bounds check */
1380 				key_material_size = internal_volume->master_key_size
1381 						  * key_slot->number_of_stripes;
1382 
1383 				key_material_data = (uint8_t *) memory_allocate(
1384 				                                 sizeof( uint8_t ) * key_material_size );
1385 
1386 				if( key_material_data == NULL )
1387 				{
1388 					libcerror_error_set(
1389 					 error,
1390 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1391 					 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1392 					 "%s: unable to create key material data.",
1393 					 function );
1394 
1395 					goto on_error;
1396 				}
1397 				read_count = libbfio_handle_read_buffer(
1398 					      file_io_handle,
1399 					      key_material_data,
1400 					      key_material_size,
1401 					      error );
1402 
1403 				if( read_count != (ssize_t) key_material_size )
1404 				{
1405 					libcerror_error_set(
1406 					 error,
1407 					 LIBCERROR_ERROR_DOMAIN_IO,
1408 					 LIBCERROR_IO_ERROR_READ_FAILED,
1409 					 "%s: unable to read key material data.",
1410 					 function );
1411 
1412 					goto on_error;
1413 				}
1414 #if defined( HAVE_DEBUG_OUTPUT )
1415 				if( libcnotify_verbose != 0 )
1416 				{
1417 					libcnotify_printf(
1418 					 "%s: key material data:\n",
1419 					 function );
1420 					libcnotify_print_data(
1421 					 key_material_data,
1422 					 key_material_size,
1423 					 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1424 				}
1425 #endif
1426 				split_master_key_data = (uint8_t *) memory_allocate(
1427 				                                     sizeof( uint8_t ) * key_material_size );
1428 
1429 				if( split_master_key_data == NULL )
1430 				{
1431 					libcerror_error_set(
1432 					 error,
1433 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1434 					 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1435 					 "%s: unable to create split master key data.",
1436 					 function );
1437 
1438 					goto on_error;
1439 				}
1440 #if defined( HAVE_DEBUG_OUTPUT )
1441 				if( libcnotify_verbose != 0 )
1442 				{
1443 					libcnotify_printf(
1444 					 "%s: user key:\n",
1445 					 function );
1446 					libcnotify_print_data(
1447 					 user_key,
1448 					 32,
1449 					 0 );
1450 				}
1451 #endif
1452 				if( libluksde_encryption_initialize(
1453 				     &user_key_encryption_context,
1454 				     internal_volume->header->encryption_method,
1455 				     internal_volume->header->encryption_chaining_mode,
1456 				     internal_volume->header->initialization_vector_mode,
1457 				     internal_volume->header->essiv_hashing_method,
1458 				     error ) != 1 )
1459 				{
1460 					libcerror_error_set(
1461 					 error,
1462 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1463 					 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1464 					 "%s: unable to create user key encryption context.",
1465 					 function );
1466 
1467 					goto on_error;
1468 				}
1469 				if( libluksde_encryption_set_key(
1470 				     user_key_encryption_context,
1471 				     user_key,
1472 				     internal_volume->master_key_size,
1473 				     error ) != 1 )
1474 				{
1475 					libcerror_error_set(
1476 					 error,
1477 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1478 					 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1479 					 "%s: unable to set key in user key encryption context.",
1480 					 function );
1481 
1482 					goto on_error;
1483 				}
1484 				if( memory_set(
1485 				     user_key,
1486 				     0,
1487 				     32  ) == NULL )
1488 				{
1489 					libcerror_error_set(
1490 					 error,
1491 					 LIBCERROR_ERROR_DOMAIN_MEMORY,
1492 					 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1493 					 "%s: unable to clear user key.",
1494 					 function );
1495 
1496 					goto on_error;
1497 				}
1498 				key_material_block_key = 0;
1499 
1500 				while( key_material_data_offset < key_material_size )
1501 				{
1502 					/* The data needs to be decrypted sector-by-sector
1503 					 */
1504 					if( libluksde_encryption_crypt(
1505 					     user_key_encryption_context,
1506 					     LIBLUKSDE_ENCRYPTION_CRYPT_MODE_DECRYPT,
1507 					     &( key_material_data[ key_material_data_offset ] ),
1508 					     internal_volume->io_handle->bytes_per_sector,
1509 					     &( split_master_key_data[ key_material_data_offset ] ),
1510 					     internal_volume->io_handle->bytes_per_sector,
1511 					     key_material_block_key,
1512 					     error ) != 1 )
1513 					{
1514 						libcerror_error_set(
1515 						 error,
1516 						 LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
1517 						 LIBCERROR_ENCRYPTION_ERROR_GENERIC,
1518 						 "%s: unable to decrypt key material data.",
1519 						 function );
1520 
1521 						goto on_error;
1522 					}
1523 					key_material_data_offset += internal_volume->io_handle->bytes_per_sector;
1524 					key_material_block_key   += 1;
1525 				}
1526 #if defined( HAVE_DEBUG_OUTPUT )
1527 				if( libcnotify_verbose != 0 )
1528 				{
1529 					libcnotify_printf(
1530 					 "%s: split master key data:\n",
1531 					 function );
1532 					libcnotify_print_data(
1533 					 split_master_key_data,
1534 					 key_material_size,
1535 					 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1536 				}
1537 #endif
1538 				memory_free(
1539 				 key_material_data );
1540 
1541 				key_material_data = NULL;
1542 
1543 				if( libluksde_encryption_free(
1544 				     &user_key_encryption_context,
1545 				     error ) != 1 )
1546 				{
1547 					libcerror_error_set(
1548 					 error,
1549 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1550 					 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1551 					 "%s: unable to free user key encryption context.",
1552 					 function );
1553 
1554 					goto on_error;
1555 				}
1556 				if( libluksde_diffuser_merge(
1557 				     split_master_key_data,
1558 				     key_material_size,
1559 				     internal_volume->master_key,
1560 				     internal_volume->master_key_size,
1561 				     key_slot->number_of_stripes,
1562 				     internal_volume->header->hashing_method,
1563 				     error ) != 1 )
1564 				{
1565 					libcerror_error_set(
1566 					 error,
1567 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1568 					 LIBCERROR_RUNTIME_ERROR_GENERIC,
1569 					 "%s: unable to merge split master key.",
1570 					 function );
1571 
1572 					goto on_error;
1573 				}
1574 #if defined( HAVE_DEBUG_OUTPUT )
1575 				if( libcnotify_verbose != 0 )
1576 				{
1577 					libcnotify_printf(
1578 					 "%s: master key data:\n",
1579 					 function );
1580 					libcnotify_print_data(
1581 					 internal_volume->master_key,
1582 					 internal_volume->master_key_size,
1583 					 0 );
1584 				}
1585 #endif
1586 				if( memory_set(
1587 				     split_master_key_data,
1588 				     0,
1589 				     key_material_size  ) == NULL )
1590 				{
1591 					libcerror_error_set(
1592 					 error,
1593 					 LIBCERROR_ERROR_DOMAIN_MEMORY,
1594 					 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1595 					 "%s: unable to clear split master key data.",
1596 					 function );
1597 
1598 					goto on_error;
1599 				}
1600 				memory_free(
1601 				 split_master_key_data );
1602 
1603 				split_master_key_data = NULL;
1604 
1605 				if( libluksde_password_pbkdf2(
1606 				     internal_volume->master_key,
1607 				     internal_volume->master_key_size,
1608 				     internal_volume->header->hashing_method,
1609 				     internal_volume->header->master_key_salt,
1610 				     32,
1611 				     internal_volume->header->master_key_number_of_iterations,
1612 				     master_key_validation_hash,
1613 				     20,
1614 				     error ) == -1 )
1615 				{
1616 					libcerror_error_set(
1617 					 error,
1618 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1619 					 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1620 					 "%s: unable to determine master key validation hash.",
1621 					 function );
1622 
1623 					goto on_error;
1624 				}
1625 #if defined( HAVE_DEBUG_OUTPUT )
1626 				if( libcnotify_verbose != 0 )
1627 				{
1628 					libcnotify_printf(
1629 					 "%s: master key validation hash data:\n",
1630 					 function );
1631 					libcnotify_print_data(
1632 					 master_key_validation_hash,
1633 					 20,
1634 					 0 );
1635 				}
1636 #endif
1637 #if defined( HAVE_DEBUG_OUTPUT )
1638 				if( libcnotify_verbose != 0 )
1639 				{
1640 					libcnotify_printf(
1641 					 "%s: check:\n",
1642 					 function );
1643 					libcnotify_print_data(
1644 					 internal_volume->header->master_key_validation_hash,
1645 					 20,
1646 					 0 );
1647 				}
1648 #endif
1649 				if( memory_compare(
1650 				     master_key_validation_hash,
1651 				     internal_volume->header->master_key_validation_hash,
1652 				     20 ) == 0 )
1653 				{
1654 					internal_volume->is_locked = 0;
1655 
1656 					break;
1657 				}
1658 			}
1659 		}
1660 	}
1661 	result = 0;
1662 
1663 	if( internal_volume->is_locked == 0 )
1664 	{
1665 		if( libluksde_encryption_initialize(
1666 		     &( internal_volume->io_handle->encryption_context ),
1667 		     internal_volume->header->encryption_method,
1668 		     internal_volume->header->encryption_chaining_mode,
1669 		     internal_volume->header->initialization_vector_mode,
1670 		     internal_volume->header->essiv_hashing_method,
1671 		     error ) != 1 )
1672 		{
1673 			libcerror_error_set(
1674 			 error,
1675 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1676 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1677 			 "%s: unable to create encryption context.",
1678 			 function );
1679 
1680 			goto on_error;
1681 		}
1682 		if( libluksde_encryption_set_key(
1683 		     internal_volume->io_handle->encryption_context,
1684 		     internal_volume->master_key,
1685 		     internal_volume->master_key_size,
1686 		     error ) != 1 )
1687 		{
1688 			libcerror_error_set(
1689 			 error,
1690 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1691 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1692 			 "%s: unable to set key in encryption context.",
1693 			 function );
1694 
1695 			goto on_error;
1696 		}
1697 /* TODO clone function ? */
1698 		if( libfdata_vector_initialize(
1699 		     &( internal_volume->sectors_vector ),
1700 		     (size64_t) internal_volume->io_handle->bytes_per_sector,
1701 		     (intptr_t *) internal_volume->io_handle,
1702 		     NULL,
1703 		     NULL,
1704 		     (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libluksde_io_handle_read_sector,
1705 		     NULL,
1706 		     LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
1707 		     error ) != 1 )
1708 		{
1709 			libcerror_error_set(
1710 			 error,
1711 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1712 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1713 			 "%s: unable to create sectors vector.",
1714 			 function );
1715 
1716 			goto on_error;
1717 		}
1718 		if( libfdata_vector_append_segment(
1719 		     internal_volume->sectors_vector,
1720 		     &element_index,
1721 		     0,
1722 		     internal_volume->io_handle->encrypted_volume_offset,
1723 		     internal_volume->io_handle->volume_size,
1724 		     0,
1725 		     error ) != 1 )
1726 		{
1727 			libcerror_error_set(
1728 			 error,
1729 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1730 			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1731 			 "%s: unable to append segment to sectors vector.",
1732 			 function );
1733 
1734 			goto on_error;
1735 		}
1736 		if( libfcache_cache_initialize(
1737 		     &( internal_volume->sectors_cache ),
1738 		     LIBLUKSDE_MAXIMUM_CACHE_ENTRIES_SECTORS,
1739 		     error ) != 1 )
1740 		{
1741 			libcerror_error_set(
1742 			 error,
1743 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1744 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1745 			 "%s: unable to create sectors cache.",
1746 			 function );
1747 
1748 			goto on_error;
1749 		}
1750 		result = 1;
1751 	}
1752 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
1753 	if( libcthreads_read_write_lock_release_for_write(
1754 	     internal_volume->read_write_lock,
1755 	     error ) != 1 )
1756 	{
1757 		libcerror_error_set(
1758 		 error,
1759 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1760 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1761 		 "%s: unable to release read/write lock for writing.",
1762 		 function );
1763 
1764 		return( -1 );
1765 	}
1766 #endif
1767 	return( result );
1768 
1769 on_error:
1770 	if( internal_volume->sectors_cache != NULL )
1771 	{
1772 		libfcache_cache_free(
1773 		 &( internal_volume->sectors_cache ),
1774 		 NULL );
1775 	}
1776 	if( internal_volume->sectors_vector != NULL )
1777 	{
1778 		libfdata_vector_free(
1779 		 &( internal_volume->sectors_vector ),
1780 		 NULL );
1781 	}
1782 	if( internal_volume->io_handle->encryption_context != NULL )
1783 	{
1784 		libluksde_encryption_free(
1785 		 &( internal_volume->io_handle->encryption_context ),
1786 		 NULL );
1787 	}
1788 	if( split_master_key_data != NULL )
1789 	{
1790 		memory_set(
1791 		 split_master_key_data,
1792 		 0,
1793 		 key_material_size );
1794 
1795 		memory_free(
1796 		 split_master_key_data );
1797 	}
1798 	if( key_material_data != NULL )
1799 	{
1800 		memory_free(
1801 		 key_material_data );
1802 	}
1803 	if( user_key_encryption_context != NULL )
1804 	{
1805 		libluksde_encryption_free(
1806 		 &user_key_encryption_context,
1807 		 NULL );
1808 	}
1809 	if( internal_volume->header != NULL )
1810 	{
1811 		libluksde_volume_header_free(
1812 		 &( internal_volume->header ),
1813 		 NULL );
1814 	}
1815 	memory_set(
1816 	 user_key,
1817 	 0,
1818 	 32 );
1819 
1820 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
1821 	libcthreads_read_write_lock_release_for_write(
1822 	 internal_volume->read_write_lock,
1823 	 NULL );
1824 #endif
1825 	return( -1 );
1826 }
1827 
1828 /* Determines if the volume is locked
1829  * Returns 1 if locked, 0 if not or -1 on error
1830  */
libluksde_volume_is_locked(libluksde_volume_t * volume,libcerror_error_t ** error)1831 int libluksde_volume_is_locked(
1832      libluksde_volume_t *volume,
1833      libcerror_error_t **error )
1834 {
1835 	libluksde_internal_volume_t *internal_volume = NULL;
1836 	static char *function                        = "libluksde_volume_is_locked";
1837 	uint8_t is_locked                            = 0;
1838 
1839 	if( volume == NULL )
1840 	{
1841 		libcerror_error_set(
1842 		 error,
1843 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1844 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1845 		 "%s: invalid volume.",
1846 		 function );
1847 
1848 		return( -1 );
1849 	}
1850 	internal_volume = (libluksde_internal_volume_t *) volume;
1851 
1852 #if defined( HAVE_LIBBDE_MULTI_THREAD_SUPPORT )
1853 	if( libcthreads_read_write_lock_grab_for_read(
1854 	     internal_volume->read_write_lock,
1855 	     error ) != 1 )
1856 	{
1857 		libcerror_error_set(
1858 		 error,
1859 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1860 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1861 		 "%s: unable to grab read/write lock for reading.",
1862 		 function );
1863 
1864 		return( -1 );
1865 	}
1866 #endif
1867 	is_locked = internal_volume->is_locked;
1868 
1869 #if defined( HAVE_LIBBDE_MULTI_THREAD_SUPPORT )
1870 	if( libcthreads_read_write_lock_release_for_read(
1871 	     internal_volume->read_write_lock,
1872 	     error ) != 1 )
1873 	{
1874 		libcerror_error_set(
1875 		 error,
1876 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1877 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1878 		 "%s: unable to release read/write lock for reading.",
1879 		 function );
1880 
1881 		return( -1 );
1882 	}
1883 #endif
1884 	return( is_locked );
1885 }
1886 
1887 /* Reads (volume) data from the last current into a buffer using a Basic File IO (bfio) handle
1888  * This function is not multi-thread safe acquire write lock before call
1889  * Returns the number of bytes read or -1 on error
1890  */
libluksde_internal_volume_read_buffer_from_file_io_handle(libluksde_internal_volume_t * internal_volume,libbfio_handle_t * file_io_handle,void * buffer,size_t buffer_size,libcerror_error_t ** error)1891 ssize_t libluksde_internal_volume_read_buffer_from_file_io_handle(
1892          libluksde_internal_volume_t *internal_volume,
1893          libbfio_handle_t *file_io_handle,
1894          void *buffer,
1895          size_t buffer_size,
1896          libcerror_error_t **error )
1897 {
1898 	libluksde_sector_data_t *sector_data = NULL;
1899 	static char *function                = "libluksde_internal_volume_read_buffer_from_file_io_handle";
1900 	off64_t element_data_offset          = 0;
1901 	size_t buffer_offset                 = 0;
1902 	size_t read_size                     = 0;
1903 	size_t sector_data_offset            = 0;
1904 	ssize_t total_read_count             = 0;
1905 
1906 	if( internal_volume == NULL )
1907 	{
1908 		libcerror_error_set(
1909 		 error,
1910 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1911 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1912 		 "%s: invalid volume.",
1913 		 function );
1914 
1915 		return( -1 );
1916 	}
1917 	if( internal_volume->is_locked != 0 )
1918 	{
1919 		libcerror_error_set(
1920 		 error,
1921 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1922 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1923 		 "%s: invalid volume - volume is locked.",
1924 		 function );
1925 
1926 		return( -1 );
1927 	}
1928 	if( internal_volume->io_handle == NULL )
1929 	{
1930 		libcerror_error_set(
1931 		 error,
1932 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1933 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1934 		 "%s: invalid volume - missing IO handle.",
1935 		 function );
1936 
1937 		return( -1 );
1938 	}
1939 	if( internal_volume->sectors_vector == NULL )
1940 	{
1941 		libcerror_error_set(
1942 		 error,
1943 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1944 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1945 		 "%s: invalid volume - missing sectors vector.",
1946 		 function );
1947 
1948 		return( -1 );
1949 	}
1950 	if( internal_volume->sectors_cache == NULL )
1951 	{
1952 		libcerror_error_set(
1953 		 error,
1954 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1955 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1956 		 "%s: invalid volume - missing sectors cache.",
1957 		 function );
1958 
1959 		return( -1 );
1960 	}
1961 	if( internal_volume->current_offset < 0 )
1962 	{
1963 		libcerror_error_set(
1964 		 error,
1965 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1966 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1967 		 "%s: invalid volume - current offset value out of bounds.",
1968 		 function );
1969 
1970 		return( -1 );
1971 	}
1972 	if( buffer == NULL )
1973 	{
1974 		libcerror_error_set(
1975 		 error,
1976 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1977 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1978 		 "%s: invalid buffer.",
1979 		 function );
1980 
1981 		return( -1 );
1982 	}
1983 	if( buffer_size > (size_t) SSIZE_MAX )
1984 	{
1985 		libcerror_error_set(
1986 		 error,
1987 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1988 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1989 		 "%s: invalid buffer size value exceeds maximum.",
1990 		 function );
1991 
1992 		return( -1 );
1993 	}
1994 	if( (size64_t) internal_volume->current_offset >= internal_volume->io_handle->encrypted_volume_size )
1995 	{
1996 		return( 0 );
1997 	}
1998 	if( (size64_t) ( internal_volume->current_offset + buffer_size ) >= internal_volume->io_handle->encrypted_volume_size )
1999 	{
2000 		buffer_size = (size_t) ( internal_volume->io_handle->encrypted_volume_size - internal_volume->current_offset );
2001 	}
2002 	sector_data_offset = (size_t) ( internal_volume->current_offset % internal_volume->io_handle->bytes_per_sector );
2003 
2004 	while( buffer_size > 0 )
2005 	{
2006 		if( libfdata_vector_get_element_value_at_offset(
2007 		     internal_volume->sectors_vector,
2008 		     (intptr_t *) file_io_handle,
2009 		     (libfdata_cache_t *) internal_volume->sectors_cache,
2010 		     internal_volume->current_offset,
2011 		     &element_data_offset,
2012 		     (intptr_t **) &sector_data,
2013 		     0,
2014 		     error ) != 1 )
2015 		{
2016 			libcerror_error_set(
2017 			 error,
2018 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2019 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2020 			 "%s: unable to retrieve sector data at offset: %" PRIi64 ".",
2021 			 function,
2022 			 internal_volume->current_offset );
2023 
2024 			return( -1 );
2025 		}
2026 		if( sector_data == NULL )
2027 		{
2028 			libcerror_error_set(
2029 			 error,
2030 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2031 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2032 			 "%s: missing sector data at offset: %" PRIi64 ".",
2033 			 function,
2034 			 internal_volume->current_offset );
2035 
2036 			return( -1 );
2037 		}
2038 		read_size = sector_data->data_size - sector_data_offset;
2039 
2040 		if( read_size > buffer_size )
2041 		{
2042 			read_size = buffer_size;
2043 		}
2044 		if( read_size == 0 )
2045 		{
2046 			break;
2047 		}
2048 		if( memory_copy(
2049 		     &( ( (uint8_t *) buffer )[ buffer_offset ] ),
2050 		     &( ( sector_data->data )[ sector_data_offset ] ),
2051 		     read_size ) == NULL )
2052 		{
2053 			libcerror_error_set(
2054 			 error,
2055 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
2056 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2057 			 "%s: unable to copy sector data to buffer.",
2058 			 function );
2059 
2060 			return( -1 );
2061 		}
2062 		buffer_offset     += read_size;
2063 		buffer_size       -= read_size;
2064 		total_read_count  += (ssize_t) read_size;
2065 		sector_data_offset = 0;
2066 
2067 		internal_volume->current_offset += (off64_t) read_size;
2068 
2069 		if( (size64_t) internal_volume->current_offset >= internal_volume->io_handle->encrypted_volume_size )
2070 		{
2071 			break;
2072 		}
2073 		if( internal_volume->io_handle->abort != 0 )
2074 		{
2075 			break;
2076 		}
2077 	}
2078 	return( total_read_count );
2079 }
2080 
2081 /* Reads data at the current offset into a buffer
2082  * Returns the number of bytes read or -1 on error
2083  */
libluksde_volume_read_buffer(libluksde_volume_t * volume,void * buffer,size_t buffer_size,libcerror_error_t ** error)2084 ssize_t libluksde_volume_read_buffer(
2085          libluksde_volume_t *volume,
2086          void *buffer,
2087          size_t buffer_size,
2088          libcerror_error_t **error )
2089 {
2090 	libluksde_internal_volume_t *internal_volume = NULL;
2091 	static char *function                        = "libluksde_volume_read_buffer";
2092 	ssize_t read_count                           = 0;
2093 
2094 	if( volume == NULL )
2095 	{
2096 		libcerror_error_set(
2097 		 error,
2098 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2099 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2100 		 "%s: invalid volume.",
2101 		 function );
2102 
2103 		return( -1 );
2104 	}
2105 	internal_volume = (libluksde_internal_volume_t *) volume;
2106 
2107 	if( internal_volume->file_io_handle == NULL )
2108 	{
2109 		libcerror_error_set(
2110 		 error,
2111 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2112 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2113 		 "%s: invalid volume - missing file IO handle.",
2114 		 function );
2115 
2116 		return( -1 );
2117 	}
2118 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2119 	if( libcthreads_read_write_lock_grab_for_write(
2120 	     internal_volume->read_write_lock,
2121 	     error ) != 1 )
2122 	{
2123 		libcerror_error_set(
2124 		 error,
2125 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2126 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2127 		 "%s: unable to grab read/write lock for writing.",
2128 		 function );
2129 
2130 		return( -1 );
2131 	}
2132 #endif
2133 	read_count = libluksde_internal_volume_read_buffer_from_file_io_handle(
2134 		      internal_volume,
2135 		      internal_volume->file_io_handle,
2136 		      buffer,
2137 		      buffer_size,
2138 		      error );
2139 
2140 	if( read_count == -1 )
2141 	{
2142 		libcerror_error_set(
2143 		 error,
2144 		 LIBCERROR_ERROR_DOMAIN_IO,
2145 		 LIBCERROR_IO_ERROR_READ_FAILED,
2146 		 "%s: unable to read buffer.",
2147 		 function );
2148 
2149 		read_count = -1;
2150 	}
2151 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2152 	if( libcthreads_read_write_lock_release_for_write(
2153 	     internal_volume->read_write_lock,
2154 	     error ) != 1 )
2155 	{
2156 		libcerror_error_set(
2157 		 error,
2158 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2159 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2160 		 "%s: unable to release read/write lock for writing.",
2161 		 function );
2162 
2163 		return( -1 );
2164 	}
2165 #endif
2166 	return( read_count );
2167 }
2168 
2169 /* Reads (volume) data at a specific offset
2170  * Returns the number of bytes read or -1 on error
2171  */
libluksde_volume_read_buffer_at_offset(libluksde_volume_t * volume,void * buffer,size_t buffer_size,off64_t offset,libcerror_error_t ** error)2172 ssize_t libluksde_volume_read_buffer_at_offset(
2173          libluksde_volume_t *volume,
2174          void *buffer,
2175          size_t buffer_size,
2176          off64_t offset,
2177          libcerror_error_t **error )
2178 {
2179 	libluksde_internal_volume_t *internal_volume = NULL;
2180 	static char *function                        = "libluksde_volume_read_buffer_at_offset";
2181 	ssize_t read_count                           = 0;
2182 
2183 	if( volume == NULL )
2184 	{
2185 		libcerror_error_set(
2186 		 error,
2187 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2188 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2189 		 "%s: invalid volume.",
2190 		 function );
2191 
2192 		return( -1 );
2193 	}
2194 	internal_volume = (libluksde_internal_volume_t *) volume;
2195 
2196 	if( internal_volume->file_io_handle == NULL )
2197 	{
2198 		libcerror_error_set(
2199 		 error,
2200 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2201 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2202 		 "%s: invalid volume - missing file IO handle.",
2203 		 function );
2204 
2205 		return( -1 );
2206 	}
2207 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2208 	if( libcthreads_read_write_lock_grab_for_write(
2209 	     internal_volume->read_write_lock,
2210 	     error ) != 1 )
2211 	{
2212 		libcerror_error_set(
2213 		 error,
2214 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2215 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2216 		 "%s: unable to grab read/write lock for writing.",
2217 		 function );
2218 
2219 		return( -1 );
2220 	}
2221 #endif
2222 	if( libluksde_internal_volume_seek_offset(
2223 	     internal_volume,
2224 	     offset,
2225 	     SEEK_SET,
2226 	     error ) == -1 )
2227 	{
2228 		libcerror_error_set(
2229 		 error,
2230 		 LIBCERROR_ERROR_DOMAIN_IO,
2231 		 LIBCERROR_IO_ERROR_SEEK_FAILED,
2232 		 "%s: unable to seek offset.",
2233 		 function );
2234 
2235 		goto on_error;
2236 	}
2237 	read_count = libluksde_internal_volume_read_buffer_from_file_io_handle(
2238 		      internal_volume,
2239 		      internal_volume->file_io_handle,
2240 		      buffer,
2241 		      buffer_size,
2242 		      error );
2243 
2244 	if( read_count == -1 )
2245 	{
2246 		libcerror_error_set(
2247 		 error,
2248 		 LIBCERROR_ERROR_DOMAIN_IO,
2249 		 LIBCERROR_IO_ERROR_READ_FAILED,
2250 		 "%s: unable to read buffer.",
2251 		 function );
2252 
2253 		goto on_error;
2254 	}
2255 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2256 	if( libcthreads_read_write_lock_release_for_write(
2257 	     internal_volume->read_write_lock,
2258 	     error ) != 1 )
2259 	{
2260 		libcerror_error_set(
2261 		 error,
2262 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2263 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2264 		 "%s: unable to release read/write lock for writing.",
2265 		 function );
2266 
2267 		return( -1 );
2268 	}
2269 #endif
2270 	return( read_count );
2271 
2272 on_error:
2273 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2274 	libcthreads_read_write_lock_release_for_write(
2275 	 internal_volume->read_write_lock,
2276 	 NULL );
2277 #endif
2278 	return( -1 );
2279 }
2280 
2281 #ifdef TODO_WRITE_SUPPORT
2282 
2283 /* Writes (volume) data at the current offset
2284  * Returns the number of input bytes written, 0 when no longer bytes can be written or -1 on error
2285  */
libluksde_volume_write_buffer(libluksde_volume_t * volume,void * buffer,size_t buffer_size,libcerror_error_t ** error)2286 ssize_t libluksde_volume_write_buffer(
2287          libluksde_volume_t *volume,
2288          void *buffer,
2289          size_t buffer_size,
2290          libcerror_error_t **error )
2291 {
2292 	return( -1 );
2293 }
2294 
2295 /* Writes (volume) data at a specific offset,
2296  * Returns the number of input bytes written, 0 when no longer bytes can be written or -1 on error
2297  */
libluksde_volume_write_buffer_at_offset(libluksde_volume_t * volume,const void * buffer,size_t buffer_size,off64_t offset,libcerror_error_t ** error)2298 ssize_t libluksde_volume_write_buffer_at_offset(
2299          libluksde_volume_t *volume,
2300          const void *buffer,
2301          size_t buffer_size,
2302          off64_t offset,
2303          libcerror_error_t **error )
2304 {
2305 	static char *function = "libluksde_volume_write_buffer_at_offset";
2306 	ssize_t write_count   = 0;
2307 
2308 	if( libluksde_volume_seek_offset(
2309 	     volume,
2310 	     offset,
2311 	     SEEK_SET,
2312 	     error ) == -1 )
2313 	{
2314 		libcerror_error_set(
2315 		 error,
2316 		 LIBCERROR_ERROR_DOMAIN_IO,
2317 		 LIBCERROR_IO_ERROR_SEEK_FAILED,
2318 		 "%s: unable to seek offset.",
2319 		 function );
2320 
2321 		return( -1 );
2322 	}
2323 	write_count = libluksde_volume_write_buffer(
2324 	               volume,
2325 	               buffer,
2326 	               buffer_size,
2327 	               error );
2328 
2329 	if( write_count < 0 )
2330 	{
2331 		libcerror_error_set(
2332 		 error,
2333 		 LIBCERROR_ERROR_DOMAIN_IO,
2334 		 LIBCERROR_IO_ERROR_WRITE_FAILED,
2335 		 "%s: unable to write buffer.",
2336 		 function );
2337 
2338 		return( -1 );
2339 	}
2340 	return( write_count );
2341 }
2342 
2343 #endif /* TODO_WRITE_SUPPORT */
2344 
2345 /* Seeks a certain offset of the (volume) data
2346  * This function is not multi-thread safe acquire write lock before call
2347  * Returns the offset if seek is successful or -1 on error
2348  */
libluksde_internal_volume_seek_offset(libluksde_internal_volume_t * internal_volume,off64_t offset,int whence,libcerror_error_t ** error)2349 off64_t libluksde_internal_volume_seek_offset(
2350          libluksde_internal_volume_t *internal_volume,
2351          off64_t offset,
2352          int whence,
2353          libcerror_error_t **error )
2354 {
2355 	static char *function = "libluksde_internal_volume_seek_offset";
2356 
2357 	if( internal_volume == NULL )
2358 	{
2359 		libcerror_error_set(
2360 		 error,
2361 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2362 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2363 		 "%s: invalid volume.",
2364 		 function );
2365 
2366 		return( -1 );
2367 	}
2368 	if( internal_volume->is_locked != 0 )
2369 	{
2370 		libcerror_error_set(
2371 		 error,
2372 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2373 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2374 		 "%s: invalid volume - volume is locked.",
2375 		 function );
2376 
2377 		return( -1 );
2378 	}
2379 	if( internal_volume->io_handle == NULL )
2380 	{
2381 		libcerror_error_set(
2382 		 error,
2383 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2384 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2385 		 "%s: invalid volume - missing IO handle.",
2386 		 function );
2387 
2388 		return( -1 );
2389 	}
2390 	if( ( whence != SEEK_CUR )
2391 	 && ( whence != SEEK_END )
2392 	 && ( whence != SEEK_SET ) )
2393 	{
2394 		libcerror_error_set(
2395 		 error,
2396 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2397 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2398 		 "%s: unsupported whence.",
2399 		 function );
2400 
2401 		return( -1 );
2402 	}
2403 	if( whence == SEEK_CUR )
2404 	{
2405 		offset += internal_volume->current_offset;
2406 	}
2407 	else if( whence == SEEK_END )
2408 	{
2409 		offset += (off64_t) internal_volume->io_handle->encrypted_volume_size;
2410 	}
2411 #if defined( HAVE_DEBUG_OUTPUT )
2412 	if( libcnotify_verbose != 0 )
2413 	{
2414 		libcnotify_printf(
2415 		 "%s: seeking volume data offset: %" PRIi64 ".\n",
2416 		 function,
2417 		 offset );
2418 	}
2419 #endif
2420 	if( offset < 0 )
2421 	{
2422 		libcerror_error_set(
2423 		 error,
2424 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2425 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2426 		 "%s: invalid offset value out of bounds.",
2427 		 function );
2428 
2429 		return( -1 );
2430 	}
2431 	internal_volume->current_offset = offset;
2432 
2433 	return( offset );
2434 }
2435 
2436 /* Seeks a certain offset of the data
2437  * Returns the offset if seek is successful or -1 on error
2438  */
libluksde_volume_seek_offset(libluksde_volume_t * volume,off64_t offset,int whence,libcerror_error_t ** error)2439 off64_t libluksde_volume_seek_offset(
2440          libluksde_volume_t *volume,
2441          off64_t offset,
2442          int whence,
2443          libcerror_error_t **error )
2444 {
2445 	libluksde_internal_volume_t *internal_volume = NULL;
2446 	static char *function                        = "libluksde_volume_seek_offset";
2447 
2448 	if( volume == NULL )
2449 	{
2450 		libcerror_error_set(
2451 		 error,
2452 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2453 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2454 		 "%s: invalid volume.",
2455 		 function );
2456 
2457 		return( -1 );
2458 	}
2459 	internal_volume = (libluksde_internal_volume_t *) volume;
2460 
2461 	if( internal_volume->file_io_handle == NULL )
2462 	{
2463 		libcerror_error_set(
2464 		 error,
2465 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2466 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2467 		 "%s: invalid volume - missing file IO handle.",
2468 		 function );
2469 
2470 		return( -1 );
2471 	}
2472 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2473 	if( libcthreads_read_write_lock_grab_for_write(
2474 	     internal_volume->read_write_lock,
2475 	     error ) != 1 )
2476 	{
2477 		libcerror_error_set(
2478 		 error,
2479 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2480 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2481 		 "%s: unable to grab read/write lock for writing.",
2482 		 function );
2483 
2484 		return( -1 );
2485 	}
2486 #endif
2487 	offset = libluksde_internal_volume_seek_offset(
2488 	          internal_volume,
2489 	          offset,
2490 	          whence,
2491 	          error );
2492 
2493 	if( offset == -1 )
2494 	{
2495 		libcerror_error_set(
2496 		 error,
2497 		 LIBCERROR_ERROR_DOMAIN_IO,
2498 		 LIBCERROR_IO_ERROR_SEEK_FAILED,
2499 		 "%s: unable to seek offset.",
2500 		 function );
2501 
2502 		offset = -1;
2503 	}
2504 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2505 	if( libcthreads_read_write_lock_release_for_write(
2506 	     internal_volume->read_write_lock,
2507 	     error ) != 1 )
2508 	{
2509 		libcerror_error_set(
2510 		 error,
2511 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2512 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2513 		 "%s: unable to release read/write lock for writing.",
2514 		 function );
2515 
2516 		return( -1 );
2517 	}
2518 #endif
2519 	return( offset );
2520 }
2521 
2522 /* Retrieves the current offset of the (volume) data
2523  * Returns 1 if successful or -1 on error
2524  */
libluksde_volume_get_offset(libluksde_volume_t * volume,off64_t * offset,libcerror_error_t ** error)2525 int libluksde_volume_get_offset(
2526      libluksde_volume_t *volume,
2527      off64_t *offset,
2528      libcerror_error_t **error )
2529 {
2530 	libluksde_internal_volume_t *internal_volume = NULL;
2531 	static char *function                        = "libluksde_volume_get_offset";
2532 
2533 	if( volume == NULL )
2534 	{
2535 		libcerror_error_set(
2536 		 error,
2537 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2538 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2539 		 "%s: invalid volume.",
2540 		 function );
2541 
2542 		return( -1 );
2543 	}
2544 	internal_volume = (libluksde_internal_volume_t *) volume;
2545 
2546 	if( offset == NULL )
2547 	{
2548 		libcerror_error_set(
2549 		 error,
2550 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2551 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2552 		 "%s: invalid offset.",
2553 		 function );
2554 
2555 		return( -1 );
2556 	}
2557 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2558 	if( libcthreads_read_write_lock_grab_for_read(
2559 	     internal_volume->read_write_lock,
2560 	     error ) != 1 )
2561 	{
2562 		libcerror_error_set(
2563 		 error,
2564 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2565 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2566 		 "%s: unable to grab read/write lock for reading.",
2567 		 function );
2568 
2569 		return( -1 );
2570 	}
2571 #endif
2572 	*offset = internal_volume->current_offset;
2573 
2574 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2575 	if( libcthreads_read_write_lock_release_for_read(
2576 	     internal_volume->read_write_lock,
2577 	     error ) != 1 )
2578 	{
2579 		libcerror_error_set(
2580 		 error,
2581 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2582 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2583 		 "%s: unable to release read/write lock for reading.",
2584 		 function );
2585 
2586 		return( -1 );
2587 	}
2588 #endif
2589 	return( 1 );
2590 }
2591 
2592 /* Retrieves the size
2593  * Returns 1 if successful or -1 on error
2594  */
libluksde_volume_get_size(libluksde_volume_t * volume,size64_t * size,libcerror_error_t ** error)2595 int libluksde_volume_get_size(
2596      libluksde_volume_t *volume,
2597      size64_t *size,
2598      libcerror_error_t **error )
2599 {
2600 	libluksde_internal_volume_t *internal_volume = NULL;
2601 	static char *function                        = "libluksde_volume_get_size";
2602 
2603 	if( volume == NULL )
2604 	{
2605 		libcerror_error_set(
2606 		 error,
2607 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2608 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2609 		 "%s: invalid volume.",
2610 		 function );
2611 
2612 		return( -1 );
2613 	}
2614 	internal_volume = (libluksde_internal_volume_t *) volume;
2615 
2616 	if( internal_volume->io_handle == NULL )
2617 	{
2618 		libcerror_error_set(
2619 		 error,
2620 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2621 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2622 		 "%s: invalid volume - missing IO handle.",
2623 		 function );
2624 
2625 		return( -1 );
2626 	}
2627 	if( size == NULL )
2628 	{
2629 		libcerror_error_set(
2630 		 error,
2631 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2632 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2633 		 "%s: invalid size.",
2634 		 function );
2635 
2636 		return( -1 );
2637 	}
2638 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2639 	if( libcthreads_read_write_lock_grab_for_read(
2640 	     internal_volume->read_write_lock,
2641 	     error ) != 1 )
2642 	{
2643 		libcerror_error_set(
2644 		 error,
2645 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2646 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2647 		 "%s: unable to grab read/write lock for reading.",
2648 		 function );
2649 
2650 		return( -1 );
2651 	}
2652 #endif
2653 	*size = internal_volume->io_handle->encrypted_volume_size;
2654 
2655 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2656 	if( libcthreads_read_write_lock_release_for_read(
2657 	     internal_volume->read_write_lock,
2658 	     error ) != 1 )
2659 	{
2660 		libcerror_error_set(
2661 		 error,
2662 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2663 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2664 		 "%s: unable to release read/write lock for reading.",
2665 		 function );
2666 
2667 		return( -1 );
2668 	}
2669 #endif
2670 	return( 1 );
2671 }
2672 
2673 /* Retrieves the encryption method
2674  * Returns 1 if successful or -1 on error
2675  */
libluksde_volume_get_encryption_method(libluksde_volume_t * volume,int * encryption_method,int * encryption_chaining_mode,libcerror_error_t ** error)2676 int libluksde_volume_get_encryption_method(
2677      libluksde_volume_t *volume,
2678      int *encryption_method,
2679      int *encryption_chaining_mode,
2680      libcerror_error_t **error )
2681 {
2682 	libluksde_internal_volume_t *internal_volume = NULL;
2683 	static char *function                        = "libluksde_volume_get_encryption_method";
2684 
2685 	if( volume == NULL )
2686 	{
2687 		libcerror_error_set(
2688 		 error,
2689 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2690 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2691 		 "%s: invalid volume.",
2692 		 function );
2693 
2694 		return( -1 );
2695 	}
2696 	internal_volume = (libluksde_internal_volume_t *) volume;
2697 
2698 	if( encryption_method == NULL )
2699 	{
2700 		libcerror_error_set(
2701 		 error,
2702 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2703 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2704 		 "%s: invalid encryption method.",
2705 		 function );
2706 
2707 		return( -1 );
2708 	}
2709 	if( encryption_chaining_mode == NULL )
2710 	{
2711 		libcerror_error_set(
2712 		 error,
2713 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2714 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2715 		 "%s: invalid encryption chaining mode.",
2716 		 function );
2717 
2718 		return( -1 );
2719 	}
2720 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2721 	if( libcthreads_read_write_lock_grab_for_read(
2722 	     internal_volume->read_write_lock,
2723 	     error ) != 1 )
2724 	{
2725 		libcerror_error_set(
2726 		 error,
2727 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2728 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2729 		 "%s: unable to grab read/write lock for reading.",
2730 		 function );
2731 
2732 		return( -1 );
2733 	}
2734 #endif
2735 	*encryption_method        = internal_volume->header->encryption_method;
2736 	*encryption_chaining_mode = internal_volume->header->encryption_chaining_mode;
2737 
2738 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2739 	if( libcthreads_read_write_lock_release_for_read(
2740 	     internal_volume->read_write_lock,
2741 	     error ) != 1 )
2742 	{
2743 		libcerror_error_set(
2744 		 error,
2745 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2746 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2747 		 "%s: unable to release read/write lock for reading.",
2748 		 function );
2749 
2750 		return( -1 );
2751 	}
2752 #endif
2753 	return( 1 );
2754 }
2755 
2756 /* Retrieves the volume identifier
2757  * The identifier is an UUID and is 16 bytes of size
2758  * Returns 1 if successful, 0 if not or or -1 on error
2759  */
libluksde_volume_get_volume_identifier(libluksde_volume_t * volume,uint8_t * uuid_data,size_t uuid_data_size,libcerror_error_t ** error)2760 int libluksde_volume_get_volume_identifier(
2761      libluksde_volume_t *volume,
2762      uint8_t *uuid_data,
2763      size_t uuid_data_size,
2764      libcerror_error_t **error )
2765 {
2766 	libluksde_internal_volume_t *internal_volume = NULL;
2767 	static char *function                        = "libluksde_volume_get_volume_identifier";
2768 	int result                                   = 0;
2769 
2770 	if( volume == NULL )
2771 	{
2772 		libcerror_error_set(
2773 		 error,
2774 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2775 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2776 		 "%s: invalid volume.",
2777 		 function );
2778 
2779 		return( -1 );
2780 	}
2781 	internal_volume = (libluksde_internal_volume_t *) volume;
2782 
2783 #if defined( HAVE_LIBBDE_MULTI_THREAD_SUPPORT )
2784 	if( libcthreads_read_write_lock_grab_for_read(
2785 	     internal_volume->read_write_lock,
2786 	     error ) != 1 )
2787 	{
2788 		libcerror_error_set(
2789 		 error,
2790 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2791 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2792 		 "%s: unable to grab read/write lock for reading.",
2793 		 function );
2794 
2795 		return( -1 );
2796 	}
2797 #endif
2798 	if( internal_volume->header != NULL )
2799 	{
2800 		result = libluksde_volume_header_get_volume_identifier(
2801 		          internal_volume->header,
2802 		          uuid_data,
2803 		          uuid_data_size,
2804 		          error );
2805 
2806 		if( result != 1 )
2807 		{
2808 			libcerror_error_set(
2809 			 error,
2810 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2811 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2812 			 "%s: unable to retrieve volume identifier.",
2813 			 function );
2814 
2815 			result = -1;
2816 		}
2817 	}
2818 #if defined( HAVE_LIBBDE_MULTI_THREAD_SUPPORT )
2819 	if( libcthreads_read_write_lock_release_for_read(
2820 	     internal_volume->read_write_lock,
2821 	     error ) != 1 )
2822 	{
2823 		libcerror_error_set(
2824 		 error,
2825 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2826 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2827 		 "%s: unable to release read/write lock for reading.",
2828 		 function );
2829 
2830 		return( -1 );
2831 	}
2832 #endif
2833 	return( result );
2834 }
2835 
2836 /* Sets the key
2837  * This function needs to be used before one of the open functions
2838  * Returns 1 if successful or -1 on error
2839  */
libluksde_volume_set_key(libluksde_volume_t * volume,const uint8_t * master_key,size_t master_key_size,libcerror_error_t ** error)2840 int libluksde_volume_set_key(
2841      libluksde_volume_t *volume,
2842      const uint8_t *master_key,
2843      size_t master_key_size,
2844      libcerror_error_t **error )
2845 {
2846 	libluksde_internal_volume_t *internal_volume = NULL;
2847 	static char *function                        = "libluksde_volume_set_key";
2848 
2849 	if( volume == NULL )
2850 	{
2851 		libcerror_error_set(
2852 		 error,
2853 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2854 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2855 		 "%s: invalid volume.",
2856 		 function );
2857 
2858 		return( -1 );
2859 	}
2860 	internal_volume = (libluksde_internal_volume_t *) volume;
2861 
2862 	if( internal_volume->file_io_handle != NULL )
2863 	{
2864 		libcerror_error_set(
2865 		 error,
2866 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2867 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2868 		 "%s: invalid volume - file IO handle already set.",
2869 		 function );
2870 
2871 		return( -1 );
2872 	}
2873 	if( master_key == NULL )
2874 	{
2875 		libcerror_error_set(
2876 		 error,
2877 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2878 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2879 		 "%s: invalid master key.",
2880 		 function );
2881 
2882 		return( -1 );
2883 	}
2884 	if( ( master_key_size != 16 )
2885 	 && ( master_key_size != 32 )
2886 	 && ( master_key_size != 64 ) )
2887 	{
2888 		libcerror_error_set(
2889 		 error,
2890 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2891 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2892 		 "%s: unsupported master key size.",
2893 		 function );
2894 
2895 		return( -1 );
2896 	}
2897 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2898 	if( libcthreads_read_write_lock_grab_for_write(
2899 	     internal_volume->read_write_lock,
2900 	     error ) != 1 )
2901 	{
2902 		libcerror_error_set(
2903 		 error,
2904 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2905 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2906 		 "%s: unable to grab read/write lock for writing.",
2907 		 function );
2908 
2909 		return( -1 );
2910 	}
2911 #endif
2912 	if( memory_set(
2913 	     internal_volume->master_key,
2914 	     0,
2915 	     64  ) == NULL )
2916 	{
2917 		libcerror_error_set(
2918 		 error,
2919 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
2920 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
2921 		 "%s: unable to clear master key.",
2922 		 function );
2923 
2924 		goto on_error;
2925 	}
2926 	if( memory_copy(
2927 	     internal_volume->master_key,
2928 	     master_key,
2929 	     master_key_size ) == NULL )
2930 	{
2931 		libcerror_error_set(
2932 		 error,
2933 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
2934 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2935 		 "%s: unable to copy master key.",
2936 		 function );
2937 
2938 		goto on_error;
2939 	}
2940 	internal_volume->master_key_size = (uint32_t) master_key_size;
2941 
2942 	internal_volume->keys_are_set = 1;
2943 
2944 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2945 	if( libcthreads_read_write_lock_release_for_write(
2946 	     internal_volume->read_write_lock,
2947 	     error ) != 1 )
2948 	{
2949 		libcerror_error_set(
2950 		 error,
2951 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2952 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2953 		 "%s: unable to release read/write lock for writing.",
2954 		 function );
2955 
2956 		return( -1 );
2957 	}
2958 #endif
2959 	return( 1 );
2960 
2961 on_error:
2962 	memory_set(
2963 	 internal_volume->master_key,
2964 	 0,
2965 	 32 );
2966 
2967 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
2968 	libcthreads_read_write_lock_release_for_write(
2969 	 internal_volume->read_write_lock,
2970 	 NULL );
2971 #endif
2972 	return( -1 );
2973 }
2974 
2975 /* Sets the keys
2976  * This function needs to be used before one of the open functions
2977  * Returns 1 if successful or -1 on error
2978  */
libluksde_volume_set_keys(libluksde_volume_t * volume,const uint8_t * master_key,size_t master_key_size,libcerror_error_t ** error)2979 int libluksde_volume_set_keys(
2980      libluksde_volume_t *volume,
2981      const uint8_t *master_key,
2982      size_t master_key_size,
2983      libcerror_error_t **error )
2984 {
2985 	libluksde_internal_volume_t *internal_volume = NULL;
2986 	static char *function                        = "libluksde_volume_set_keys";
2987 
2988 	if( volume == NULL )
2989 	{
2990 		libcerror_error_set(
2991 		 error,
2992 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2993 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2994 		 "%s: invalid volume.",
2995 		 function );
2996 
2997 		return( -1 );
2998 	}
2999 	internal_volume = (libluksde_internal_volume_t *) volume;
3000 
3001 	if( internal_volume->file_io_handle != NULL )
3002 	{
3003 		libcerror_error_set(
3004 		 error,
3005 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3006 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3007 		 "%s: invalid volume - file IO handle already set.",
3008 		 function );
3009 
3010 		return( -1 );
3011 	}
3012 	if( master_key == NULL )
3013 	{
3014 		libcerror_error_set(
3015 		 error,
3016 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3017 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3018 		 "%s: invalid master key.",
3019 		 function );
3020 
3021 		return( -1 );
3022 	}
3023 	if( ( master_key_size != 16 )
3024 	 && ( master_key_size != 32 ) )
3025 	{
3026 		libcerror_error_set(
3027 		 error,
3028 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3029 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3030 		 "%s: unsupported master key size.",
3031 		 function );
3032 
3033 		return( -1 );
3034 	}
3035 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
3036 	if( libcthreads_read_write_lock_grab_for_write(
3037 	     internal_volume->read_write_lock,
3038 	     error ) != 1 )
3039 	{
3040 		libcerror_error_set(
3041 		 error,
3042 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3043 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3044 		 "%s: unable to grab read/write lock for writing.",
3045 		 function );
3046 
3047 		return( -1 );
3048 	}
3049 #endif
3050 	if( master_key_size < 32 )
3051 	{
3052 		if( memory_set(
3053 		     internal_volume->master_key,
3054 		     0,
3055 		     32  ) == NULL )
3056 		{
3057 			libcerror_error_set(
3058 			 error,
3059 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
3060 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
3061 			 "%s: unable to clear master key.",
3062 			 function );
3063 
3064 			goto on_error;
3065 		}
3066 	}
3067 	if( memory_copy(
3068 	     internal_volume->master_key,
3069 	     master_key,
3070 	     master_key_size ) == NULL )
3071 	{
3072 		libcerror_error_set(
3073 		 error,
3074 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
3075 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
3076 		 "%s: unable to copy master key.",
3077 		 function );
3078 
3079 		goto on_error;
3080 	}
3081 	internal_volume->master_key_size = (uint32_t) master_key_size;
3082 
3083 	internal_volume->keys_are_set = 1;
3084 
3085 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
3086 	if( libcthreads_read_write_lock_release_for_write(
3087 	     internal_volume->read_write_lock,
3088 	     error ) != 1 )
3089 	{
3090 		libcerror_error_set(
3091 		 error,
3092 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3093 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3094 		 "%s: unable to release read/write lock for writing.",
3095 		 function );
3096 
3097 		return( -1 );
3098 	}
3099 #endif
3100 	return( 1 );
3101 
3102 on_error:
3103 	memory_set(
3104 	 internal_volume->master_key,
3105 	 0,
3106 	 32 );
3107 
3108 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
3109 	libcthreads_read_write_lock_release_for_write(
3110 	 internal_volume->read_write_lock,
3111 	 NULL );
3112 #endif
3113 	return( -1 );
3114 }
3115 
3116 /* Sets an UTF-8 formatted password
3117  * This function needs to be used before one of the open functions
3118  * Returns 1 if successful, 0 if password is invalid or -1 on error
3119  */
libluksde_volume_set_utf8_password(libluksde_volume_t * volume,const uint8_t * utf8_string,size_t utf8_string_length,libcerror_error_t ** error)3120 int libluksde_volume_set_utf8_password(
3121      libluksde_volume_t *volume,
3122      const uint8_t *utf8_string,
3123      size_t utf8_string_length,
3124      libcerror_error_t **error )
3125 {
3126 	libluksde_internal_volume_t *internal_volume = NULL;
3127 	static char *function                        = "libluksde_volume_set_utf8_password";
3128 
3129 	if( volume == NULL )
3130 	{
3131 		libcerror_error_set(
3132 		 error,
3133 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3134 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3135 		 "%s: invalid volume.",
3136 		 function );
3137 
3138 		return( -1 );
3139 	}
3140 	internal_volume = (libluksde_internal_volume_t *) volume;
3141 
3142 	if( internal_volume->file_io_handle != NULL )
3143 	{
3144 		libcerror_error_set(
3145 		 error,
3146 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3147 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3148 		 "%s: invalid volume - file IO handle already set.",
3149 		 function );
3150 
3151 		return( -1 );
3152 	}
3153 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
3154 	if( libcthreads_read_write_lock_grab_for_write(
3155 	     internal_volume->read_write_lock,
3156 	     error ) != 1 )
3157 	{
3158 		libcerror_error_set(
3159 		 error,
3160 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3161 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3162 		 "%s: unable to grab read/write lock for writing.",
3163 		 function );
3164 
3165 		return( -1 );
3166 	}
3167 #endif
3168 	if( internal_volume->user_password != NULL )
3169 	{
3170 		if( memory_set(
3171 		     internal_volume->user_password,
3172 		     0,
3173 		     internal_volume->user_password_size ) == NULL )
3174 		{
3175 			libcerror_error_set(
3176 			 error,
3177 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
3178 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
3179 			 "%s: unable to user password.",
3180 			 function );
3181 
3182 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
3183 			libcthreads_read_write_lock_release_for_write(
3184 			 internal_volume->read_write_lock,
3185 			 NULL );
3186 #endif
3187 			return( -1 );
3188 		}
3189 		memory_free(
3190 		 internal_volume->user_password );
3191 
3192 		internal_volume->user_password      = NULL;
3193 		internal_volume->user_password_size = 0;
3194 	}
3195 	if( libuna_byte_stream_size_from_utf8(
3196 	     utf8_string,
3197 	     utf8_string_length,
3198 	     LIBLUKSDE_CODEPAGE_US_ASCII,
3199 	     &( internal_volume->user_password_size ),
3200 	     error ) != 1 )
3201 	{
3202 		libcerror_error_set(
3203 		 error,
3204 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3205 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3206 		 "%s: unable to set password size.",
3207 		 function );
3208 
3209 		goto on_error;
3210 	}
3211 	internal_volume->user_password_size += 1;
3212 
3213 	internal_volume->user_password = (uint8_t *) memory_allocate(
3214 	                                              sizeof( uint8_t ) * internal_volume->user_password_size );
3215 
3216 	if( internal_volume->user_password == NULL )
3217 	{
3218 		libcerror_error_set(
3219 		 error,
3220 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3221 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3222 		 "%s: unable to create user password.",
3223 		 function );
3224 
3225 		goto on_error;
3226 	}
3227 	if( libuna_byte_stream_copy_from_utf8(
3228 	     internal_volume->user_password,
3229 	     internal_volume->user_password_size,
3230 	     LIBLUKSDE_CODEPAGE_US_ASCII,
3231 	     utf8_string,
3232 	     utf8_string_length,
3233 	     error ) != 1 )
3234 	{
3235 		libcerror_error_set(
3236 		 error,
3237 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3238 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3239 		 "%s: unable to copy user password.",
3240 		 function );
3241 
3242 		goto on_error;
3243 	}
3244 	internal_volume->user_password[ internal_volume->user_password_size - 1 ] = 0;
3245 
3246 	internal_volume->user_password_is_set = 1;
3247 
3248 #if defined( HAVE_DEBUG_OUTPUT )
3249 	if( libcnotify_verbose != 0 )
3250 	{
3251 		libcnotify_printf(
3252 		 "%s: user password: %s\n",
3253 		 function,
3254 		 internal_volume->user_password );
3255 	}
3256 #endif
3257 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
3258 	if( libcthreads_read_write_lock_release_for_write(
3259 	     internal_volume->read_write_lock,
3260 	     error ) != 1 )
3261 	{
3262 		libcerror_error_set(
3263 		 error,
3264 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3265 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3266 		 "%s: unable to release read/write lock for writing.",
3267 		 function );
3268 
3269 		return( -1 );
3270 	}
3271 #endif
3272 	return( 1 );
3273 
3274 on_error:
3275 	if( internal_volume->user_password != NULL )
3276 	{
3277 		memory_set(
3278 		 internal_volume->user_password,
3279 		 0,
3280 		 internal_volume->user_password_size );
3281 		memory_free(
3282 		 internal_volume->user_password );
3283 
3284 		internal_volume->user_password = NULL;
3285 	}
3286 	internal_volume->user_password_size = 0;
3287 
3288 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
3289 	libcthreads_read_write_lock_release_for_write(
3290 	 internal_volume->read_write_lock,
3291 	 NULL );
3292 #endif
3293 	return( -1 );
3294 }
3295 
3296 /* Sets an UTF-16 formatted password
3297  * This function needs to be used before one of the open functions
3298  * Returns 1 if successful, 0 if password is invalid or -1 on error
3299  */
libluksde_volume_set_utf16_password(libluksde_volume_t * volume,const uint16_t * utf16_string,size_t utf16_string_length,libcerror_error_t ** error)3300 int libluksde_volume_set_utf16_password(
3301      libluksde_volume_t *volume,
3302      const uint16_t *utf16_string,
3303      size_t utf16_string_length,
3304      libcerror_error_t **error )
3305 {
3306 	libluksde_internal_volume_t *internal_volume = NULL;
3307 	static char *function                        = "libluksde_volume_set_utf16_password";
3308 
3309 	if( volume == NULL )
3310 	{
3311 		libcerror_error_set(
3312 		 error,
3313 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3314 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3315 		 "%s: invalid volume.",
3316 		 function );
3317 
3318 		return( -1 );
3319 	}
3320 	internal_volume = (libluksde_internal_volume_t *) volume;
3321 
3322 	if( internal_volume->file_io_handle != NULL )
3323 	{
3324 		libcerror_error_set(
3325 		 error,
3326 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3327 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3328 		 "%s: invalid volume - file IO handle already set.",
3329 		 function );
3330 
3331 		return( -1 );
3332 	}
3333 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
3334 	if( libcthreads_read_write_lock_grab_for_write(
3335 	     internal_volume->read_write_lock,
3336 	     error ) != 1 )
3337 	{
3338 		libcerror_error_set(
3339 		 error,
3340 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3341 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3342 		 "%s: unable to grab read/write lock for writing.",
3343 		 function );
3344 
3345 		return( -1 );
3346 	}
3347 #endif
3348 	if( internal_volume->user_password != NULL )
3349 	{
3350 		if( memory_set(
3351 		     internal_volume->user_password,
3352 		     0,
3353 		     internal_volume->user_password_size ) == NULL )
3354 		{
3355 			libcerror_error_set(
3356 			 error,
3357 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
3358 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
3359 			 "%s: unable to user password.",
3360 			 function );
3361 
3362 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
3363 			libcthreads_read_write_lock_release_for_write(
3364 			 internal_volume->read_write_lock,
3365 			 NULL );
3366 #endif
3367 			return( -1 );
3368 		}
3369 		memory_free(
3370 		 internal_volume->user_password );
3371 
3372 		internal_volume->user_password      = NULL;
3373 		internal_volume->user_password_size = 0;
3374 	}
3375 	if( libuna_byte_stream_size_from_utf16(
3376 	     utf16_string,
3377 	     utf16_string_length,
3378 	     LIBLUKSDE_CODEPAGE_US_ASCII,
3379 	     &( internal_volume->user_password_size ),
3380 	     error ) != 1 )
3381 	{
3382 		libcerror_error_set(
3383 		 error,
3384 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3385 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3386 		 "%s: unable to set password length.",
3387 		 function );
3388 
3389 		goto on_error;
3390 	}
3391 	internal_volume->user_password_size += 1;
3392 
3393 	internal_volume->user_password = (uint8_t *) memory_allocate(
3394 	                                              sizeof( uint8_t ) * internal_volume->user_password_size );
3395 
3396 	if( internal_volume->user_password == NULL )
3397 	{
3398 		libcerror_error_set(
3399 		 error,
3400 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3401 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3402 		 "%s: unable to create user password.",
3403 		 function );
3404 
3405 		goto on_error;
3406 	}
3407 	if( libuna_byte_stream_copy_from_utf16(
3408 	     internal_volume->user_password,
3409 	     internal_volume->user_password_size,
3410 	     LIBLUKSDE_CODEPAGE_US_ASCII,
3411 	     utf16_string,
3412 	     utf16_string_length,
3413 	     error ) != 1 )
3414 	{
3415 		libcerror_error_set(
3416 		 error,
3417 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3418 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3419 		 "%s: unable to copy user password.",
3420 		 function );
3421 
3422 		goto on_error;
3423 	}
3424 	internal_volume->user_password[ internal_volume->user_password_size - 1 ] = 0;
3425 
3426 	internal_volume->user_password_is_set = 1;
3427 
3428 #if defined( HAVE_DEBUG_OUTPUT )
3429 	if( libcnotify_verbose != 0 )
3430 	{
3431 		libcnotify_printf(
3432 		 "%s: user password: %s\n",
3433 		 function,
3434 		 internal_volume->user_password );
3435 	}
3436 #endif
3437 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
3438 	if( libcthreads_read_write_lock_release_for_write(
3439 	     internal_volume->read_write_lock,
3440 	     error ) != 1 )
3441 	{
3442 		libcerror_error_set(
3443 		 error,
3444 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3445 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3446 		 "%s: unable to release read/write lock for writing.",
3447 		 function );
3448 
3449 		return( -1 );
3450 	}
3451 #endif
3452 	return( 1 );
3453 
3454 on_error:
3455 	if( internal_volume->user_password != NULL )
3456 	{
3457 		memory_set(
3458 		 internal_volume->user_password,
3459 		 0,
3460 		 internal_volume->user_password_size );
3461 		memory_free(
3462 		 internal_volume->user_password );
3463 
3464 		internal_volume->user_password = NULL;
3465 	}
3466 	internal_volume->user_password_size = 0;
3467 
3468 #if defined( HAVE_LIBLUKSDE_MULTI_THREAD_SUPPORT )
3469 	libcthreads_read_write_lock_release_for_write(
3470 	 internal_volume->read_write_lock,
3471 	 NULL );
3472 #endif
3473 	return( -1 );
3474 }
3475 
3476