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