/src/libewf/libewf/libewf_ltree_section.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Ltree section functions |
3 | | * |
4 | | * Copyright (C) 2006-2023, 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 <types.h> |
27 | | |
28 | | #include "libewf_checksum.h" |
29 | | #include "libewf_debug.h" |
30 | | #include "libewf_definitions.h" |
31 | | #include "libewf_hash_sections.h" |
32 | | #include "libewf_io_handle.h" |
33 | | #include "libewf_libbfio.h" |
34 | | #include "libewf_libcerror.h" |
35 | | #include "libewf_libcnotify.h" |
36 | | #include "libewf_libhmac.h" |
37 | | #include "libewf_ltree_section.h" |
38 | | #include "libewf_section.h" |
39 | | #include "libewf_section_descriptor.h" |
40 | | |
41 | | #include "ewf_ltree.h" |
42 | | |
43 | | /* Reads a version 1 ltree section or version 2 singles files data section |
44 | | * single_files_data will be set to a pointer within the section data |
45 | | * Returns 1 if successful or -1 on error |
46 | | */ |
47 | | int libewf_ltree_section_read_data( |
48 | | const uint8_t *data, |
49 | | size_t data_size, |
50 | | uint8_t format_version, |
51 | | uint8_t **single_files_data, |
52 | | size_t *single_files_data_size, |
53 | | libcerror_error_t **error ) |
54 | 48 | { |
55 | 48 | uint8_t calculated_md5_hash[ 16 ]; |
56 | | |
57 | 48 | uint8_t ltree_header_data[ sizeof( ewf_ltree_header_t ) ]; |
58 | | |
59 | 48 | static char *function = "libewf_ltree_section_read_data"; |
60 | 48 | size_t data_offset = 0; |
61 | 48 | uint64_t stored_data_size = 0; |
62 | 48 | uint32_t calculated_checksum = 0; |
63 | 48 | uint32_t stored_checksum = 0; |
64 | | |
65 | | #if defined( HAVE_DEBUG_OUTPUT ) |
66 | | size_t trailing_data_size = 0; |
67 | | #endif |
68 | | |
69 | 48 | if( data == NULL ) |
70 | 0 | { |
71 | 0 | libcerror_error_set( |
72 | 0 | error, |
73 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
74 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
75 | 0 | "%s: missing data.", |
76 | 0 | function ); |
77 | |
|
78 | 0 | return( -1 ); |
79 | 0 | } |
80 | 48 | if( data_size > (size_t) SSIZE_MAX ) |
81 | 0 | { |
82 | 0 | libcerror_error_set( |
83 | 0 | error, |
84 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
85 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, |
86 | 0 | "%s: invalid data size value exceeds maximum.", |
87 | 0 | function ); |
88 | |
|
89 | 0 | return( -1 ); |
90 | 0 | } |
91 | 48 | if( ( format_version != 1 ) |
92 | 48 | && ( format_version != 2 ) ) |
93 | 0 | { |
94 | 0 | libcerror_error_set( |
95 | 0 | error, |
96 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
97 | 0 | LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, |
98 | 0 | "%s: unsupported format version.", |
99 | 0 | function ); |
100 | |
|
101 | 0 | return( -1 ); |
102 | 0 | } |
103 | 48 | if( single_files_data == NULL ) |
104 | 0 | { |
105 | 0 | libcerror_error_set( |
106 | 0 | error, |
107 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
108 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
109 | 0 | "%s: invalid single files data.", |
110 | 0 | function ); |
111 | |
|
112 | 0 | return( -1 ); |
113 | 0 | } |
114 | 48 | if( *single_files_data != NULL ) |
115 | 0 | { |
116 | 0 | libcerror_error_set( |
117 | 0 | error, |
118 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
119 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
120 | 0 | "%s: invalid single files data value already set.", |
121 | 0 | function ); |
122 | |
|
123 | 0 | return( -1 ); |
124 | 0 | } |
125 | 48 | if( single_files_data_size == NULL ) |
126 | 0 | { |
127 | 0 | libcerror_error_set( |
128 | 0 | error, |
129 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
130 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
131 | 0 | "%s: invalid single files data size.", |
132 | 0 | function ); |
133 | |
|
134 | 0 | return( -1 ); |
135 | 0 | } |
136 | 48 | if( format_version == 1 ) |
137 | 48 | { |
138 | 48 | if( data_size < sizeof( ewf_ltree_header_t ) ) |
139 | 0 | { |
140 | 0 | libcerror_error_set( |
141 | 0 | error, |
142 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
143 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
144 | 0 | "%s: invalid section size value out of bounds - insufficient space for header.", |
145 | 0 | function ); |
146 | |
|
147 | 0 | return( -1 ); |
148 | 0 | } |
149 | | #if defined( HAVE_DEBUG_OUTPUT ) |
150 | | if( libcnotify_verbose != 0 ) |
151 | | { |
152 | | libcnotify_printf( |
153 | | "%s: ltree header data:\n", |
154 | | function ); |
155 | | libcnotify_print_data( |
156 | | data, |
157 | | sizeof( ewf_ltree_header_t ), |
158 | | 0 ); |
159 | | } |
160 | | #endif |
161 | 48 | byte_stream_copy_to_uint64_little_endian( |
162 | 48 | ( (ewf_ltree_header_t *) data )->data_size, |
163 | 48 | stored_data_size ); |
164 | | |
165 | 48 | byte_stream_copy_to_uint32_little_endian( |
166 | 48 | ( (ewf_ltree_header_t *) data )->checksum, |
167 | 48 | stored_checksum ); |
168 | | |
169 | | #if defined( HAVE_DEBUG_OUTPUT ) |
170 | | if( libcnotify_verbose != 0 ) |
171 | | { |
172 | | libcnotify_printf( |
173 | | "%s: integrity hash:\n", |
174 | | function ); |
175 | | libcnotify_print_data( |
176 | | ( (ewf_ltree_header_t *) data )->integrity_hash, |
177 | | 16, |
178 | | 0 ); |
179 | | |
180 | | libcnotify_printf( |
181 | | "%s: data size\t\t\t\t\t: %" PRIu64 "\n", |
182 | | function, |
183 | | stored_data_size ); |
184 | | |
185 | | libcnotify_printf( |
186 | | "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", |
187 | | function, |
188 | | stored_checksum ); |
189 | | |
190 | | libcnotify_printf( |
191 | | "%s: unknown1:\n", |
192 | | function ); |
193 | | libcnotify_print_data( |
194 | | ( (ewf_ltree_header_t *) data )->unknown1, |
195 | | 20, |
196 | | 0 ); |
197 | | } |
198 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
199 | | |
200 | 48 | if( memory_copy( |
201 | 48 | ltree_header_data, |
202 | 48 | data, |
203 | 48 | sizeof( ewf_ltree_header_t ) ) == NULL ) |
204 | 0 | { |
205 | 0 | libcerror_error_set( |
206 | 0 | error, |
207 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
208 | 0 | LIBCERROR_MEMORY_ERROR_COPY_FAILED, |
209 | 0 | "%s: unable to copy ltree header data.", |
210 | 0 | function ); |
211 | |
|
212 | 0 | return( -1 ); |
213 | 0 | } |
214 | 48 | byte_stream_copy_from_uint32_little_endian( |
215 | 48 | ( (ewf_ltree_header_t *) ltree_header_data )->checksum, |
216 | 48 | 0 ); |
217 | | |
218 | 48 | if( libewf_checksum_calculate_adler32( |
219 | 48 | &calculated_checksum, |
220 | 48 | ltree_header_data, |
221 | 48 | sizeof( ewf_ltree_header_t ), |
222 | 48 | 1, |
223 | 48 | error ) != 1 ) |
224 | 0 | { |
225 | 0 | libcerror_error_set( |
226 | 0 | error, |
227 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
228 | 0 | LIBCERROR_RUNTIME_ERROR_SET_FAILED, |
229 | 0 | "%s: unable to calculate header checksum.", |
230 | 0 | function ); |
231 | |
|
232 | 0 | return( -1 ); |
233 | 0 | } |
234 | 48 | if( stored_checksum != calculated_checksum ) |
235 | 40 | { |
236 | 40 | libcerror_error_set( |
237 | 40 | error, |
238 | 40 | LIBCERROR_ERROR_DOMAIN_INPUT, |
239 | 40 | LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH, |
240 | 40 | "%s: header checksum does not match (stored: 0x%08" PRIx32 ", calculated: 0x%08" PRIx32 ").", |
241 | 40 | function, |
242 | 40 | stored_checksum, |
243 | 40 | calculated_checksum ); |
244 | | |
245 | 40 | return( -1 ); |
246 | 40 | } |
247 | 8 | data_offset += sizeof( ewf_ltree_header_t ); |
248 | 8 | data_size -= sizeof( ewf_ltree_header_t ); |
249 | | |
250 | 8 | if( stored_data_size > (uint64_t) data_size ) |
251 | 8 | { |
252 | 8 | libcerror_error_set( |
253 | 8 | error, |
254 | 8 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
255 | 8 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
256 | 8 | "%s: invalid section size value out of bounds - insufficient space for entries data.", |
257 | 8 | function ); |
258 | | |
259 | 8 | return( -1 ); |
260 | 8 | } |
261 | 0 | *single_files_data = (uint8_t *) &( data[ data_offset ] ); |
262 | 0 | *single_files_data_size = (size_t) stored_data_size; |
263 | 0 | } |
264 | 0 | else if( format_version == 2 ) |
265 | 0 | { |
266 | 0 | *single_files_data = (uint8_t *) data; |
267 | 0 | *single_files_data_size = data_size; |
268 | 0 | } |
269 | | #if defined( HAVE_DEBUG_OUTPUT ) |
270 | | if( libcnotify_verbose != 0 ) |
271 | | { |
272 | | if( libewf_debug_utf16_stream_print( |
273 | | "single files data", |
274 | | *single_files_data, |
275 | | *single_files_data_size, |
276 | | error ) != 1 ) |
277 | | { |
278 | | libcerror_error_set( |
279 | | error, |
280 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
281 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
282 | | "%s: unable to print single files data.", |
283 | | function ); |
284 | | |
285 | | return( -1 ); |
286 | | } |
287 | | } |
288 | | #endif |
289 | 0 | if( format_version == 1 ) |
290 | 0 | { |
291 | 0 | if( libhmac_md5_calculate( |
292 | 0 | *single_files_data, |
293 | 0 | *single_files_data_size, |
294 | 0 | calculated_md5_hash, |
295 | 0 | 16, |
296 | 0 | error ) != 1 ) |
297 | 0 | { |
298 | 0 | libcerror_error_set( |
299 | 0 | error, |
300 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
301 | 0 | LIBCERROR_RUNTIME_ERROR_SET_FAILED, |
302 | 0 | "%s: unable to calculate integrity hash.", |
303 | 0 | function ); |
304 | |
|
305 | 0 | return( -1 ); |
306 | 0 | } |
307 | | #if defined( HAVE_DEBUG_OUTPUT ) |
308 | | if( libcnotify_verbose != 0 ) |
309 | | { |
310 | | libcnotify_printf( |
311 | | "%s: calculated MD5 hash:\n", |
312 | | function ); |
313 | | libcnotify_print_data( |
314 | | calculated_md5_hash, |
315 | | 16, |
316 | | 0 ); |
317 | | } |
318 | | #endif |
319 | 0 | if( memory_compare( |
320 | 0 | data, |
321 | 0 | calculated_md5_hash, |
322 | 0 | 16 ) != 0 ) |
323 | 0 | { |
324 | 0 | libcerror_error_set( |
325 | 0 | error, |
326 | 0 | LIBCERROR_ERROR_DOMAIN_INPUT, |
327 | 0 | LIBCERROR_INPUT_ERROR_VALUE_MISMATCH, |
328 | 0 | "%s: mismatch in integrity hash.", |
329 | 0 | function ); |
330 | |
|
331 | 0 | return( -1 ); |
332 | 0 | } |
333 | | #if defined( HAVE_DEBUG_OUTPUT ) || defined( HAVE_VERBOSE_OUTPUT ) |
334 | | if( libcnotify_verbose != 0 ) |
335 | | { |
336 | | if( stored_data_size < (uint64_t) data_size ) |
337 | | { |
338 | | #if defined( HAVE_DEBUG_OUTPUT ) |
339 | | data_offset += stored_data_size; |
340 | | trailing_data_size = data_size - stored_data_size; |
341 | | |
342 | | libcnotify_printf( |
343 | | "%s: trailing data:\n", |
344 | | function ); |
345 | | libcnotify_print_data( |
346 | | &( data[ data_offset ] ), |
347 | | trailing_data_size, |
348 | | 0 ); |
349 | | |
350 | | #elif defined( HAVE_VERBOSE_OUTPUT ) |
351 | | libcnotify_printf( |
352 | | "%s: section has trailing data.\n", |
353 | | function ); |
354 | | #endif |
355 | | } |
356 | | } |
357 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) || defined( HAVE_VERBOSE_OUTPUT ) */ |
358 | 0 | } |
359 | 0 | return( 1 ); |
360 | 0 | } |
361 | | |
362 | | /* Reads a version 1 ltree section or version 2 singles files data section |
363 | | * section_data will be set to a buffer containing the full section data |
364 | | * single_files_data will be set to a pointer within the section data |
365 | | * Returns the number of bytes read or -1 on error |
366 | | */ |
367 | | ssize_t libewf_ltree_section_read_file_io_pool( |
368 | | libewf_section_descriptor_t *section_descriptor, |
369 | | libewf_io_handle_t *io_handle, |
370 | | libbfio_pool_t *file_io_pool, |
371 | | int file_io_pool_entry, |
372 | | uint8_t format_version, |
373 | | uint8_t **section_data, |
374 | | size_t *section_data_size, |
375 | | uint8_t **single_files_data, |
376 | | size_t *single_files_data_size, |
377 | | libcerror_error_t **error ) |
378 | 49 | { |
379 | 49 | static char *function = "libewf_ltree_section_read_file_io_pool"; |
380 | 49 | ssize_t read_count = 0; |
381 | | |
382 | 49 | if( section_descriptor == NULL ) |
383 | 0 | { |
384 | 0 | libcerror_error_set( |
385 | 0 | error, |
386 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
387 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
388 | 0 | "%s: invalid section descriptor.", |
389 | 0 | function ); |
390 | |
|
391 | 0 | return( -1 ); |
392 | 0 | } |
393 | 49 | read_count = libewf_section_read_data( |
394 | 49 | section_descriptor, |
395 | 49 | io_handle, |
396 | 49 | file_io_pool, |
397 | 49 | file_io_pool_entry, |
398 | 49 | section_data, |
399 | 49 | section_data_size, |
400 | 49 | error ); |
401 | | |
402 | 49 | if( read_count == -1 ) |
403 | 1 | { |
404 | 1 | libcerror_error_set( |
405 | 1 | error, |
406 | 1 | LIBCERROR_ERROR_DOMAIN_IO, |
407 | 1 | LIBCERROR_IO_ERROR_READ_FAILED, |
408 | 1 | "%s: unable to read section data.", |
409 | 1 | function ); |
410 | | |
411 | 1 | goto on_error; |
412 | 1 | } |
413 | 48 | else if( read_count > 0 ) |
414 | 48 | { |
415 | 48 | if( section_data == NULL ) |
416 | 0 | { |
417 | 0 | libcerror_error_set( |
418 | 0 | error, |
419 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
420 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
421 | 0 | "%s: missing section data.", |
422 | 0 | function ); |
423 | |
|
424 | 0 | goto on_error; |
425 | 0 | } |
426 | 48 | if( libewf_ltree_section_read_data( |
427 | 48 | *section_data, |
428 | 48 | *section_data_size, |
429 | 48 | format_version, |
430 | 48 | single_files_data, |
431 | 48 | single_files_data_size, |
432 | 48 | error ) != 1 ) |
433 | 48 | { |
434 | 48 | libcerror_error_set( |
435 | 48 | error, |
436 | 48 | LIBCERROR_ERROR_DOMAIN_IO, |
437 | 48 | LIBCERROR_IO_ERROR_READ_FAILED, |
438 | 48 | "%s: unable to read ltree section.", |
439 | 48 | function ); |
440 | | |
441 | 48 | goto on_error; |
442 | 48 | } |
443 | 48 | } |
444 | 0 | return( read_count ); |
445 | | |
446 | 49 | on_error: |
447 | 49 | if( *section_data != NULL ) |
448 | 48 | { |
449 | 48 | memory_free( |
450 | 48 | *section_data ); |
451 | | |
452 | 48 | *section_data = NULL; |
453 | 48 | } |
454 | 49 | *section_data_size = 0; |
455 | | |
456 | 49 | return( -1 ); |
457 | 49 | } |
458 | | |
459 | | /* Writes a version 1 ltree section or version 2 singles files data section |
460 | | * Returns the number of bytes written or -1 on error |
461 | | */ |
462 | | ssize_t libewf_ltree_section_write_file_io_pool( |
463 | | libewf_section_descriptor_t *section_descriptor, |
464 | | libewf_io_handle_t *io_handle, |
465 | | libbfio_pool_t *file_io_pool, |
466 | | int file_io_pool_entry, |
467 | | uint8_t format_version, |
468 | | off64_t section_offset, |
469 | | uint8_t *section_data, |
470 | | size_t section_data_size, |
471 | | uint8_t *single_files_data, |
472 | | size_t single_files_data_size, |
473 | | libcerror_error_t **error ) |
474 | 0 | { |
475 | 0 | static char *function = "libewf_ltree_section_write_file_io_pool"; |
476 | 0 | size_t ltree_header_data_size = 0; |
477 | 0 | size_t required_section_data_size = 0; |
478 | 0 | size_t section_descriptor_data_size = 0; |
479 | 0 | ssize_t total_write_count = 0; |
480 | 0 | ssize_t write_count = 0; |
481 | 0 | uint32_t calculated_checksum = 0; |
482 | 0 | uint32_t section_padding_size = 0; |
483 | |
|
484 | 0 | if( section_descriptor == NULL ) |
485 | 0 | { |
486 | 0 | libcerror_error_set( |
487 | 0 | error, |
488 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
489 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
490 | 0 | "%s: invalid section descriptor.", |
491 | 0 | function ); |
492 | |
|
493 | 0 | return( -1 ); |
494 | 0 | } |
495 | 0 | if( format_version == 1 ) |
496 | 0 | { |
497 | 0 | section_descriptor_data_size = sizeof( ewf_section_descriptor_v1_t ); |
498 | 0 | ltree_header_data_size = sizeof( ewf_ltree_header_t ); |
499 | 0 | } |
500 | 0 | else if( format_version == 2 ) |
501 | 0 | { |
502 | 0 | section_descriptor_data_size = sizeof( ewf_section_descriptor_v2_t ); |
503 | 0 | } |
504 | 0 | else |
505 | 0 | { |
506 | 0 | libcerror_error_set( |
507 | 0 | error, |
508 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
509 | 0 | LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, |
510 | 0 | "%s: unsupported format version.", |
511 | 0 | function ); |
512 | |
|
513 | 0 | return( -1 ); |
514 | 0 | } |
515 | 0 | if( section_data == NULL ) |
516 | 0 | { |
517 | 0 | libcerror_error_set( |
518 | 0 | error, |
519 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
520 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
521 | 0 | "%s: invalid section data.", |
522 | 0 | function ); |
523 | |
|
524 | 0 | return( -1 ); |
525 | 0 | } |
526 | 0 | if( section_data_size > (size_t) SSIZE_MAX ) |
527 | 0 | { |
528 | 0 | libcerror_error_set( |
529 | 0 | error, |
530 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
531 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, |
532 | 0 | "%s: invalid section data size value exceeds maximum.", |
533 | 0 | function ); |
534 | |
|
535 | 0 | return( -1 ); |
536 | 0 | } |
537 | 0 | if( single_files_data == NULL ) |
538 | 0 | { |
539 | 0 | libcerror_error_set( |
540 | 0 | error, |
541 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
542 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
543 | 0 | "%s: invalid single files data.", |
544 | 0 | function ); |
545 | |
|
546 | 0 | return( -1 ); |
547 | 0 | } |
548 | 0 | required_section_data_size = ltree_header_data_size |
549 | 0 | + single_files_data_size; |
550 | |
|
551 | 0 | if( required_section_data_size > section_data_size ) |
552 | 0 | { |
553 | 0 | libcerror_error_set( |
554 | 0 | error, |
555 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
556 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, |
557 | 0 | "%s: invalid section data value too small.", |
558 | 0 | function ); |
559 | |
|
560 | 0 | return( -1 ); |
561 | 0 | } |
562 | 0 | if( single_files_data_size > (size_t) SSIZE_MAX ) |
563 | 0 | { |
564 | 0 | libcerror_error_set( |
565 | 0 | error, |
566 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
567 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, |
568 | 0 | "%s: invalid single files data size value exceeds maximum.", |
569 | 0 | function ); |
570 | |
|
571 | 0 | return( -1 ); |
572 | 0 | } |
573 | 0 | if( libewf_section_descriptor_set( |
574 | 0 | section_descriptor, |
575 | 0 | LIBEWF_SECTION_TYPE_SINGLE_FILES_DATA, |
576 | 0 | (uint8_t *) "ltree", |
577 | 0 | 5, |
578 | 0 | section_offset, |
579 | 0 | (size64_t) ( section_descriptor_data_size + required_section_data_size ), |
580 | 0 | (size64_t) required_section_data_size, |
581 | 0 | section_padding_size, |
582 | 0 | error ) != 1 ) |
583 | 0 | { |
584 | 0 | libcerror_error_set( |
585 | 0 | error, |
586 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
587 | 0 | LIBCERROR_RUNTIME_ERROR_SET_FAILED, |
588 | 0 | "%s: unable to set section descriptor.", |
589 | 0 | function ); |
590 | |
|
591 | 0 | return( -1 ); |
592 | 0 | } |
593 | 0 | if( format_version == 1 ) |
594 | 0 | { |
595 | 0 | write_count = libewf_section_descriptor_write_file_io_pool( |
596 | 0 | section_descriptor, |
597 | 0 | file_io_pool, |
598 | 0 | file_io_pool_entry, |
599 | 0 | format_version, |
600 | 0 | error ); |
601 | |
|
602 | 0 | if( write_count != (ssize_t) section_descriptor_data_size ) |
603 | 0 | { |
604 | 0 | libcerror_error_set( |
605 | 0 | error, |
606 | 0 | LIBCERROR_ERROR_DOMAIN_IO, |
607 | 0 | LIBCERROR_IO_ERROR_WRITE_FAILED, |
608 | 0 | "%s: unable to write section descriptor data.", |
609 | 0 | function ); |
610 | |
|
611 | 0 | return( -1 ); |
612 | 0 | } |
613 | 0 | total_write_count += write_count; |
614 | 0 | } |
615 | 0 | if( format_version == 1 ) |
616 | 0 | { |
617 | 0 | if( ( section_data + ltree_header_data_size ) != single_files_data ) |
618 | 0 | { |
619 | 0 | libcerror_error_set( |
620 | 0 | error, |
621 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
622 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
623 | 0 | "%s: invalid single files data value out of bounds.", |
624 | 0 | function ); |
625 | |
|
626 | 0 | return( -1 ); |
627 | 0 | } |
628 | 0 | if( single_files_data_size > (size_t) UINT32_MAX ) |
629 | 0 | { |
630 | 0 | libcerror_error_set( |
631 | 0 | error, |
632 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
633 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, |
634 | 0 | "%s: invalid single files data size value exceeds maximum.", |
635 | 0 | function ); |
636 | |
|
637 | 0 | return( -1 ); |
638 | 0 | } |
639 | 0 | if( section_data_size < ltree_header_data_size ) |
640 | 0 | { |
641 | 0 | libcerror_error_set( |
642 | 0 | error, |
643 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
644 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
645 | 0 | "%s: invalid section size value out of bounds - insufficient space for header.", |
646 | 0 | function ); |
647 | |
|
648 | 0 | return( -1 ); |
649 | 0 | } |
650 | 0 | if( memory_set( |
651 | 0 | section_data, |
652 | 0 | 0, |
653 | 0 | ltree_header_data_size ) == NULL ) |
654 | 0 | { |
655 | 0 | libcerror_error_set( |
656 | 0 | error, |
657 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
658 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
659 | 0 | "%s: unable to clear ltree header data.", |
660 | 0 | function ); |
661 | |
|
662 | 0 | return( -1 ); |
663 | 0 | } |
664 | 0 | if( libhmac_md5_calculate( |
665 | 0 | single_files_data, |
666 | 0 | single_files_data_size, |
667 | 0 | ( (ewf_ltree_header_t *) section_data )->integrity_hash, |
668 | 0 | 16, |
669 | 0 | error ) != 1 ) |
670 | 0 | { |
671 | 0 | libcerror_error_set( |
672 | 0 | error, |
673 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
674 | 0 | LIBCERROR_RUNTIME_ERROR_SET_FAILED, |
675 | 0 | "%s: unable to calculate integrity hash.", |
676 | 0 | function ); |
677 | |
|
678 | 0 | return( -1 ); |
679 | 0 | } |
680 | | #if defined( HAVE_DEBUG_OUTPUT ) |
681 | | if( libcnotify_verbose != 0 ) |
682 | | { |
683 | | libcnotify_printf( |
684 | | "%s: calculated MD5 hash:\n", |
685 | | function ); |
686 | | libcnotify_print_data( |
687 | | ( (ewf_ltree_header_t *) section_data )->integrity_hash, |
688 | | 16, |
689 | | 0 ); |
690 | | } |
691 | | #endif |
692 | 0 | byte_stream_copy_from_uint32_little_endian( |
693 | 0 | ( (ewf_ltree_header_t *) section_data )->data_size, |
694 | 0 | single_files_data_size ); |
695 | |
|
696 | 0 | if( libewf_checksum_calculate_adler32( |
697 | 0 | &calculated_checksum, |
698 | 0 | section_data, |
699 | 0 | ltree_header_data_size, |
700 | 0 | 1, |
701 | 0 | error ) != 1 ) |
702 | 0 | { |
703 | 0 | libcerror_error_set( |
704 | 0 | error, |
705 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
706 | 0 | LIBCERROR_RUNTIME_ERROR_SET_FAILED, |
707 | 0 | "%s: unable to calculate header checksum.", |
708 | 0 | function ); |
709 | |
|
710 | 0 | return( -1 ); |
711 | 0 | } |
712 | 0 | byte_stream_copy_from_uint32_little_endian( |
713 | 0 | ( (ewf_ltree_header_t *) section_data )->checksum, |
714 | 0 | calculated_checksum ); |
715 | |
|
716 | | #if defined( HAVE_DEBUG_OUTPUT ) |
717 | | if( libcnotify_verbose != 0 ) |
718 | | { |
719 | | libcnotify_printf( |
720 | | "%s: ltree header data:\n", |
721 | | function ); |
722 | | libcnotify_print_data( |
723 | | section_data, |
724 | | ltree_header_data_size, |
725 | | 0 ); |
726 | | } |
727 | | #endif |
728 | | #if defined( HAVE_DEBUG_OUTPUT ) |
729 | | if( libcnotify_verbose != 0 ) |
730 | | { |
731 | | libcnotify_printf( |
732 | | "%s: integrity hash:\n", |
733 | | function ); |
734 | | libcnotify_print_data( |
735 | | ( (ewf_ltree_header_t *) section_data )->integrity_hash, |
736 | | 16, |
737 | | 0 ); |
738 | | |
739 | | libcnotify_printf( |
740 | | "%s: data size\t\t\t\t\t: %" PRIzd "\n", |
741 | | function, |
742 | | single_files_data_size ); |
743 | | |
744 | | libcnotify_printf( |
745 | | "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", |
746 | | function, |
747 | | calculated_checksum ); |
748 | | |
749 | | libcnotify_printf( |
750 | | "%s: unknown1:\n", |
751 | | function ); |
752 | | libcnotify_print_data( |
753 | | ( (ewf_ltree_header_t *) section_data )->unknown1, |
754 | | 20, |
755 | | 0 ); |
756 | | } |
757 | | #endif |
758 | 0 | } |
759 | 0 | else if( format_version == 2 ) |
760 | 0 | { |
761 | 0 | section_descriptor->data_flags |= LIBEWF_SECTION_DATA_FLAGS_HAS_INTEGRITY_HASH; |
762 | 0 | } |
763 | 0 | write_count = libewf_section_write_data( |
764 | 0 | section_descriptor, |
765 | 0 | io_handle, |
766 | 0 | file_io_pool, |
767 | 0 | file_io_pool_entry, |
768 | 0 | section_data, |
769 | 0 | required_section_data_size, |
770 | 0 | error ); |
771 | |
|
772 | 0 | if( write_count == -1 ) |
773 | 0 | { |
774 | 0 | libcerror_error_set( |
775 | 0 | error, |
776 | 0 | LIBCERROR_ERROR_DOMAIN_IO, |
777 | 0 | LIBCERROR_IO_ERROR_WRITE_FAILED, |
778 | 0 | "%s: unable to write section data.", |
779 | 0 | function ); |
780 | |
|
781 | 0 | return( -1 ); |
782 | 0 | } |
783 | 0 | total_write_count += write_count; |
784 | |
|
785 | 0 | if( format_version == 2 ) |
786 | 0 | { |
787 | 0 | write_count = libewf_section_descriptor_write_file_io_pool( |
788 | 0 | section_descriptor, |
789 | 0 | file_io_pool, |
790 | 0 | file_io_pool_entry, |
791 | 0 | format_version, |
792 | 0 | error ); |
793 | |
|
794 | 0 | if( write_count != (ssize_t) section_descriptor_data_size ) |
795 | 0 | { |
796 | 0 | libcerror_error_set( |
797 | 0 | error, |
798 | 0 | LIBCERROR_ERROR_DOMAIN_IO, |
799 | 0 | LIBCERROR_IO_ERROR_WRITE_FAILED, |
800 | 0 | "%s: unable to write section descriptor data.", |
801 | 0 | function ); |
802 | |
|
803 | 0 | return( -1 ); |
804 | 0 | } |
805 | 0 | total_write_count += write_count; |
806 | 0 | } |
807 | 0 | return( total_write_count ); |
808 | 0 | } |
809 | | |