1 /*
2  * Metadata entry functions
3  *
4  * Copyright (C) 2011-2021, Joachim Metz <joachim.metz@gmail.com>
5  *
6  * Refer to AUTHORS for acknowledgements.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <common.h>
23 #include <byte_stream.h>
24 #include <memory.h>
25 #include <narrow_string.h>
26 #include <system_string.h>
27 #include <types.h>
28 #include <wide_string.h>
29 
30 #include "libbde_debug.h"
31 #include "libbde_definitions.h"
32 #include "libbde_libcerror.h"
33 #include "libbde_libcnotify.h"
34 #include "libbde_libuna.h"
35 #include "libbde_metadata_entry.h"
36 
37 #include "bde_metadata.h"
38 
39 const uint8_t libbde_metadata_entry_empty[ 8 ] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
40 
41 /* Creates a metadata entry
42  * Make sure the value metadata entry is referencing, is set to NULL
43  * Returns 1 if successful or -1 on error
44  */
libbde_metadata_entry_initialize(libbde_metadata_entry_t ** metadata_entry,libcerror_error_t ** error)45 int libbde_metadata_entry_initialize(
46      libbde_metadata_entry_t **metadata_entry,
47      libcerror_error_t **error )
48 {
49 	static char *function = "libbde_metadata_entry_initialize";
50 
51 	if( metadata_entry == NULL )
52 	{
53 		libcerror_error_set(
54 		 error,
55 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
56 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
57 		 "%s: invalid metadata entry.",
58 		 function );
59 
60 		return( -1 );
61 	}
62 	if( *metadata_entry != NULL )
63 	{
64 		libcerror_error_set(
65 		 error,
66 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
67 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
68 		 "%s: invalid metadata entry value already set.",
69 		 function );
70 
71 		return( -1 );
72 	}
73 	*metadata_entry = memory_allocate_structure(
74 	                   libbde_metadata_entry_t );
75 
76 	if( *metadata_entry == NULL )
77 	{
78 		libcerror_error_set(
79 		 error,
80 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
81 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
82 		 "%s: unable to create metadata entry.",
83 		 function );
84 
85 		goto on_error;
86 	}
87 	if( memory_set(
88 	     *metadata_entry,
89 	     0,
90 	     sizeof( libbde_metadata_entry_t ) ) == NULL )
91 	{
92 		libcerror_error_set(
93 		 error,
94 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
95 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
96 		 "%s: unable to clear metadata entry.",
97 		 function );
98 
99 		goto on_error;
100 	}
101 	return( 1 );
102 
103 on_error:
104 	if( *metadata_entry != NULL )
105 	{
106 		memory_free(
107 		 *metadata_entry );
108 
109 		*metadata_entry = NULL;
110 	}
111 	return( -1 );
112 }
113 
114 /* Frees a metadata entry
115  * Returns 1 if successful or -1 on error
116  */
libbde_metadata_entry_free(libbde_metadata_entry_t ** metadata_entry,libcerror_error_t ** error)117 int libbde_metadata_entry_free(
118      libbde_metadata_entry_t **metadata_entry,
119      libcerror_error_t **error )
120 {
121 	static char *function = "libbde_metadata_entry_free";
122 
123 	if( metadata_entry == NULL )
124 	{
125 		libcerror_error_set(
126 		 error,
127 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
128 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
129 		 "%s: invalid metadata entry.",
130 		 function );
131 
132 		return( -1 );
133 	}
134 	if( *metadata_entry != NULL )
135 	{
136 		if( ( *metadata_entry )->value_data != NULL )
137 		{
138 			memory_free(
139 			 ( *metadata_entry )->value_data );
140 		}
141 		memory_free(
142 		 *metadata_entry );
143 
144 		*metadata_entry = NULL;
145 	}
146 	return( 1 );
147 }
148 
149 /* Reads a metadata entry from the metadata data
150  * Returns the number of bytes read if successful or -1 on error
151  */
libbde_metadata_entry_read(libbde_metadata_entry_t * metadata_entry,const uint8_t * fve_metadata,size_t fve_metadata_size,libcerror_error_t ** error)152 ssize_t libbde_metadata_entry_read(
153          libbde_metadata_entry_t *metadata_entry,
154          const uint8_t *fve_metadata,
155          size_t fve_metadata_size,
156          libcerror_error_t **error )
157 {
158 	static char *function = "libbde_metadata_entry_read";
159 	uint16_t entry_size   = 0;
160 	uint16_t version      = 0;
161 
162 	if( metadata_entry == NULL )
163 	{
164 		libcerror_error_set(
165 		 error,
166 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
167 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
168 		 "%s: invalid metadata entry.",
169 		 function );
170 
171 		return( -1 );
172 	}
173 	if( fve_metadata == NULL )
174 	{
175 		libcerror_error_set(
176 		 error,
177 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
178 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
179 		 "%s: invalid FVE metadata.",
180 		 function );
181 
182 		return( -1 );
183 	}
184 	if( fve_metadata_size < sizeof( bde_metadata_entry_v1_t ) )
185 	{
186 		libcerror_error_set(
187 		 error,
188 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
189 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
190 		 "%s: invalid FVE metadata size value too small.",
191 		 function );
192 
193 		return( -1 );
194 	}
195 #if defined( HAVE_DEBUG_OUTPUT )
196 	if( libcnotify_verbose != 0 )
197 	{
198 		libcnotify_printf(
199 		 "%s: FVE metadata entry:\n",
200 		 function );
201 		libcnotify_print_data(
202 		 fve_metadata,
203 		 sizeof( bde_metadata_entry_v1_t ),
204 		 0 );
205 	}
206 #endif
207 	byte_stream_copy_to_uint16_little_endian(
208 	 ( (bde_metadata_entry_v1_t *) fve_metadata )->size,
209 	 entry_size );
210 
211 	byte_stream_copy_to_uint16_little_endian(
212 	 ( (bde_metadata_entry_v1_t *) fve_metadata )->type,
213 	 metadata_entry->type );
214 
215 	byte_stream_copy_to_uint16_little_endian(
216 	 ( (bde_metadata_entry_v1_t *) fve_metadata )->value_type,
217 	 metadata_entry->value_type );
218 
219 	byte_stream_copy_to_uint16_little_endian(
220 	 ( (bde_metadata_entry_v1_t *) fve_metadata )->version,
221 	 version );
222 
223 #if defined( HAVE_DEBUG_OUTPUT )
224 	if( libcnotify_verbose != 0 )
225 	{
226 		libcnotify_printf(
227 		 "%s: entry size\t\t\t\t\t: %" PRIu16 "\n",
228 		 function,
229 		 entry_size );\
230 
231 		libcnotify_printf(
232 		 "%s: entry type\t\t\t\t\t: 0x%04" PRIx16 " (%s)\n",
233 		 function,
234 		 metadata_entry->type,
235 		 libbde_debug_print_entry_type(
236 		  metadata_entry->type ) );
237 
238 		libcnotify_printf(
239 		 "%s: value type\t\t\t\t\t: 0x%04" PRIx16 " (%s)\n",
240 		 function,
241 		 metadata_entry->value_type,
242 		 libbde_debug_print_value_type(
243 		  metadata_entry->value_type ) );
244 
245 		libcnotify_printf(
246 		 "%s: version\t\t\t\t\t: %" PRIu16 "\n",
247 		 function,
248 		 version );
249 	}
250 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
251 
252 	if( version != 1 )
253 	{
254 		libcerror_error_set(
255 		 error,
256 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
257 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
258 		 "%s: unsupported FVE metadata entry version.",
259 		 function );
260 
261 		return( -1 );
262 	}
263 	if( ( entry_size < sizeof( bde_metadata_entry_v1_t ) )
264 	 || ( entry_size > fve_metadata_size ) )
265 	{
266 		libcerror_error_set(
267 		 error,
268 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
269 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
270 		 "%s: FVE metadata entry size value out of bounds.",
271 		 function );
272 
273 		return( -1 );
274 	}
275 	fve_metadata += sizeof( bde_metadata_entry_v1_t );
276 
277 	metadata_entry->value_data_size = entry_size - (uint16_t) sizeof( bde_metadata_entry_v1_t );
278 
279 	metadata_entry->value_data = (uint8_t *) memory_allocate(
280 	                                          sizeof( uint8_t ) * metadata_entry->value_data_size );
281 
282 	if( metadata_entry->value_data == NULL )
283 	{
284 		libcerror_error_set(
285 		 error,
286 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
287 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
288 		 "%s: unable to create value data.",
289 		 function );
290 
291 		goto on_error;
292 	}
293 	if( memory_copy(
294 	     metadata_entry->value_data,
295 	     fve_metadata,
296 	     metadata_entry->value_data_size ) == NULL )
297 	{
298 		libcerror_error_set(
299 		 error,
300 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
301 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
302 		 "%s: unable to copy value data.",
303 		 function );
304 
305 		goto on_error;
306 	}
307 #if defined( HAVE_DEBUG_OUTPUT )
308 	if( libcnotify_verbose != 0 )
309 	{
310 		libcnotify_printf(
311 		 "%s: FVE metadata entry data:\n",
312 		 function );
313 		libcnotify_print_data(
314 		 metadata_entry->value_data,
315 		 (size_t) metadata_entry->value_data_size,
316 		 0 );
317 	}
318 #endif
319 	return( (ssize_t) entry_size );
320 
321 on_error:
322 	if( metadata_entry->value_data != NULL )
323 	{
324 		memory_free(
325 		 metadata_entry->value_data );
326 
327 		metadata_entry->value_data = NULL;
328 	}
329 	return( -1 );
330 }
331 
332 /* Reads a string from the metadata entry
333  * Returns the 1 if successful or -1 on error
334  */
libbde_metadata_entry_read_string(libbde_metadata_entry_t * metadata_entry,libcerror_error_t ** error)335 int libbde_metadata_entry_read_string(
336      libbde_metadata_entry_t *metadata_entry,
337      libcerror_error_t **error )
338 {
339 	static char *function            = "libbde_metadata_entry_read_string";
340 
341 #if defined( HAVE_DEBUG_OUTPUT )
342 	system_character_t *value_string = NULL;
343 	size_t value_string_size         = 0;
344 	int result                       = 0;
345 #endif
346 
347 	if( metadata_entry == NULL )
348 	{
349 		libcerror_error_set(
350 		 error,
351 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
352 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
353 		 "%s: invalid metadata entry.",
354 		 function );
355 
356 		return( -1 );
357 	}
358 	if( metadata_entry->value_type != LIBBDE_VALUE_TYPE_UNICODE_STRING )
359 	{
360 		libcerror_error_set(
361 		 error,
362 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
363 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
364 		 "%s: invalid metadata entry - unsupported value type: 0x%04" PRIx16 ".",
365 		 function,
366 		 metadata_entry->value_type );
367 
368 		return( -1 );
369 	}
370 #if defined( HAVE_DEBUG_OUTPUT )
371 	if( libcnotify_verbose != 0 )
372 	{
373 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
374 		result = libuna_utf16_string_size_from_utf16_stream(
375 			  metadata_entry->value_data,
376 			  (size_t) metadata_entry->value_data_size,
377 			  LIBUNA_ENDIAN_LITTLE,
378 			  &value_string_size,
379 			  error );
380 #else
381 		result = libuna_utf8_string_size_from_utf16_stream(
382 			  metadata_entry->value_data,
383 			  (size_t) metadata_entry->value_data_size,
384 			  LIBUNA_ENDIAN_LITTLE,
385 			  &value_string_size,
386 			  error );
387 #endif
388 		if( result != 1 )
389 		{
390 			libcerror_error_set(
391 			 error,
392 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
393 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
394 			 "%s: unable to determine size of name string.",
395 			 function );
396 
397 			return( -1 );
398 		}
399 		if( value_string_size > 0 )
400 		{
401 			if( ( value_string_size > (size_t) SSIZE_MAX )
402 			 || ( ( sizeof( system_character_t ) * value_string_size )  > (size_t) SSIZE_MAX ) )
403 			{
404 				libcerror_error_set(
405 				 error,
406 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
407 				 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
408 				 "%s: invalid value string size value exceeds maximum.",
409 				 function );
410 
411 				return( -1 );
412 			}
413 			value_string = system_string_allocate(
414 					value_string_size );
415 
416 			if( value_string == NULL )
417 			{
418 				libcerror_error_set(
419 				 error,
420 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
421 				 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
422 				 "%s: unable to create name string.",
423 				 function );
424 
425 				return( -1 );
426 			}
427 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
428 			result = libuna_utf16_string_copy_from_utf16_stream(
429 				  (libuna_utf16_character_t *) value_string,
430 				  value_string_size,
431 				  metadata_entry->value_data,
432 				  (size_t) metadata_entry->value_data_size,
433 				  LIBUNA_ENDIAN_LITTLE,
434 				  error );
435 #else
436 			result = libuna_utf8_string_copy_from_utf16_stream(
437 				  (libuna_utf8_character_t *) value_string,
438 				  value_string_size,
439 				  metadata_entry->value_data,
440 				  (size_t) metadata_entry->value_data_size,
441 				  LIBUNA_ENDIAN_LITTLE,
442 				  error );
443 #endif
444 			if( result != 1 )
445 			{
446 				libcerror_error_set(
447 				 error,
448 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
449 				 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
450 				 "%s: unable to set name string.",
451 				 function );
452 
453 				memory_free(
454 				 value_string );
455 
456 				return( -1 );
457 			}
458 			libcnotify_printf(
459 			 "%s: string\t\t\t\t: %" PRIs_SYSTEM "\n",
460 			 function,
461 			 value_string );
462 
463 			memory_free(
464 			 value_string );
465 		}
466 		libcnotify_printf(
467 		 "\n" );
468 	}
469 #endif
470 	return( 1 );
471 }
472 
473