/* Reads the security descriptor values * Returns 1 if successful or -1 on error */ int libfsntfs_security_descriptor_values_read( libfsntfs_security_descriptor_values_t *security_descriptor_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_values_read"; if( security_descriptor_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor values.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: security descriptor data:\n", function ); libcnotify_print_data( data, data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif /* TODO use libfwnt to print the security descriptor */ return( 1 ); }
/* Reads an index node * Returns 1 if successful or -1 on error */ int libpff_index_node_read( libpff_index_node_t *index_node, libpff_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, off64_t node_offset, libcerror_error_t **error ) { uint8_t *index_node_footer_data = NULL; static char *function = "libpff_index_node_read"; ssize_t read_count = 0; uint32_t calculated_checksum = 0; uint32_t stored_checksum = 0; uint8_t calculated_entry_size = 0; uint8_t calculated_maximum_number_of_entries = 0; uint8_t index_node_type_copy = 0; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint8_t *index_node_entry_data = NULL; uint64_t value_64bit = 0; uint32_t value_32bit = 0; uint16_t entry_index = 0; uint16_t index_node_entry_data_size = 0; uint16_t value_16bit = 0; #endif if( index_node == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index node.", function ); return( -1 ); } if( index_node->data != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index node - data already set.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT ) && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT ) && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported file type.", function ); return( -1 ); } if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { index_node->data_size = 512; index_node->maximum_entries_data_size = 512 - sizeof( pff_index_node_32bit_footer_t ); } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) { index_node->data_size = 512; index_node->maximum_entries_data_size = 512 - sizeof( pff_index_node_64bit_footer_t ); } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) { index_node->data_size = 4096; index_node->maximum_entries_data_size = 4096 - sizeof( pff_index_node_64bit_4k_page_footer_t ); } index_node->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * index_node->data_size ); if( index_node->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create index node data.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading index node data at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, node_offset, node_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, node_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek node offset: %" PRIi64 ".", function, node_offset ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, index_node->data, index_node->data_size, error ); if( read_count != (ssize_t) index_node->data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read index node data.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index node data:\n", function ); libcnotify_print_data( index_node->data, index_node->data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif index_node_footer_data = &( index_node->data[ index_node->maximum_entries_data_size ] ); if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { index_node->type = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->type; index_node_type_copy = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->type_copy; byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->back_pointer, index_node->back_pointer ); byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->checksum, stored_checksum ); index_node->number_of_entries = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->number_of_entries; index_node->maximum_number_of_entries = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->maximum_number_of_entries; index_node->entry_size = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->entry_size; index_node->level = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->level; if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR ) && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) ) { calculated_entry_size = 16; calculated_maximum_number_of_entries = 496 / 16; } else { calculated_entry_size = 12; calculated_maximum_number_of_entries = 496 / 12; } } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) { index_node->type = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->type; index_node_type_copy = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->type_copy; byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->checksum, stored_checksum ); byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->back_pointer, index_node->back_pointer ); index_node->number_of_entries = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->number_of_entries; index_node->maximum_number_of_entries = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->maximum_number_of_entries; index_node->entry_size = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->entry_size; index_node->level = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->level; if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR ) && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) ) { calculated_entry_size = 32; calculated_maximum_number_of_entries = 488 / 32; } else { calculated_entry_size = 24; calculated_maximum_number_of_entries = 488 / 24; } } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) { index_node->type = ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->type; index_node_type_copy = ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->type_copy; byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->checksum, stored_checksum ); byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->back_pointer, index_node->back_pointer ); byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->number_of_entries, index_node->number_of_entries ); byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->maximum_number_of_entries, index_node->maximum_number_of_entries ); index_node->entry_size = ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->entry_size; index_node->level = ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->level; if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR ) && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) ) { calculated_entry_size = 32; calculated_maximum_number_of_entries = 4056 / 32; } else { calculated_entry_size = 24; calculated_maximum_number_of_entries = 4056 / 24; } } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: number of entries\t\t\t\t: %" PRIu16 "\n", function, index_node->number_of_entries ); libcnotify_printf( "%s: maximum number of entries\t\t\t: %" PRIu16 "\n", function, index_node->maximum_number_of_entries ); libcnotify_printf( "%s: entry size\t\t\t\t\t: %" PRIu8 "\n", function, index_node->entry_size ); libcnotify_printf( "%s: node level\t\t\t\t\t: %" PRIu8 "\n", function, index_node->level ); if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) { libcnotify_printf( "%s: padding:\n", function ); libcnotify_print_data( ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->padding1, 4, 0 ); } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) { libcnotify_printf( "%s: padding:\n", function ); libcnotify_print_data( ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->padding1, 10, 0 ); } libcnotify_printf( "%s: index node type\t\t\t\t\t: 0x%02" PRIx8 "\n", function, index_node->type ); libcnotify_printf( "%s: index node type copy\t\t\t\t: 0x%02" PRIx8 "\n", function, index_node_type_copy ); if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->signature, value_16bit ); libcnotify_printf( "%s: signature\t\t\t\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "%s: back pointer\t\t\t\t\t: 0x%08" PRIx64 "\n", function, index_node->back_pointer ); libcnotify_printf( "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", function, stored_checksum ); } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) { byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->signature, value_16bit ); libcnotify_printf( "%s: signature\t\t\t\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", function, stored_checksum ); libcnotify_printf( "%s: back pointer\t\t\t\t\t: 0x%08" PRIx64 "\n", function, index_node->back_pointer ); } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) { byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->signature, value_16bit ); libcnotify_printf( "%s: signature\t\t\t\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", function, stored_checksum ); libcnotify_printf( "%s: back pointer\t\t\t\t\t: 0x%08" PRIx64 "\n", function, index_node->back_pointer ); byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->unknown1, value_64bit ); libcnotify_printf( "%s: unknown1\t\t\t\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); } libcnotify_printf( "\n" ); } #endif if( index_node->type != index_node_type_copy ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: mismatch in index node type (0x%02" PRIx8 " != 0x%02" PRIx8 ").\n", function, index_node->type, index_node_type_copy ); } #endif if( ( index_node->type != LIBPFF_INDEX_TYPE_DESCRIPTOR ) && ( index_node->type != LIBPFF_INDEX_TYPE_OFFSET ) && ( ( index_node_type_copy == LIBPFF_INDEX_TYPE_DESCRIPTOR ) || ( index_node_type_copy == LIBPFF_INDEX_TYPE_OFFSET ) ) ) { index_node->type = index_node_type_copy; } } if( ( index_node->type != LIBPFF_INDEX_TYPE_DESCRIPTOR ) && ( index_node->type != LIBPFF_INDEX_TYPE_OFFSET ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported index node type: 0x%02" PRIx8 ".", function, index_node->type ); goto on_error; } if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { result = libfmapi_checksum_calculate_weak_crc32( &calculated_checksum, index_node->data, 500, 0, error ); } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) { result = libfmapi_checksum_calculate_weak_crc32( &calculated_checksum, index_node->data, 496, 0, error ); } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) { result = libfmapi_checksum_calculate_weak_crc32( &calculated_checksum, index_node->data, 4072, 0, error ); } if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to calculate weak CRC-32.", function ); goto on_error; } if( stored_checksum != calculated_checksum ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: mismatch in checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n", function, stored_checksum, calculated_checksum ); } #endif /* TODO smart error handling */ } if( ( index_node->entry_size != 0 ) && ( index_node->entry_size != calculated_entry_size ) ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: entry size mismatch (calculated: %" PRIu8 ", stored: %" PRIu8 ").\n", function, calculated_entry_size, index_node->entry_size ); } #endif index_node->entry_size = calculated_entry_size; } if( ( index_node->maximum_number_of_entries != 0 ) && ( index_node->maximum_number_of_entries != calculated_maximum_number_of_entries ) ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: maximum number of entries mismatch (calculated: %" PRIu8 ", stored: %" PRIu8 ").\n", function, calculated_maximum_number_of_entries, index_node->maximum_number_of_entries ); } #endif index_node->maximum_number_of_entries = calculated_maximum_number_of_entries; } if( index_node->number_of_entries > index_node->maximum_number_of_entries ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: number of entries: %" PRIu8 ", exceeds maximum: %" PRIu8 ".", function, index_node->number_of_entries, index_node->maximum_number_of_entries ); } #endif index_node->number_of_entries = index_node->maximum_number_of_entries; } if( ( (uint16_t) index_node->number_of_entries * (uint16_t) index_node->entry_size ) > index_node->maximum_entries_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: size of entries: %" PRIu16 ", exceeds maximum: %" PRIu16 ".", function, index_node->number_of_entries * index_node->entry_size, index_node->maximum_entries_data_size ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { index_node_entry_data = index_node->data; index_node_entry_data_size = index_node->maximum_entries_data_size; /* Print all the entries */ for( entry_index = 0; entry_index < index_node->maximum_number_of_entries; entry_index++ ) { if( entry_index == index_node->number_of_entries ) { result = libpff_index_node_check_for_empty_block( index_node_entry_data, index_node_entry_data_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if remaining index nodes are empty.", function ); return( -1 ); } else if( result != 0 ) { break; } libcnotify_printf( "\n" ); libcnotify_printf( "%s: remaining node entries\n", function ); } if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint32_little_endian( index_node_entry_data, value_64bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint64_little_endian( index_node_entry_data, value_64bit ); } libcnotify_printf( "%s: entry: %03" PRIu16 " index node identifier\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n", function, entry_index, value_64bit, value_64bit ); /* Process descriptor index node leaf nodes */ if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR ) && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) ) { if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_descriptor_entry_32bit_t *) index_node_entry_data )->data_identifier, value_64bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->data_identifier, value_64bit ); } libcnotify_printf( "%s: entry: %03" PRIu16 " data identifier\t\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n", function, entry_index, value_64bit, value_64bit ); if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_descriptor_entry_32bit_t *) index_node_entry_data )->local_descriptors_identifier, value_64bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->local_descriptors_identifier, value_64bit ); } libcnotify_printf( "%s: entry: %03" PRIu16 " local descriptors identifier\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n", function, entry_index, value_64bit, value_64bit ); if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_descriptor_entry_32bit_t *) index_node_entry_data )->parent_identifier, value_32bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->parent_identifier, value_32bit ); } libcnotify_printf( "%s: entry: %03" PRIu16 " parent identifier\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", function, entry_index, value_32bit, value_32bit ); if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->unknown1, value_32bit ); libcnotify_printf( "%s: entry: %03" PRIu16 " unknown1\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", function, entry_index, value_32bit, value_32bit ); } } /* Process offset and descriptor index node branch nodes and offset index node leaf nodes */ else { if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF ) { if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_branch_entry_32bit_t *) index_node_entry_data )->back_pointer, value_64bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_branch_entry_64bit_t *) index_node_entry_data )->back_pointer, value_64bit ); } libcnotify_printf( "%s: entry: %03" PRIu16 " back pointer\t\t\t\t: 0x%08" PRIx64 "\n", function, entry_index, value_64bit ); } if( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) { if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_offset_entry_32bit_t *) index_node_entry_data )->file_offset, value_64bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->file_offset, value_64bit ); } } else { if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_branch_entry_32bit_t *) index_node_entry_data )->file_offset, value_64bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_branch_entry_64bit_t *) index_node_entry_data )->file_offset, value_64bit ); } } libcnotify_printf( "%s: entry: %03" PRIu16 " file offset\t\t\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n", function, entry_index, value_64bit, value_64bit ); if( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) { if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_offset_entry_32bit_t *) index_node_entry_data )->data_size, value_16bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->data_size, value_16bit ); } libcnotify_printf( "%s: entry: %03" PRIu16 " data size\t\t\t\t: %" PRIu16 "\n", function, entry_index, value_16bit ); if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_offset_entry_32bit_t *) index_node_entry_data )->reference_count, value_16bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->reference_count, value_16bit ); } libcnotify_printf( "%s: entry: %03" PRIu16 " reference count\t\t\t: %" PRIu16 "\n", function, entry_index, value_16bit ); if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->data_allocation_table_file_offset, value_32bit ); libcnotify_printf( "%s: entry: %03" PRIu16 " data allocation table offset\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", function, entry_index, value_32bit, value_32bit ); } } } index_node_entry_data += index_node->entry_size; index_node_entry_data_size -= index_node->entry_size; } libcnotify_printf( "\n" ); } #endif index_node->entries_data = index_node->data; return( 1 ); on_error: if( index_node->data != NULL ) { memory_free( index_node->data ); index_node->data = NULL; } return( -1 ); }
/* Sends a ATA DEVICE CONFIGURATION IDENTIFY to the file descriptor * Returns 1 if successful, 0 if not or -1 on error */ int libsmdev_ata_get_device_configuration( libcfile_file_t *device_file, struct hd_driveid *device_configuration, libcerror_error_t **error ) { static char *function = "libsmdev_ata_get_device_configuration"; int read_count = 0; if( device_configuration == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid device configuration.", function ); return( -1 ); } #if defined( HDIO_GET_IDENTITY ) read_count = libcfile_file_io_control_read( device_file, HDIO_GET_IDENTITY, NULL, 0, (uint8_t *) device_configuration, sizeof( struct hd_driveid ), error ); if( read_count == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_IOCTL_FAILED, "%s: unable to query device file for: HDIO_GET_IDENTITY.", function ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( ( error != NULL ) && ( *error != NULL ) ) { libcnotify_print_error_backtrace( *error ); } } #endif libcerror_error_free( error ); return( 0 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: HDIO_GET_IDENTITY:\n", function ); libcnotify_print_data( (uint8_t *) device_configuration, sizeof( struct hd_driveid ), 0 ); libcnotify_printf( "Feature sets:\n" ); libcnotify_printf( "SMART:\t\t\t%d\n", ( device_configuration->command_set_1 & 0x0001 ) ); libcnotify_printf( "Security Mode:\t\t%d (%d)\n", ( device_configuration->command_set_1 & 0x0002 ) >> 1, ( device_configuration->dlf & 0x0001 ) ); libcnotify_printf( "Security Mode enabled:\t%d\n", ( device_configuration->dlf & 0x0002 ) >> 1 ); libcnotify_printf( "Removable Media:\t%d\n", ( device_configuration->command_set_1 & 0x0004 ) >> 2 ); libcnotify_printf( "HPA:\t\t\t%d\n", ( device_configuration->command_set_1 & 0x0400 ) >> 10 ); libcnotify_printf( "DCO:\t\t\t%d\n", ( device_configuration->command_set_2 & 0x0800 ) >> 11 ); libcnotify_printf( "Media serial:\t\t%d\n", ( device_configuration->cfsse & 0x0004 ) >> 2 ); libcnotify_printf( "\n" ); }
/* De- or encrypts a block of data * Returns 1 if successful or -1 on error */ int libbde_encryption_crypt( libbde_encryption_context_t *context, int mode, const uint8_t *input_data, size_t input_data_size, uint8_t *output_data, size_t output_data_size, uint64_t block_key, libcerror_error_t **error ) { uint8_t block_key_data[ 16 ]; uint8_t initialization_vector[ 16 ]; uint8_t sector_key_data[ 32 ]; static char *function = "libbde_encryption_crypt"; size_t data_index = 0; size_t sector_key_data_index = 0; if( context == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid context.", function ); return( -1 ); } if( ( mode != LIBBDE_ENCRYPTION_CRYPT_MODE_DECRYPT ) && ( mode != LIBBDE_ENCRYPTION_CRYPT_MODE_ENCRYPT ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported mode.", function ); return( -1 ); } if( memory_set( initialization_vector, 0, 16 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear initialization vector.", function ); return( -1 ); } if( memory_set( block_key_data, 0, 16 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear block key data.", function ); return( -1 ); } if( memory_set( sector_key_data, 0, 32 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear sector key data.", function ); return( -1 ); } if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC_DIFFUSER ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC_DIFFUSER ) ) { byte_stream_copy_from_uint64_little_endian( block_key_data, block_key ); /* The block key for the initialization vector is encrypted * with the FVEK */ if( libcaes_crypt_ecb( context->fvek_encryption_context, LIBCAES_CRYPT_MODE_ENCRYPT, block_key_data, 16, initialization_vector, 16, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ENCRYPTION, LIBCERROR_ENCRYPTION_ERROR_GENERIC, "%s: unable to encrypt initialization vector.", function ); return( -1 ); } if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC_DIFFUSER ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC_DIFFUSER ) ) { /* The block key for the sector key data is encrypted * with the TWEAK key */ if( libcaes_crypt_ecb( context->tweak_encryption_context, LIBCAES_CRYPT_MODE_ENCRYPT, block_key_data, 16, sector_key_data, 16, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ENCRYPTION, LIBCERROR_ENCRYPTION_ERROR_GENERIC, "%s: unable to encrypt sector key data.", function ); return( -1 ); } /* Set the last byte to contain 0x80 (128) */ block_key_data[ 15 ] = 0x80; if( libcaes_crypt_ecb( context->tweak_encryption_context, LIBCAES_CRYPT_MODE_ENCRYPT, block_key_data, 16, &( sector_key_data[ 16 ] ), 16, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ENCRYPTION, LIBCERROR_ENCRYPTION_ERROR_GENERIC, "%s: unable to encrypt sector key data.", function ); return( -1 ); } } } else if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_XTS ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_XTS ) ) { byte_stream_copy_from_uint64_little_endian( initialization_vector, block_key ); /* TODO: implement */ } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: initialization vector:\n", function ); libcnotify_print_data( initialization_vector, 16, 0 ); } #endif if( mode == LIBBDE_ENCRYPTION_CRYPT_MODE_ENCRYPT ) { /* TODO safe guard input data ? */ if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC_DIFFUSER ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC_DIFFUSER ) ) { sector_key_data_index = 0; for( data_index = 0; data_index < input_data_size; data_index++ ) { output_data[ data_index ] ^= sector_key_data[ sector_key_data_index ]; sector_key_data_index++; if( sector_key_data_index >= 32 ) { sector_key_data_index -= 32; } } if( libbde_diffuser_encrypt( output_data, output_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ENCRYPTION, LIBCERROR_ENCRYPTION_ERROR_ENCRYPT_FAILED, "%s: unable to encrypt data using Diffuser.", function ); return( -1 ); } } if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC_DIFFUSER ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC_DIFFUSER ) ) { if( libcaes_crypt_cbc( context->fvek_encryption_context, LIBCAES_CRYPT_MODE_ENCRYPT, initialization_vector, 16, input_data, input_data_size, output_data, output_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ENCRYPTION, LIBCERROR_ENCRYPTION_ERROR_GENERIC, "%s: unable to AES-CBC encrypt output data.", function ); return( -1 ); } } else if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_XTS ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_XTS ) ) { if( libcaes_crypt_xts( context->fvek_decryption_tweaked_context, LIBCAES_CRYPT_MODE_ENCRYPT, initialization_vector, 16, input_data, input_data_size, output_data, output_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ENCRYPTION, LIBCERROR_ENCRYPTION_ERROR_GENERIC, "%s: unable to AES-XTS decrypt output data.", function ); return( -1 ); } } } else { if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC_DIFFUSER ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC_DIFFUSER ) ) { if( libcaes_crypt_cbc( context->fvek_decryption_context, LIBCAES_CRYPT_MODE_DECRYPT, initialization_vector, 16, input_data, input_data_size, output_data, output_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ENCRYPTION, LIBCERROR_ENCRYPTION_ERROR_GENERIC, "%s: unable to AES-CBC decrypt output data.", function ); return( -1 ); } } else if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_XTS ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_XTS ) ) { if( libcaes_crypt_xts( context->fvek_decryption_tweaked_context, LIBCAES_CRYPT_MODE_DECRYPT, initialization_vector, 16, input_data, input_data_size, output_data, output_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ENCRYPTION, LIBCERROR_ENCRYPTION_ERROR_GENERIC, "%s: unable to AES-XTS decrypt output data.", function ); return( -1 ); } } if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC_DIFFUSER ) || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC_DIFFUSER ) ) { if( libbde_diffuser_decrypt( output_data, output_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ENCRYPTION, LIBCERROR_ENCRYPTION_ERROR_DECRYPT_FAILED, "%s: unable to decrypt data using Diffuser.", function ); return( -1 ); } sector_key_data_index = 0; for( data_index = 0; data_index < input_data_size; data_index++ ) { output_data[ data_index ] ^= sector_key_data[ sector_key_data_index ]; sector_key_data_index++; if( sector_key_data_index >= 32 ) { sector_key_data_index -= 32; } } } } return( 1 ); }
/* Reads the channel * Returns 1 if successful or -1 on error */ int libfwevt_channel_read( libfwevt_channel_t *channel, const uint8_t *data, size_t data_size, size_t data_offset, libcerror_error_t **error ) { libfwevt_internal_channel_t *internal_channel = NULL; fwevt_template_channel_t *wevt_channel = NULL; static char *function = "libfwevt_channel_read"; uint32_t channel_data_offset = 0; uint32_t channel_data_size = 0; #if defined( HAVE_DEBUG_OUTPUT ) system_character_t *value_string = NULL; size_t value_string_size = 0; uint32_t value_32bit = 0; int result = 0; #endif if( channel == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid channel.", function ); return( -1 ); } internal_channel = (libfwevt_internal_channel_t *) channel; if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid data size value exceeds maximum.", function ); return( -1 ); } if( data_offset >= data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data offset value out of bounds.", function ); return( -1 ); } if( ( data_size < sizeof( fwevt_template_channel_t ) ) || ( data_offset > ( data_size - sizeof( fwevt_template_channel_t ) ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: invalid data value too small.", function ); return( -1 ); } wevt_channel = (fwevt_template_channel_t *) &( data[ data_offset ] ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: channel data:\n", function ); libcnotify_print_data( (uint8_t *) wevt_channel, sizeof( fwevt_template_channel_t ), 0 ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ byte_stream_copy_to_uint32_little_endian( wevt_channel->identifier, internal_channel->identifier ); byte_stream_copy_to_uint32_little_endian( wevt_channel->data_offset, channel_data_offset ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: identifier\t\t\t\t\t: %" PRIu32 "\n", function, internal_channel->identifier ); libcnotify_printf( "%s: data offset\t\t\t\t\t: 0x%08" PRIx32 "\n", function, channel_data_offset ); byte_stream_copy_to_uint32_little_endian( wevt_channel->unknown1, value_32bit ); libcnotify_printf( "%s: unknown1\t\t\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( wevt_channel->message_identifier, value_32bit ); libcnotify_printf( "%s: message identifier\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( channel_data_offset > 0 ) { if( channel_data_offset >= ( data_size - 4 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid channel data offset value out of bounds.", function ); return( -1 ); } byte_stream_copy_to_uint32_little_endian( &( data[ channel_data_offset ] ), channel_data_size ); if( ( data_size < channel_data_size ) || ( channel_data_offset > ( data_size - channel_data_size ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid channel data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: data:\n", function ); libcnotify_print_data( &( data[ channel_data_offset ] ), channel_data_size, 0 ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: data size\t\t\t\t\t: %" PRIu32 "\n", function, channel_data_size ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( channel_data_size >= 4 ) { channel_data_offset += 4; channel_data_size -= 4; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfwevt_debug_print_utf16_string_value( function, "name\t\t\t\t\t\t", &( data[ channel_data_offset ] ), channel_data_size, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print UTF-16 string value.", function ); return( -1 ); } } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ } } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n" ); } #endif return( 1 ); }
/* Reads the property set from the property set stream * Returns 1 if successful or -1 on error */ int libolecf_property_set_read( libolecf_property_set_t *property_set, libolecf_io_handle_t *io_handle, libolecf_item_t *property_set_stream, libcerror_error_t **error ) { olecf_property_set_header_t property_set_header; libolecf_internal_property_set_t *internal_property_set = NULL; libolecf_property_section_t *property_section = NULL; static char *function = "libolecf_property_set_read"; off64_t section_list_entry_offset = 0; ssize_t read_count = 0; uint32_t section_header_offset = 0; uint16_t number_of_sections = 0; uint16_t section_index = 0; int sections_entry = 0; #if defined( HAVE_DEBUG_OUTPUT ) libcstring_system_character_t guid_string[ 48 ]; libfguid_identifier_t *guid = NULL; int result = 0; #endif if( property_set == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid property set.", function ); return( -1 ); } internal_property_set = (libolecf_internal_property_set_t *) property_set; if( libolecf_stream_seek_offset( property_set_stream, 0, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek property set header offset: 0.", function ); goto on_error; } read_count = libolecf_stream_read_buffer( property_set_stream, (uint8_t *) &property_set_header, sizeof( olecf_property_set_header_t ), error ); if( read_count != (ssize_t) sizeof( olecf_property_set_header_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read property set header.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: property set header:\n", function ); libcnotify_print_data( (uint8_t *) &property_set_header, sizeof( olecf_property_set_header_t ), 0 ); } #endif if( ( property_set_header.byte_order[ 0 ] == 0xfe ) && ( property_set_header.byte_order[ 1 ] == 0xff ) ) { internal_property_set->byte_order = LIBOLECF_ENDIAN_LITTLE; } else if( ( property_set_header.byte_order[ 0 ] == 0xff ) && ( property_set_header.byte_order[ 1 ] == 0xfe ) ) { internal_property_set->byte_order = LIBOLECF_ENDIAN_BIG; } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported byte order: 0x%02" PRIx8 " 0x%02" PRIx8 ".", function, property_set_header.byte_order[ 0 ], property_set_header.byte_order[ 1 ] ); goto on_error; } if( internal_property_set->byte_order == LIBOLECF_ENDIAN_LITTLE ) { byte_stream_copy_to_uint16_little_endian( property_set_header.format, internal_property_set->format ); byte_stream_copy_to_uint32_little_endian( property_set_header.system_version, internal_property_set->system_version ); byte_stream_copy_to_uint16_little_endian( property_set_header.number_of_sections, number_of_sections ); } else if( internal_property_set->byte_order == LIBOLECF_ENDIAN_BIG ) { byte_stream_copy_to_uint16_big_endian( property_set_header.format, internal_property_set->format ); byte_stream_copy_to_uint32_big_endian( property_set_header.system_version, internal_property_set->system_version ); byte_stream_copy_to_uint16_big_endian( property_set_header.number_of_sections, number_of_sections ); } if( memory_copy( internal_property_set->class_identifier, property_set_header.class_identifier, 16 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy class identifier.", function ); goto on_error; } /* TODO make sure the class identifier is set in little endian */ #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: property set header byte order\t\t: 0x%02" PRIx8 " 0x%02" PRIx8 "\n", function, property_set_header.byte_order[ 0 ], property_set_header.byte_order[ 1 ] ); libcnotify_printf( "%s: property set header format\t\t\t: %" PRIu16 "\n", function, internal_property_set->format ); libcnotify_printf( "%s: property set header system version\t\t: 0x%08" PRIx32 "\n", function, internal_property_set->system_version ); if( libfguid_identifier_initialize( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create GUID.", function ); goto on_error; } if( libfguid_identifier_copy_from_byte_stream( guid, internal_property_set->class_identifier, 16, internal_property_set->byte_order, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy byte stream to GUID.", function ); goto on_error; } #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) result = libfguid_identifier_copy_to_utf16_string( guid, (uint16_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #else result = libfguid_identifier_copy_to_utf8_string( guid, (uint8_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy GUID to string.", function ); goto on_error; } libcnotify_printf( "%s: property set header class identifier\t: %" PRIs_LIBCSTRING_SYSTEM " (%s : %s)\n", function, guid_string, libfwps_format_class_identifier_get_identifier( internal_property_set->class_identifier ), libfwps_format_class_identifier_get_description( internal_property_set->class_identifier ) ); if( libfguid_identifier_free( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free GUID.", function ); goto on_error; } libcnotify_printf( "%s: property set header number of sections\t: %" PRIu16 "\n", function, number_of_sections ); libcnotify_printf( "\n" ); } #endif section_list_entry_offset = sizeof( olecf_property_set_header_t ); for( section_index = 0; section_index < (int) number_of_sections; section_index++ ) { if( libolecf_property_section_initialize( &property_section, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create property section: %d.", function, section_index ); goto on_error; } if( libolecf_stream_seek_offset( property_set_stream, section_list_entry_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek property section list entry: %d offset: %" PRIi64 ".", function, section_index, section_list_entry_offset ); goto on_error; } if( libolecf_property_section_read_list_entry( (libolecf_internal_property_section_t *) property_section, property_set_stream, internal_property_set->byte_order, §ion_header_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read property section list entry: %d.", function, section_index ); goto on_error; } if( libolecf_stream_get_offset( property_set_stream, §ion_list_entry_offset, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to retrieve property section list entry offset.", function ); goto on_error; } if( libolecf_property_section_read( (libolecf_internal_property_section_t *) property_section, io_handle, property_set_stream, section_header_offset, internal_property_set->byte_order, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read property section: %d at offset: %" PRIu32 ".", function, section_index, section_header_offset ); goto on_error; } if( libcdata_array_append_entry( internal_property_set->sections, §ions_entry, (intptr_t *) property_section, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append property section: %d to sections array.", function, section_index ); goto on_error; } property_section = NULL; } return( 1 ); on_error: #if defined( HAVE_DEBUG_OUTPUT ) if( guid != NULL ) { libfguid_identifier_free( &guid, NULL ); } #endif if( property_section != NULL ) { libolecf_property_section_free( &property_section, NULL ); } return( -1 ); }
/* Reads the page tags * Returns 1 if successful or -1 on error */ int libesedb_page_read_tags( libcdata_array_t *page_tags_array, libesedb_io_handle_t *io_handle, uint16_t number_of_page_tags, uint8_t *page_data, size_t page_data_size, libcerror_error_t **error ) { libesedb_page_tags_value_t *page_tags_value = NULL; uint8_t *page_tags_data = NULL; static char *function = "libesedb_page_read_tags"; uint16_t page_tag_offset = 0; uint16_t page_tag_size = 0; uint16_t page_tags_index = 0; #if defined( HAVE_DEBUG_OUTPUT ) size_t page_tags_data_size = 0; #endif if( page_tags_array == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid page tags array.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( page_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid page data.", function ); return( -1 ); } if( page_data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid page data size value exceeds maximum.", function ); return( -1 ); } if( libcdata_array_resize( page_tags_array, number_of_page_tags, (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_tags_value_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED, "%s: unable to resize page tags array.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { page_tags_data_size = 4 * number_of_page_tags; libcnotify_printf( "%s: page tags:\n", function ); libcnotify_print_data( &( page_data[ page_data_size - page_tags_data_size ] ), page_tags_data_size, 0 ); } #endif /* Read the page tags back to front */ page_tags_data = &( page_data[ page_data_size - 2 ] ); for( page_tags_index = 0; page_tags_index < number_of_page_tags; page_tags_index++ ) { if( libesedb_page_tags_value_initialize( &page_tags_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create page tags value.", function ); goto on_error; } byte_stream_copy_to_uint16_little_endian( page_tags_data, page_tag_offset ); page_tags_data -= 2; byte_stream_copy_to_uint16_little_endian( page_tags_data, page_tag_size ); page_tags_data -= 2; if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER ) && ( io_handle->page_size >= 16384 ) ) { page_tags_value->flags = 0; page_tags_value->offset = page_tag_offset & 0x7fff; page_tags_value->size = page_tag_size & 0x7fff;; } else { page_tags_value->flags = page_tag_offset >> 13; page_tags_value->offset = page_tag_offset & 0x1fff; page_tags_value->size = page_tag_size & 0x1fff; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: page tag: %03" PRIu16 " offset\t\t\t\t: %" PRIu16 " (0x%04" PRIx16 ")\n", function, page_tags_index, page_tags_value->offset, page_tag_offset ); libcnotify_printf( "%s: page tag: %03" PRIu16 " size\t\t\t\t: %" PRIu16 " (0x%04" PRIx16 ")\n", function, page_tags_index, page_tags_value->size, page_tag_size ); if( ( io_handle->format_revision < LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER ) && ( io_handle->page_size < 16384 ) ) { libcnotify_printf( "%s: page tag: %03" PRIu16 " flags\t\t\t\t: 0x%02" PRIx8 "", function, page_tags_index, page_tags_value->flags ); libesedb_debug_print_page_tag_flags( page_tags_value->flags ); libcnotify_printf( "\n" ); } } #endif if( libcdata_array_set_entry_by_index( page_tags_array, (int) page_tags_index, (intptr_t *) page_tags_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set page tag: %" PRIu16 ".", function, page_tags_index ); goto on_error; } page_tags_value = NULL; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n" ); } #endif return( 1 ); on_error: if( page_tags_value != NULL ) { libesedb_page_tags_value_free( &page_tags_value, NULL ); } return( -1 ); }
/* Calculates the SHA256 hash of an UTF-8 formatted password * Returns 1 if successful or -1 on error */ int libbde_utf8_password_calculate_hash( const uint8_t *utf8_string, size_t utf8_string_length, uint8_t *password_hash, size_t password_hash_size, libcerror_error_t **error ) { uint8_t *utf16_stream = NULL; static char *function = "libbde_utf8_password_calculate_hash"; size_t utf16_stream_size = 0; if( password_hash == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid password hash.", function ); return( -1 ); } if( password_hash_size != 32 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: password hash size value out of bounds.", function ); return( -1 ); } if( libuna_utf16_stream_size_from_utf8( utf8_string, utf8_string_length, &utf16_stream_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine UTF-16 stream size.", function ); goto on_error; } utf16_stream = (uint8_t *) memory_allocate( sizeof( uint8_t ) * utf16_stream_size ); if( utf16_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create UTF-16 stream.", function ); goto on_error; } if( libuna_utf16_stream_copy_from_utf8( utf16_stream, utf16_stream_size, LIBUNA_ENDIAN_LITTLE, utf8_string, utf8_string_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-8 string to UTF-16 stream size.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: password:\n", function ); libcnotify_print_data( utf16_stream, utf16_stream_size, 0 ); } #endif /* Ignore the byte-order mark in the UTF16 stream */ if( libhmac_sha256_calculate( &( utf16_stream[ 2 ] ), utf16_stream_size - 2, password_hash, password_hash_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to calculate password hash.", function ); goto on_error; } if( libhmac_sha256_calculate( password_hash, password_hash_size, password_hash, password_hash_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to calculate password hash.", function ); goto on_error; } if( memory_set( utf16_stream, 0, utf16_stream_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear UTF-16 stream.", function ); goto on_error; } memory_free( utf16_stream ); return( 1 ); on_error: if( utf16_stream != NULL ) { memory_set( utf16_stream, 0, utf16_stream_size ); memory_free( utf16_stream ); } return( -1 ); }
int main( int argc, char * const argv[] ) #endif { libcerror_error_t *error = NULL; libcfile_file_t *destination_file = NULL; libcfile_file_t *source_file = NULL; system_character_t *option_target_path = NULL; system_character_t *options_string = NULL; system_character_t *source = NULL; uint8_t *buffer = NULL; uint8_t *uncompressed_data = NULL; char *program = "lzxpressdecompress"; system_integer_t option = 0; size64_t source_size = 0; size_t buffer_size = 0; size_t uncompressed_data_size = 0; ssize_t read_count = 0; ssize_t write_count = 0; off_t source_offset = 0; int decompression_method = 1; int result = 0; int verbose = 0; #if defined( WINAPI ) void *workspace = NULL; unsigned short winapi_compression_method = 0; #endif assorted_output_version_fprint( stdout, program ); #if defined( WINAPI ) options_string = _SYSTEM_STRING( "d:ho:s:t:vV1234" ); #else options_string = _SYSTEM_STRING( "d:ho:s:t:vV12" ); #endif while( ( option = assorted_getopt( argc, argv, options_string ) ) != (system_integer_t) -1 ) { switch( option ) { case (system_integer_t) '?': default: fprintf( stderr, "Invalid argument: %" PRIs_SYSTEM "\n", argv[ optind ] ); usage_fprint( stdout ); return( EXIT_FAILURE ); case (system_integer_t) '1': decompression_method = 1; break; case (system_integer_t) '2': decompression_method = 2; break; #if defined( WINAPI ) case (system_integer_t) '3': decompression_method = 3; break; case (system_integer_t) '4': decompression_method = 4; break; #endif case (system_integer_t) 'd': #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) uncompressed_data_size = _wtol( optarg ); #else uncompressed_data_size = atol( optarg ); #endif break; case (system_integer_t) 'h': usage_fprint( stdout ); return( EXIT_SUCCESS ); case (system_integer_t) 'o': #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) source_offset = _wtol( optarg ); #else source_offset = atol( optarg ); #endif break; case (system_integer_t) 's': #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) source_size = _wtol( optarg ); #else source_size = atol( optarg ); #endif break; case (system_integer_t) 't': option_target_path = optarg; break; case (system_integer_t) 'v': verbose = 1; break; case (system_integer_t) 'V': assorted_output_copyright_fprint( stdout ); return( EXIT_SUCCESS ); } } if( optind == argc ) { fprintf( stderr, "Missing source file.\n" ); usage_fprint( stdout ); return( EXIT_FAILURE ); } source = argv[ optind ]; libcnotify_stream_set( stderr, NULL ); libcnotify_verbose_set( verbose ); /* Open the source file */ if( libcfile_file_initialize( &source_file, &error ) != 1 ) { fprintf( stderr, "Unable to create source file.\n" ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libcfile_file_open_wide( source_file, source, LIBCFILE_OPEN_READ, &error ); #else result = libcfile_file_open( source_file, source, LIBCFILE_OPEN_READ, &error ); #endif if( result != 1 ) { fprintf( stderr, "Unable to open source file.\n" ); goto on_error; } if( source_size == 0 ) { if( libcfile_file_get_size( source_file, &source_size, &error ) == -1 ) { fprintf( stderr, "Unable to determine size of source file.\n" ); goto on_error; } if( source_size <= (size64_t) source_offset ) { fprintf( stderr, "Invalid source size value is less equal than source offset.\n" ); goto on_error; } source_size -= source_offset; } if( source_size == 0 ) { fprintf( stderr, "Invalid source size value is zero.\n" ); goto on_error; } if( source_size > (size_t) SSIZE_MAX ) { fprintf( stderr, "Invalid source size value exceeds maximum.\n" ); goto on_error; } /* Create the input buffer */ buffer_size = source_size; buffer = (uint8_t *) memory_allocate( sizeof( uint8_t ) * buffer_size ); if( buffer == NULL ) { fprintf( stderr, "Unable to create buffer.\n" ); goto on_error; } if( uncompressed_data_size == 0 ) { uncompressed_data_size = 65536; } uncompressed_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * uncompressed_data_size ); if( uncompressed_data == NULL ) { fprintf( stderr, "Unable to create uncompressed data buffer.\n" ); goto on_error; } if( memory_set( uncompressed_data, 0, uncompressed_data_size ) == NULL ) { fprintf( stderr, "Unable to clear uncompressed data buffer.\n" ); goto on_error; } /* Position the source file at the right offset */ if( libcfile_file_seek_offset( source_file, source_offset, SEEK_SET, &error ) == -1 ) { fprintf( stderr, "Unable to seek offset in source file.\n" ); goto on_error; } fprintf( stdout, "Starting LZXPRESS decompression of: %" PRIs_SYSTEM " at offset: %" PRIjd " (0x%08" PRIjx ").\n", source, source_offset, source_offset ); read_count = libcfile_file_read_buffer( source_file, buffer, source_size, &error ); if( read_count != (ssize_t) source_size ) { fprintf( stderr, "Unable to read from source file.\n" ); goto on_error; } /* Decompress the data */ if( option_target_path == NULL ) { fprintf( stderr, "Compressed data:\n" ); libcnotify_print_data( buffer, source_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } if( decompression_method == 1 ) { result = libfwnt_lzxpress_decompress( buffer, (size_t) source_size, uncompressed_data, &uncompressed_data_size, &error ); } else if( decompression_method == 2 ) { result = libfwnt_lzxpress_huffman_decompress( buffer, (size_t) source_size, uncompressed_data, &uncompressed_data_size, &error ); } #if defined( WINAPI ) else if( ( decompression_method == 3 ) || ( decompression_method == 4 ) ) { if( decompression_method == 3 ) { winapi_compression_method = COMPRESSION_FORMAT_XPRESS; } else if( decompression_method == 4 ) { winapi_compression_method = COMPRESSION_FORMAT_XPRESS_HUFF; } /* TODO: determine workspace size: RtlGetCompressionWorkSpaceSize */ workspace = (void *) memory_allocate( 16 * 1024 * 1024 ); if( workspace == NULL ) { fprintf( stderr, "Unable to create workspace.\n" ); goto on_error; } result = lzxpresscompress_RtlDecompressBufferEx( winapi_compression_method, (unsigned char *) uncompressed_data, (unsigned long) uncompressed_data_size, (unsigned char *) buffer, (unsigned long) source_size, (unsigned long *) &uncompressed_data_size, workspace ); memory_free( workspace ); if( result != 0 ) { result = -1; } else { result = 1; } } #endif if( result == -1 ) { fprintf( stderr, "Unable to decompress data.\n" ); libcnotify_print_data( uncompressed_data, uncompressed_data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); goto on_error; } if( option_target_path == NULL ) { fprintf( stderr, "Uncompressed data:\n" ); libcnotify_print_data( uncompressed_data, uncompressed_data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } else { if( libcfile_file_initialize( &destination_file, &error ) != 1 ) { fprintf( stderr, "Unable to create destination file.\n" ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libcfile_file_open_wide( destination_file, option_target_path, LIBCFILE_OPEN_WRITE, &error ); #else result = libcfile_file_open( destination_file, option_target_path, LIBCFILE_OPEN_WRITE, &error ); #endif if( result != 1 ) { fprintf( stderr, "Unable to open destination file.\n" ); goto on_error; } write_count = libcfile_file_write_buffer( destination_file, uncompressed_data, uncompressed_data_size, &error ); if( write_count != (ssize_t) uncompressed_data_size ) { fprintf( stderr, "Unable to write to destination file.\n" ); goto on_error; } if( libcfile_file_close( destination_file, &error ) != 0 ) { fprintf( stderr, "Unable to close destination file.\n" ); goto on_error; } if( libcfile_file_free( &destination_file, &error ) != 1 ) { fprintf( stderr, "Unable to free destination file.\n" ); goto on_error; } } /* Clean up */ if( libcfile_file_close( source_file, &error ) != 0 ) { fprintf( stderr, "Unable to close source file.\n" ); goto on_error; } if( libcfile_file_free( &source_file, &error ) != 1 ) { fprintf( stderr, "Unable to free source file.\n" ); goto on_error; } memory_free( uncompressed_data ); uncompressed_data = NULL; memory_free( buffer ); buffer = NULL; fprintf( stdout, "LZXPRESS decompression:\tSUCCESS\n" ); return( EXIT_SUCCESS ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } if( destination_file != NULL ) { libcfile_file_free( &destination_file, NULL ); } if( uncompressed_data != NULL ) { memory_free( uncompressed_data ); } if( buffer != NULL ) { memory_free( buffer ); } if( source_file != NULL ) { libcfile_file_free( &source_file, NULL ); } fprintf( stdout, "LZXPRESS decompression:\tFAILURE\n" ); return( EXIT_FAILURE ); }
/* Reads cluster block * Returns 1 if successful or -1 on error */ int libqcow_cluster_block_read( libqcow_cluster_block_t *cluster_block, libbfio_handle_t *file_io_handle, off64_t cluster_block_offset, libcerror_error_t **error ) { static char *function = "libqcow_cluster_block_read"; ssize_t read_count = 0; if( cluster_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid cluster block.", function ); return( -1 ); } if( cluster_block->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid cluster block - missing data.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading cluster block at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, cluster_block_offset, cluster_block_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, cluster_block_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek cluster block offset: %" PRIi64 " (0x%08" PRIx64 ").", function, cluster_block_offset, cluster_block_offset ); return( -1 ); } read_count = libbfio_handle_read_buffer( file_io_handle, cluster_block->data, cluster_block->data_size, error ); if( read_count != (ssize_t) cluster_block->data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read cluster block.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: cluster block:\n", function ); libcnotify_print_data( cluster_block->data, cluster_block->data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif return( 1 ); }
/* Reads a data block strings * Returns the number of bytes read if successful or -1 on error */ int liblnk_data_block_strings_read( liblnk_data_string_t *data_string, liblnk_data_block_t *data_block, liblnk_io_handle_t *io_handle, libcerror_error_t **error ) { lnk_data_block_strings_t *data_block_strings_data = NULL; static char *function = "liblnk_data_block_strings_read"; size_t string_size = 0; size_t unicode_string_size = 0; if( data_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data string.", function ); return( -1 ); } if( data_string->data != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid data string - data already set.", function ); return( -1 ); } if( data_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data block.", function ); return( -1 ); } if( data_block->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data block - missing data.", function ); return( -1 ); } if( data_block->data_size < sizeof( lnk_data_block_strings_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data block - data size too small.", function ); return( -1 ); } data_block_strings_data = (lnk_data_block_strings_t *) data_block->data; if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } for( string_size = 0; string_size < 260; string_size++ ) { if( data_block_strings_data->string[ string_size ] == 0 ) { break; } } if( ( string_size == 260 ) || ( data_block_strings_data->string[ string_size ] != 0 ) ) { #if defined( HAVE_VERBOSE_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unsupported data block strings\n" ); } #endif string_size = 0; } else { string_size += 1; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: string data:\n", function ); libcnotify_print_data( data_block_strings_data->string, 260, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); if( liblnk_debug_print_string_value( function, "string\t\t\t\t\t", data_block_strings_data->string, 260, io_handle->ascii_codepage, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print string value.", function ); goto on_error; } } #endif for( unicode_string_size = 0; unicode_string_size < 520; unicode_string_size += 2 ) { if( ( data_block_strings_data->unicode_string[ unicode_string_size ] == 0 ) && ( data_block_strings_data->unicode_string[ unicode_string_size + 1 ] == 0 ) ) { break; } } if( ( unicode_string_size == 520 ) || ( data_block_strings_data->unicode_string[ unicode_string_size ] != 0 ) || ( data_block_strings_data->unicode_string[ unicode_string_size + 1 ] != 0 ) ) { #if defined( HAVE_VERBOSE_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unsupported unicode string\n" ); } #endif unicode_string_size = 0; } else { unicode_string_size += 2; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unicode string data:\n", function ); libcnotify_print_data( data_block_strings_data->unicode_string, 520, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); if( liblnk_debug_print_utf16_string_value( function, "unicode string\t\t\t\t", data_block_strings_data->unicode_string, 520, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print UTF-16 string value.", function ); goto on_error; } libcnotify_printf( "\n" ); } #endif if( unicode_string_size > 0 ) { data_string->data_size = unicode_string_size; data_string->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * data_string->data_size ); if( data_string->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data string data.", function ); goto on_error; } if( memory_copy( data_string->data, data_block_strings_data->unicode_string, data_string->data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy unicode string data.", function ); goto on_error; } data_string->is_unicode = 1; } else if( string_size > 0 ) { data_string->data_size = string_size; data_string->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * data_string->data_size ); if( data_string->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data string data.", function ); goto on_error; } if( memory_copy( data_string->data, data_block_strings_data->string, data_string->data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy string data.", function ); goto on_error; } data_string->is_unicode = 0; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( data_block->data_size > sizeof( lnk_data_block_strings_t ) ) { libcnotify_printf( "%s: trailing data:\n", function ); libcnotify_print_data( &( data_block->data[ sizeof( lnk_data_block_strings_t ) ] ), data_block->data_size - sizeof( lnk_data_block_strings_t ), LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } } #endif return( 1 ); on_error: if( data_string->data != NULL ) { memory_free( data_string->data ); data_string->data = NULL; } data_string->data_size = 0; return( -1 ); }
/* Reads the metadata area * Returns 1 if successful or -1 on error */ int libvslvm_metadata_area_read( libvslvm_metadata_area_t *metadata_area, libbfio_handle_t *file_io_handle, off64_t file_offset, libcerror_error_t **error ) { vslvm_raw_location_descriptor_t raw_location_descriptor_data; vslvm_metadata_area_header_t metadata_area_header; libvslvm_raw_location_descriptor_t *raw_location_descriptor = NULL; static char *function = "libvslvm_metadata_area_read"; ssize_t read_count = 0; uint64_t offset = 0; uint64_t size = 0; uint32_t checksum = 0; uint32_t flags = 0; int entry_index = 0; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint64_t value_64bit = 0; uint32_t value_32bit = 0; #endif if( metadata_area == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid metadata area.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading metadata area at offset: %" PRIi64 "\n", function, file_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek offset: %" PRIi64 " (0x%08" PRIx64 ").", function, file_offset, file_offset ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, (uint8_t *) &metadata_area_header, sizeof( vslvm_metadata_area_header_t ), error ); if( read_count != (ssize_t) sizeof( vslvm_metadata_area_header_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read metadata area header.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: metadata area header data:\n", function ); libcnotify_print_data( (uint8_t *) &metadata_area_header, sizeof( vslvm_metadata_area_header_t ), 0 ); } #endif if( memory_compare( metadata_area_header.signature, vslvm_metadata_area_signature, 8 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported metadata area signature.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { byte_stream_copy_to_uint32_little_endian( metadata_area_header.checksum, value_32bit ); libcnotify_printf( "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: signature\t\t\t\t\t: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", function, metadata_area_header.signature[ 0 ], metadata_area_header.signature[ 1 ], metadata_area_header.signature[ 2 ], metadata_area_header.signature[ 3 ], metadata_area_header.signature[ 4 ], metadata_area_header.signature[ 5 ], metadata_area_header.signature[ 6 ], metadata_area_header.signature[ 7 ], metadata_area_header.signature[ 8 ], metadata_area_header.signature[ 9 ], metadata_area_header.signature[ 10 ], metadata_area_header.signature[ 11 ], metadata_area_header.signature[ 12 ], metadata_area_header.signature[ 13 ], metadata_area_header.signature[ 14 ], metadata_area_header.signature[ 15 ] ); byte_stream_copy_to_uint32_little_endian( metadata_area_header.version, value_32bit ); libcnotify_printf( "%s: version\t\t\t\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint64_little_endian( metadata_area_header.data_offset, value_64bit ); libcnotify_printf( "%s: data offset\t\t\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); byte_stream_copy_to_uint64_little_endian( metadata_area_header.data_size, value_64bit ); libcnotify_printf( "%s: data size\t\t\t\t\t: %" PRIu64 "\n", function, value_64bit ); libcnotify_printf( "\n" ); } #endif /* TODO calculate checksum */ do { read_count = libbfio_handle_read_buffer( file_io_handle, (uint8_t *) &raw_location_descriptor_data, sizeof( vslvm_raw_location_descriptor_t ), error ); if( read_count != (ssize_t) sizeof( vslvm_raw_location_descriptor_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read raw location descriptor.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: raw location descriptor data:\n", function ); libcnotify_print_data( (uint8_t *) &raw_location_descriptor_data, sizeof( vslvm_raw_location_descriptor_t ), 0 ); } #endif result = memory_compare( (uint8_t *) &raw_location_descriptor_data, vslvm_empty_raw_location_descriptor, sizeof( vslvm_raw_location_descriptor_t ) ); if( result != 0 ) { byte_stream_copy_to_uint64_little_endian( raw_location_descriptor_data.offset, offset ); byte_stream_copy_to_uint64_little_endian( raw_location_descriptor_data.size, size ); byte_stream_copy_to_uint32_little_endian( raw_location_descriptor_data.checksum, checksum ); byte_stream_copy_to_uint32_little_endian( raw_location_descriptor_data.flags, flags ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: offset\t\t\t\t\t: 0x%08" PRIx64 "\n", function, offset ); libcnotify_printf( "%s: size\t\t\t\t\t: %" PRIu64 "\n", function, size ); libcnotify_printf( "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", function, checksum ); libcnotify_printf( "%s: flags\t\t\t\t\t: 0x%08" PRIx32 "\n", function, flags ); libcnotify_printf( "\n" ); } #endif if( ( flags & LIBVSLVM_RAW_LOCATION_DESCRIPTOR_FLAG_IGNORE ) == 0 ) { if( libvslvm_raw_location_descriptor_initialize( &raw_location_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create raw location descriptor.", function ); goto on_error; } if( libvslvm_raw_location_descriptor_set( raw_location_descriptor, (off64_t) ( file_offset + offset ), (size64_t) size, checksum, flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set raw location descriptor.", function ); goto on_error; } if( libcdata_array_append_entry( metadata_area->raw_location_descriptors_array, &entry_index, (intptr_t *) raw_location_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append entry to raw location descriptors array.", function ); goto on_error; } raw_location_descriptor = NULL; } } } while( result != 0 ); return( 1 ); on_error: if( raw_location_descriptor != NULL ) { libvslvm_raw_location_descriptor_free( &raw_location_descriptor, NULL ); } libcdata_array_empty( metadata_area->raw_location_descriptors_array, (int (*)(intptr_t **, libcerror_error_t **)) &libvslvm_raw_location_descriptor_free, NULL ); return( -1 ); }
/* Reads key hierarchy entry data * Returns 1 if successful or -1 on error */ int libcreg_key_hierarchy_entry_read_data( libcreg_key_hierarchy_entry_t *key_hierarchy_entry, const uint8_t *data, size_t data_size, size_t data_offset LIBCREG_ATTRIBUTE_UNUSED, libcerror_error_t **error ) { static char *function = "libcreg_key_hierarchy_entry_read_data"; #if defined( HAVE_DEBUG_OUTPUT ) uint32_t value_32bit = 0; #else LIBCREG_UNREFERENCED_PARAMETER( data_offset ); #endif if( key_hierarchy_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid key hierarchy entry.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } if( data_size < sizeof( creg_key_hierarchy_entry_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: invalid data size value too small.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid data size value exceeds maximum.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: key hierarchy entry:\n", function ); libcnotify_print_data( data, sizeof( creg_key_hierarchy_entry_t ), 0 ); } #endif byte_stream_copy_to_uint32_little_endian( ( (creg_key_hierarchy_entry_t *) data )->name_hash, key_hierarchy_entry->name_hash ); byte_stream_copy_to_uint32_little_endian( ( (creg_key_hierarchy_entry_t *) data )->parent_key_offset, key_hierarchy_entry->parent_key_offset ); byte_stream_copy_to_uint32_little_endian( ( (creg_key_hierarchy_entry_t *) data )->sub_key_offset, key_hierarchy_entry->sub_key_offset ); byte_stream_copy_to_uint32_little_endian( ( (creg_key_hierarchy_entry_t *) data )->next_key_offset, key_hierarchy_entry->next_key_offset ); byte_stream_copy_to_uint16_little_endian( ( (creg_key_hierarchy_entry_t *) data )->key_name_entry_number, key_hierarchy_entry->key_name_entry_number ); byte_stream_copy_to_uint16_little_endian( ( (creg_key_hierarchy_entry_t *) data )->data_block_number, key_hierarchy_entry->data_block_number ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: offset\t\t\t\t: 0x%08" PRIzx "\n", function, data_offset ); byte_stream_copy_to_uint32_little_endian( ( (creg_key_hierarchy_entry_t *) data )->unknown1, value_32bit ); libcnotify_printf( "%s: unknown1\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: name hash\t\t\t\t: 0x%08" PRIx32 "\n", function, key_hierarchy_entry->name_hash ); byte_stream_copy_to_uint32_little_endian( ( (creg_key_hierarchy_entry_t *) data )->unknown2, value_32bit ); libcnotify_printf( "%s: unknown2\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: parent key offset\t\t\t: 0x%08" PRIx32 "\n", function, key_hierarchy_entry->parent_key_offset ); libcnotify_printf( "%s: sub key offset\t\t\t: 0x%08" PRIx32 "\n", function, key_hierarchy_entry->sub_key_offset ); libcnotify_printf( "%s: next key offset\t\t\t: 0x%08" PRIx32 "\n", function, key_hierarchy_entry->next_key_offset ); libcnotify_printf( "%s: key name entry number\t\t\t: %" PRIi16 "\n", function, (int16_t) key_hierarchy_entry->key_name_entry_number ); libcnotify_printf( "%s: data block number\t\t\t: %" PRIi16 "\n", function, (int16_t) key_hierarchy_entry->data_block_number ); libcnotify_printf( "\n" ); } #endif return( 1 ); }
/* Copies the sector data to the buffer * Returns the number of bytes copied if successful or -1 on error */ ssize_t libodraw_io_handle_copy_sector_data_to_buffer( libodraw_io_handle_t *io_handle, const uint8_t *sector_data, size_t sector_data_size, uint32_t bytes_per_sector, uint8_t track_type, uint8_t *buffer, size_t buffer_size, uint32_t sector_index, uint32_t sector_offset, libcerror_error_t **error ) { static char *function = "libodraw_io_handle_copy_sector_data_to_buffer"; size_t buffer_offset = 0; size_t read_size = 0; size_t sector_data_offset = 0; uint32_t sector_lba = 0; #if defined( HAVE_DEBUG_OUTPUT ) || defined( HAVE_VERBOSE_OUTPUT ) uint8_t sector_mode = 0; #endif if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( sector_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid sector data.", function ); return( -1 ); } if( sector_data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid sector data size value exceeds maximum.", function ); return( -1 ); } if( buffer == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid buffer.", function ); return( -1 ); } if( buffer_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid buffer size value exceeds maximum.", function ); return( -1 ); } if( ( (size_t) sector_offset >= sector_data_size ) || ( sector_offset >= io_handle->bytes_per_sector ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid sector offset value out of bounds.", function ); return( -1 ); } while( sector_data_offset < sector_data_size ) { if( io_handle->bytes_per_sector == 2048 ) { if( ( track_type == LIBODRAW_TRACK_TYPE_MODE1_2352 ) || ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2352 ) ) { if( ( sector_data_offset + 16 ) >= sector_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: sector data too small.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: sector: %" PRIu32 " header:\n", function, sector_index ); libcnotify_print_data( &( sector_data[ sector_data_offset ] ), 16, 0 ); } #endif if( memory_compare( &( sector_data[ sector_data_offset ] ), libodraw_sector_synchronisation_data, 12 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_INPUT, LIBCERROR_INPUT_ERROR_VALUE_MISMATCH, "%s: unsupported sector synchronisation data.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: sector: %" PRIu32 " synchronisation data:\n", function, sector_index ); libcnotify_print_data( &( sector_data[ sector_data_offset ] ), 12, 0 ); } #endif sector_data_offset += 12; libodraw_optical_disk_copy_msf_to_lba( sector_data[ sector_data_offset ], sector_data[ sector_data_offset + 1 ], sector_data[ sector_data_offset + 2 ], sector_lba ); #if defined( HAVE_DEBUG_OUTPUT ) || defined( HAVE_VERBOSE_OUTPUT ) sector_mode = sector_data[ sector_data_offset + 3 ] & 0x03; #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: sector: %" PRIu32 " MSF\t\t: %02" PRIu8 ":%02" PRIu8 ":%02" PRIu8 " (%" PRIu32 ")\n", function, sector_index, sector_data[ sector_data_offset ], sector_data[ sector_data_offset + 1 ], sector_data[ sector_data_offset + 2 ], sector_lba ); libcnotify_printf( "%s: sector: %" PRIu32 " mode bits\t: 0x%02" PRIx8 "\n", function, sector_index, sector_data[ sector_data_offset + 3 ] ); } #endif #if defined( HAVE_VERBOSE_OUTPUT ) if( sector_lba != sector_index ) { libcnotify_printf( "%s: sector MSF (LBA) does not match current.\n", function ); } if( ( ( track_type == LIBODRAW_TRACK_TYPE_MODE1_2352 ) && ( sector_mode != 1 ) ) || ( ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2352 ) && ( sector_mode != 2 ) ) ) { libcnotify_printf( "%s: sector mode does not match table of contents.\n", function ); } #endif sector_data_offset += 4; } else if( bytes_per_sector == 2352 ) { sector_data_offset += 16; } if( ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2336 ) || ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2352 ) ) { if( ( sector_data[ sector_data_offset ] != sector_data[ sector_data_offset + 4 ] ) || ( sector_data[ sector_data_offset + 1 ] != sector_data[ sector_data_offset + 5 ] ) || ( sector_data[ sector_data_offset + 2 ] != sector_data[ sector_data_offset + 6 ] ) || ( sector_data[ sector_data_offset + 3 ] != sector_data[ sector_data_offset + 7 ] ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_INPUT, LIBCERROR_INPUT_ERROR_VALUE_MISMATCH, "%s: unsupported or corrupt XA sub-header.", function ); return( -1 ); } if( sector_data[ sector_data_offset + 1 ] >= 32 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_INPUT, LIBCERROR_INPUT_ERROR_VALUE_MISMATCH, "%s: unsupported XA sub-header channel number.", function ); return( -1 ); } #if defined( HAVE_VERBOSE_OUTPUT ) if( libcnotify_verbose != 0 ) { if( ( sector_data[ sector_data_offset + 2 ] & 0x08 ) != 0 ) { libcnotify_printf( "%s: data flag not set in XA sub-header sub-mode flags.\n", function ); } } #endif /* TODO some writers seem to ignore these flags if( ( sector_data[ sector_data_offset + 2 ] & 0x08 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_INPUT, LIBCERROR_INPUT_ERROR_VALUE_MISMATCH, "%s: unsupported XA sub-header sub-mode flags - data flag not set.", function ); return( -1 ); } */ sector_data_offset += 8; } } else if( io_handle->bytes_per_sector == 2352 ) { if( sector_offset == 0 ) { /* TODO what about run-out and lead-out data (have argument indicate non-track data) */ if( ( io_handle->mode == 1 ) || ( io_handle->mode == 2 ) ) { read_size = 12; if( ( read_size + buffer_offset ) > buffer_size ) { read_size = buffer_size - buffer_offset; } if( memory_copy( &( buffer[ buffer_offset ] ), libodraw_sector_synchronisation_data, read_size ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unsupported copy sector synchronisation data to buffer.", function ); return( -1 ); } buffer_offset += read_size; if( buffer_offset >= buffer_size ) { break; } /* TODO set MSF requires current sector */ buffer[ buffer_offset++ ] = 0; if( buffer_offset >= buffer_size ) { break; } buffer[ buffer_offset++ ] = 0; if( buffer_offset >= buffer_size ) { break; } buffer[ buffer_offset++ ] = 0; if( buffer_offset >= buffer_size ) { break; } if( io_handle->mode == 1 ) { buffer[ buffer_offset++ ] = 1; } else if ( io_handle->mode == 2 ) { buffer[ buffer_offset++ ] = 2; } if( buffer_offset >= buffer_size ) { break; } } else { read_size = 16; if( ( read_size + buffer_offset ) > buffer_size ) { read_size = buffer_size - buffer_offset; } if( memory_set( &( buffer[ buffer_offset ] ), 0, read_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to set sector data in buffer.", function ); return( -1 ); } buffer_offset += read_size; if( buffer_offset >= buffer_size ) { break; } } if( io_handle->mode == 2 ) { /* TODO what about XA sub-header */ } } } read_size = io_handle->bytes_per_sector; if( sector_offset != 0 ) { sector_data_offset += sector_offset; read_size -= (size_t) sector_offset; sector_offset = 0; } if( ( read_size + buffer_offset ) > buffer_size ) { read_size = buffer_size - buffer_offset; } if( ( track_type == LIBODRAW_TRACK_TYPE_AUDIO ) && ( io_handle->bytes_per_sector != 2352 ) ) { /* If the sector size is not 2352 just return 0 bytes * for audio data */ if( memory_set( &( buffer[ buffer_offset ] ), 0, read_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to set sector data to buffer.", function ); return( -1 ); } } else { if( memory_copy( &( buffer[ buffer_offset ] ), &( sector_data[ sector_data_offset ] ), read_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy sector data to buffer.", function ); return( -1 ); } } buffer_offset += read_size; sector_data_offset += read_size; if( buffer_offset >= buffer_size ) { break; } if( io_handle->bytes_per_sector == 2048 ) { if( track_type == LIBODRAW_TRACK_TYPE_MODE1_2352 ) { /* TODO calculate checksum, what about read errors ?*/ sector_data_offset += 4; /* TODO check padding */ sector_data_offset += 8; /* TODO check ECC data if necessary, what about read errors ? */ sector_data_offset += 276; } else if( ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2336 ) || ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2352 ) ) { /* TODO calculate checksum, what about read errors ?*/ sector_data_offset += 4; /* TODO check ECC data if necessary, what about read errors ? */ sector_data_offset += 276; } else if( bytes_per_sector == 2352 ) { sector_data_offset += 288; } } else if( io_handle->bytes_per_sector == 2352 ) { /* TODO what about run-out and lead-out data (have argument indicate non-track data) */ if( ( io_handle->mode == 1 ) || ( io_handle->mode == 2 ) ) { read_size = 4; if( ( read_size + buffer_offset ) > buffer_size ) { read_size = buffer_size - buffer_offset; } /* TODO determine missing data instead of 0 fill */ if( memory_set( &( buffer[ buffer_offset ] ), 0, read_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to set sector checksum in buffer.", function ); return( -1 ); } buffer_offset += read_size; if( buffer_offset >= buffer_size ) { break; } } if( io_handle->mode == 1 ) { read_size = 8; if( ( read_size + buffer_offset ) > buffer_size ) { read_size = buffer_size - buffer_offset; } if( memory_set( &( buffer[ buffer_offset ] ), 0, read_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to set sector reserved in buffer.", function ); return( -1 ); } buffer_offset += read_size; if( buffer_offset >= buffer_size ) { break; } } if( ( io_handle->mode == 1 ) || ( io_handle->mode == 2 ) ) { read_size = 276; if( ( read_size + buffer_offset ) > buffer_size ) { read_size = buffer_size - buffer_offset; } /* TODO determine missing data instead of 0 fill */ if( memory_set( &( buffer[ buffer_offset ] ), 0, read_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to set sector error correction data in buffer.", function ); return( -1 ); } buffer_offset += read_size; if( buffer_offset >= buffer_size ) { break; } } else { read_size = 288; if( ( read_size + buffer_offset ) > buffer_size ) { read_size = buffer_size - buffer_offset; } if( memory_set( &( buffer[ buffer_offset ] ), 0, read_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to set sector data in buffer.", function ); return( -1 ); } buffer_offset += read_size; if( buffer_offset >= buffer_size ) { break; } } } sector_index++; } return( (ssize_t) buffer_offset ); }
/* Reads the volume name values * Returns 1 if successful or -1 on error */ int libfsntfs_volume_name_values_read( libfsntfs_volume_name_values_t *volume_name_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_name_values_read"; #if defined( HAVE_DEBUG_OUTPUT ) libcstring_system_character_t *value_string = NULL; size_t value_string_size = 0; int result = 0; #endif if( volume_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume name values.", function ); return( -1 ); } /* The size of the data can be 0 if the name is not set. */ if( data_size == 0 ) { return( 1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); goto on_error; } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: volume name data:\n", function ); libcnotify_print_data( data, data_size, 0 ); } #endif if( data_size > 0 ) { volume_name_values->name = (uint8_t *) memory_allocate( sizeof( uint8_t ) * data_size ); if( volume_name_values->name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name.", function ); goto on_error; } volume_name_values->name_size = data_size; if( memory_copy( volume_name_values->name, data, volume_name_values->name_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy volume name.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_utf16_string_size_from_utf16_stream( volume_name_values->name, volume_name_values->name_size, LIBUNA_ENDIAN_LITTLE, &value_string_size, error ); #else result = libuna_utf8_string_size_from_utf16_stream( volume_name_values->name, volume_name_values->name_size, LIBUNA_ENDIAN_LITTLE, &value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine size of name string.", function ); goto on_error; } value_string = libcstring_system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name string.", function ); goto on_error; } #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_utf16_string_copy_from_utf16_stream( (libuna_utf16_character_t *) value_string, value_string_size, volume_name_values->name, volume_name_values->name_size, LIBUNA_ENDIAN_LITTLE, error ); #else result = libuna_utf8_string_copy_from_utf16_stream( (libuna_utf8_character_t *) value_string, value_string_size, volume_name_values->name, volume_name_values->name_size, LIBUNA_ENDIAN_LITTLE, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set name string.", function ); goto on_error; } libcnotify_printf( "%s: name\t\t\t\t\t: %" PRIs_LIBCSTRING_SYSTEM "\n", function, value_string ); memory_free( value_string ); value_string = NULL; libcnotify_printf( "\n" ); } #endif } return( 1 ); on_error: #if defined( HAVE_DEBUG_OUTPUT ) if( value_string != NULL ) { memory_free( value_string ); } #endif if( volume_name_values->name != NULL ) { memory_free( volume_name_values->name ); volume_name_values->name = NULL; } volume_name_values->name_size = 0; return( -1 ); }
/* Reads the block descriptor * Returns 1 if successful, 0 if block list entry is empty or -1 on error */ int libvshadow_block_range_descriptor_read( libvshadow_block_range_descriptor_t *block_range_descriptor, const uint8_t *block_list_entry_data, size_t block_list_entry_size, int store_index LIBVSHADOW_ATTRIBUTE_UNUSED, libcerror_error_t **error ) { static char *function = "libvshadow_block_range_descriptor_read"; LIBVSHADOW_UNREFERENCED_PARAMETER( store_index ) if( block_range_descriptor == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid block descriptor.", function ); return( -1 ); } if( block_list_entry_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid block list entry data.", function ); return( -1 ); } if( block_list_entry_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid block list entry size value exceeds maximum.", function ); return( -1 ); } if( memory_compare( block_list_entry_data, vshadow_empty_store_block_range_list_entry, sizeof( vshadow_store_block_range_list_entry_t ) ) == 0 ) { return( 0 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: store: %02d block range list entry data:\n", function, store_index ); libcnotify_print_data( block_list_entry_data, sizeof( vshadow_store_block_range_list_entry_t ), 0 ); } #endif byte_stream_copy_to_uint64_little_endian( ( (vshadow_store_block_range_list_entry_t *) block_list_entry_data )->offset, block_range_descriptor->offset ); byte_stream_copy_to_uint64_little_endian( ( (vshadow_store_block_range_list_entry_t *) block_list_entry_data )->relative_offset, block_range_descriptor->relative_offset ); byte_stream_copy_to_uint64_little_endian( ( (vshadow_store_block_range_list_entry_t *) block_list_entry_data )->size, block_range_descriptor->size ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: store: %02d offset\t\t: 0x%08" PRIx64 "\n", function, store_index, block_range_descriptor->offset ); libcnotify_printf( "%s: store: %02d relative offset\t: 0x%08" PRIx64 "\n", function, store_index, block_range_descriptor->relative_offset ); libcnotify_printf( "%s: store: %02d size\t\t\t: %" PRIu64 "\n", function, store_index, block_range_descriptor->size ); libcnotify_printf( "\n" ); } #endif return( 1 ); }
/* Reads a external key from the metadata entry * Returns 1 if successful or -1 on error */ int libbde_external_key_read( libbde_external_key_t *external_key, libbde_metadata_entry_t *metadata_entry, libcerror_error_t **error ) { libbde_key_t *key = NULL; libbde_metadata_entry_t *property_metadata_entry = NULL; uint8_t *value_data = NULL; static char *function = "libbde_external_key_read"; size_t value_data_size = 0; ssize_t read_count = 0; int property_metadata_entry_index = 0; #if defined( HAVE_DEBUG_OUTPUT ) libcstring_system_character_t filetime_string[ 32 ]; libcstring_system_character_t guid_string[ 48 ]; libfdatetime_filetime_t *filetime = NULL; libfguid_identifier_t *guid = NULL; int result = 0; #endif if( external_key == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid external key.", function ); return( -1 ); } if( metadata_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid metadata entry.", function ); return( -1 ); } if( metadata_entry->value_type != LIBBDE_VALUE_TYPE_EXTERNAL_KEY ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: invalid metadata entry - unsupported value type: 0x%04" PRIx16 ".", function, metadata_entry->value_type ); return( -1 ); } value_data = metadata_entry->value_data; value_data_size = metadata_entry->value_data_size; if( value_data_size < sizeof( bde_metadata_entry_external_key_header_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: value data size value out of bounds.", function ); return( -1 ); } if( memory_copy( external_key->identifier, ( (bde_metadata_entry_external_key_header_t *) value_data )->identifier, 16 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy volume identifier.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfguid_identifier_initialize( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create GUID.", function ); goto on_error; } if( libfguid_identifier_copy_from_byte_stream( guid, ( (bde_metadata_entry_external_key_header_t *) value_data )->identifier, 16, LIBFGUID_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy byte stream to GUID.", function ); goto on_error; } #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) result = libfguid_identifier_copy_to_utf16_string( guid, (uint16_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #else result = libfguid_identifier_copy_to_utf8_string( guid, (uint8_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy GUID to string.", function ); goto on_error; } libcnotify_printf( "%s: identifier\t\t\t\t\t: %" PRIs_LIBCSTRING_SYSTEM "\n", function, guid_string ); if( libfguid_identifier_free( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free GUID.", function ); goto on_error; } if( libfdatetime_filetime_initialize( &filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create filetime.", function ); goto on_error; } if( libfdatetime_filetime_copy_from_byte_stream( filetime, ( (bde_metadata_entry_external_key_header_t *) value_data )->modification_time, 8, LIBFDATETIME_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to copy filetime from byte stream.", function ); goto on_error; } #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) result = libfdatetime_filetime_copy_to_utf16_string( filetime, (uint16_t *) filetime_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ); #else result = libfdatetime_filetime_copy_to_utf8_string( filetime, (uint8_t *) filetime_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to copy filetime to string.", function ); goto on_error; } libcnotify_printf( "%s: modification time\t\t\t\t: %" PRIs_LIBCSTRING_SYSTEM " UTC\n", function, filetime_string ); if( libfdatetime_filetime_free( &filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free filetime.", function ); goto on_error; } libcnotify_printf( "\n" ); } #endif value_data += sizeof( bde_metadata_entry_external_key_header_t ); value_data_size -= sizeof( bde_metadata_entry_external_key_header_t ); while( value_data_size >= sizeof( bde_metadata_entry_v1_t ) ) { if( memory_compare( value_data, libbde_metadata_entry_empty, sizeof( bde_metadata_entry_v1_t ) ) == 0 ) { break; } if( libbde_metadata_entry_initialize( &property_metadata_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create property metadata entry.", function ); goto on_error; } read_count = libbde_metadata_entry_read( property_metadata_entry, value_data, value_data_size, error ); if( read_count == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read property metadata entry.", function ); goto on_error; } value_data += read_count; value_data_size -= read_count; if( property_metadata_entry->value_type == LIBBDE_VALUE_TYPE_KEY ) { if( libbde_key_initialize( &key, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create key.", function ); goto on_error; } if( libbde_key_read( key, property_metadata_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read key metadata entry.", function ); goto on_error; } if( external_key->key == NULL ) { external_key->key = key; key = NULL; } if( key != NULL ) { if( libbde_key_free( &key, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free key.", function ); goto on_error; } } } else if( property_metadata_entry->value_type == LIBBDE_VALUE_TYPE_UNICODE_STRING ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libbde_metadata_entry_read_string( property_metadata_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read string from property metadata entry.", function ); goto on_error; } #endif if( external_key->string_entry == NULL ) { external_key->string_entry = property_metadata_entry; } } if( libcdata_array_append_entry( external_key->entries_array, &property_metadata_entry_index, (intptr_t *) property_metadata_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to append property metadata entry to entries array.", function ); goto on_error; } property_metadata_entry = NULL; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( value_data_size > 0 ) { libcnotify_printf( "%s: trailing data:\n", function ); libcnotify_print_data( value_data, value_data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } } #endif return( 1 ); on_error: #if defined( HAVE_DEBUG_OUTPUT ) if( guid != NULL ) { libfguid_identifier_free( &guid, NULL ); } if( filetime != NULL ) { libfdatetime_filetime_free( &filetime, NULL ); } #endif if( key != NULL ) { libbde_key_free( &key, NULL ); } if( property_metadata_entry != NULL ) { libbde_metadata_entry_free( &property_metadata_entry, NULL ); } return( -1 ); }
/* Sets the data of an array of variable sized strings * This function will look for a NUL-character as the indicator of * the end of the string upto data_size * Returns data size of the string array if successful or -1 on error */ ssize_t libfvalue_value_type_set_data_strings_array( libfvalue_value_t *value, const uint8_t *data, size_t data_size, int encoding, libcerror_error_t **error ) { static char *function = "libfvalue_value_type_set_data_strings_array"; ssize_t data_index = 0; ssize_t last_data_index = 0; int value_entry_index = 0; if( value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid value.", function ); return( -1 ); } while( (size_t) last_data_index < data_size ) { data_index = libfvalue_value_type_get_string_size( value, &( data[ last_data_index ] ), data_size - last_data_index, error ); if( data_index == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to determine data string size.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: strings array value entry: %d data:\n", function, value_entry_index ); libcnotify_print_data( &( data[ last_data_index ] ), (size_t) data_index, 0 ); } #endif if( libfvalue_value_append_entry_data( value, &value_entry_index, &( data[ last_data_index ] ), (size_t) data_index, encoding, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append value entry.", function ); return( -1 ); } last_data_index += data_index; } return( last_data_index ); }
/* Reads a page and its values * Returns 1 if successful or -1 on error */ int libesedb_page_read( libesedb_page_t *page, libesedb_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, off64_t file_offset, libcerror_error_t **error ) { libcdata_array_t *page_tags_array = NULL; uint8_t *page_values_data = NULL; static char *function = "libesedb_page_read"; size_t page_values_data_offset = 0; size_t page_values_data_size = 0; ssize_t read_count = 0; uint32_t calculated_ecc32_checksum = 0; uint32_t calculated_page_number = 0; uint32_t calculated_xor32_checksum = 0; uint32_t stored_ecc32_checksum = 0; uint32_t stored_page_number = 0; uint32_t stored_xor32_checksum = 0; uint16_t available_data_size = 0; uint16_t available_page_tag = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint64_t value_64bit = 0; uint16_t value_16bit = 0; #endif if( page == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid page.", function ); return( -1 ); } if( page->data != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid page data already set.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } calculated_page_number = (uint32_t) ( ( file_offset - io_handle->page_size ) / io_handle->page_size ); page->offset = file_offset; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading page: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, calculated_page_number, page->offset, page->offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, page->offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek page offset: %" PRIi64 ".", function, page->offset ); goto on_error; } page->data = (uint8_t *) memory_allocate( (size_t) io_handle->page_size ); if( page->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create page data.", function ); goto on_error; } page->data_size = (size_t) io_handle->page_size; read_count = libbfio_handle_read_buffer( file_io_handle, page->data, page->data_size, error ); if( read_count != (ssize_t) page->data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read page data.", function ); goto on_error; } page_values_data = page->data; page_values_data_size = page->data_size; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: page header:\n", function ); libcnotify_print_data( page_values_data, sizeof( esedb_page_header_t ), 0 ); } #endif page->page_number = calculated_page_number; byte_stream_copy_to_uint16_little_endian( ( (esedb_page_header_t *) page_values_data )->available_data_size, available_data_size ); byte_stream_copy_to_uint32_little_endian( ( (esedb_page_header_t *) page_values_data )->previous_page, page->previous_page_number ); byte_stream_copy_to_uint32_little_endian( ( (esedb_page_header_t *) page_values_data )->next_page, page->next_page_number ); byte_stream_copy_to_uint32_little_endian( ( (esedb_page_header_t *) page_values_data )->father_data_page_object_identifier, page->father_data_page_object_identifier ); byte_stream_copy_to_uint16_little_endian( ( (esedb_page_header_t *) page_values_data )->available_page_tag, available_page_tag ); byte_stream_copy_to_uint32_little_endian( ( (esedb_page_header_t *) page_values_data )->page_flags, page->flags ); /* Make sure to read after the page flags */ if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER ) && ( io_handle->page_size >= 16384 ) ) { /* TODO handle checksum */ } else { byte_stream_copy_to_uint32_little_endian( ( (esedb_page_header_t *) page_values_data )->xor_checksum, stored_xor32_checksum ); if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_NEW_RECORD_FORMAT ) && ( ( page->flags & LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT ) != 0 ) ) { byte_stream_copy_to_uint32_little_endian( ( (esedb_page_header_t *) page_values_data )->ecc_checksum, stored_ecc32_checksum ); } else { byte_stream_copy_to_uint32_little_endian( ( (esedb_page_header_t *) page_values_data )->page_number, stored_page_number ); } } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: current page number\t\t\t\t\t: %" PRIu32 "\n", function, calculated_page_number ); if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER ) && ( io_handle->page_size >= 16384 ) ) { /* TODO handle checksum */ byte_stream_copy_to_uint64_little_endian( page_values_data, value_64bit ); libcnotify_printf( "%s: checksum\t\t\t\t\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); } else { libcnotify_printf( "%s: XOR checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", function, stored_xor32_checksum ); if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_NEW_RECORD_FORMAT ) && ( ( page->flags & LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT ) != 0 ) ) { libcnotify_printf( "%s: ECC checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", function, stored_ecc32_checksum ); } else { libcnotify_printf( "%s: page number\t\t\t\t\t\t: %" PRIu32 "\n", function, stored_page_number ); } } libcnotify_printf( "%s: database modification time:\n", function ); libcnotify_print_data( ( (esedb_page_header_t *) page_values_data )->database_modification_time, 8, 0 ); libcnotify_printf( "%s: previous page number\t\t\t\t: %" PRIu32 "\n", function, page->previous_page_number ); libcnotify_printf( "%s: next page number\t\t\t\t\t: %" PRIu32 "\n", function, page->next_page_number ); libcnotify_printf( "%s: father data page (FDP) object identifier\t\t: %" PRIu32 "\n", function, page->father_data_page_object_identifier ); libcnotify_printf( "%s: available data size\t\t\t\t\t: %" PRIu32 "\n", function, available_data_size ); byte_stream_copy_to_uint16_little_endian( ( (esedb_page_header_t *) page_values_data )->available_uncommitted_data_size, value_16bit ); libcnotify_printf( "%s: available uncommitted data size\t\t\t: %" PRIu16 "\n", function, value_16bit ); byte_stream_copy_to_uint16_little_endian( ( (esedb_page_header_t *) page_values_data )->available_data_offset, value_16bit ); libcnotify_printf( "%s: available data offset\t\t\t\t: %" PRIu16 "\n", function, value_16bit ); libcnotify_printf( "%s: available page tag\t\t\t\t\t: %" PRIu32 "\n", function, available_page_tag ); libcnotify_printf( "%s: page flags\t\t\t\t\t\t: 0x%08" PRIx32 "\n", function, page->flags ); libesedb_debug_print_page_flags( page->flags ); libcnotify_printf( "\n" ); } #endif /* TODO for now don't bother calculating a checksum for uninitialized pages */ if( ( page_values_data[ 0 ] != 0 ) || ( page_values_data[ 1 ] != 0 ) || ( page_values_data[ 2 ] != 0 ) || ( page_values_data[ 3 ] != 0 ) ) { if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER ) && ( io_handle->page_size >= 16384 ) ) { /* TODO handle checksum */ } else if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_NEW_RECORD_FORMAT ) && ( ( page->flags & LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT ) != 0 ) ) { if( libesedb_checksum_calculate_little_endian_ecc32( &calculated_ecc32_checksum, &calculated_xor32_checksum, page_values_data, page_values_data_size, 8, calculated_page_number, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unable to calculate ECC-32 and XOR-32 checksum.", function ); goto on_error; } } else { if( libesedb_checksum_calculate_little_endian_xor32( &calculated_xor32_checksum, &( page_values_data[ 4 ] ), page_values_data_size - 4, 0x89abcdef, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unable to calculate XOR-32 checksum.", function ); goto on_error; } } if( stored_xor32_checksum != calculated_xor32_checksum ) { #ifdef TODO libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_INPUT, LIBCERROR_INPUT_ERROR_CRC_MISMATCH, "%s: mismatch in page XOR-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).", function, stored_xor32_checksum, calculated_xor32_checksum ); goto on_error; #else if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: mismatch in page XOR-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n", function, stored_xor32_checksum, calculated_xor32_checksum ); } #endif } if( stored_ecc32_checksum != calculated_ecc32_checksum ) { #ifdef TODO libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_INPUT, LIBCERROR_INPUT_ERROR_CRC_MISMATCH, "%s: mismatch in page ECC-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).", function, stored_ecc32_checksum, calculated_ecc32_checksum ); goto on_error; #else if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: mismatch in page ECC-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n", function, stored_ecc32_checksum, calculated_ecc32_checksum ); } #endif } } page_values_data += sizeof( esedb_page_header_t ); page_values_data_size -= sizeof( esedb_page_header_t ); page_values_data_offset += sizeof( esedb_page_header_t ); if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER ) && ( io_handle->page_size >= 16384 ) ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: extended page header:\n", function ); libcnotify_print_data( page_values_data, 40, 0 ); } #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { byte_stream_copy_to_uint64_little_endian( ( (esedb_extended_page_header_t *) page_values_data )->checksum1, value_64bit ); libcnotify_printf( "%s: checksum1\t\t\t\t\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); byte_stream_copy_to_uint64_little_endian( ( (esedb_extended_page_header_t *) page_values_data )->checksum2, value_64bit ); libcnotify_printf( "%s: checksum2\t\t\t\t\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); byte_stream_copy_to_uint64_little_endian( ( (esedb_extended_page_header_t *) page_values_data )->checksum3, value_64bit ); libcnotify_printf( "%s: checksum3\t\t\t\t\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); byte_stream_copy_to_uint64_little_endian( ( (esedb_extended_page_header_t *) page_values_data )->page_number, value_64bit ); libcnotify_printf( "%s: page number\t\t\t\t\t\t: %" PRIu64 "\n", function, value_64bit ); libcnotify_printf( "%s: unknown1:\n", function ); libcnotify_print_data( ( (esedb_extended_page_header_t *) page_values_data )->unknown1, 8, 0 ); } #endif page_values_data += sizeof( esedb_extended_page_header_t ); page_values_data_size -= sizeof( esedb_extended_page_header_t ); page_values_data_offset += sizeof( esedb_extended_page_header_t ); } if( available_page_tag > 0 ) { /* Create the page tags array */ if( libcdata_array_initialize( &page_tags_array, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create page tags array.", function ); goto on_error; } if( libesedb_page_read_tags( page_tags_array, io_handle, available_page_tag, page->data, page->data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read page tags.", function ); goto on_error; } /* The offsets in the page tags are relative after the page header */ if( libesedb_page_read_values( page, io_handle, page_tags_array, page_values_data, page_values_data_size, page_values_data_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read page values.", function ); goto on_error; } if( libcdata_array_free( &page_tags_array, (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_tags_value_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free the page tags array.", function ); goto on_error; } } return( 1 ); on_error: if( page_tags_array != NULL ) { libcdata_array_free( &page_tags_array, (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_tags_value_free, NULL ); } if( page->data != NULL ) { memory_free( page->data ); page->data = NULL; } return( -1 ); }
/* Determines the size of a variable sized string * This function will look for a end-of-string character as the indicator * of the end of the string upto data size * Returns data size of the string if successful or -1 on error */ ssize_t libfvalue_value_type_get_string_size( libfvalue_value_t *value, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { libfvalue_internal_value_t *internal_value = NULL; static char *function = "libfvalue_value_type_get_string_size"; size_t data_index = 0; if( value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid value.", function ); return( -1 ); } internal_value = (libfvalue_internal_value_t *) value; if( ( internal_value->type != LIBFVALUE_VALUE_TYPE_STRING_BYTE_STREAM ) && ( internal_value->type != LIBFVALUE_VALUE_TYPE_STRING_UTF8 ) && ( internal_value->type != LIBFVALUE_VALUE_TYPE_STRING_UTF16 ) && ( internal_value->type != LIBFVALUE_VALUE_TYPE_STRING_UTF32 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported type: 0x%02" PRIx8 ".", function, internal_value->type ); return( -1 ); } if( data != NULL ) { if( ( internal_value->type == LIBFVALUE_VALUE_TYPE_STRING_BYTE_STREAM ) || ( internal_value->type == LIBFVALUE_VALUE_TYPE_STRING_UTF8 ) ) { while( data_index < data_size ) { if( data[ data_index ] == 0 ) { data_index += 1; break; } data_index += 1; } } else if( internal_value->type == LIBFVALUE_VALUE_TYPE_STRING_UTF16 ) { while( ( data_index + 1 ) < data_size ) { if( ( data[ data_index ] == 0 ) && ( data[ data_index + 1 ] == 0 ) ) { data_index += 2; break; } data_index += 2; } } else if( internal_value->type == LIBFVALUE_VALUE_TYPE_STRING_UTF32 ) { while( ( data_index + 3 ) < data_size ) { if( ( data[ data_index ] == 0 ) && ( data[ data_index + 1 ] == 0 ) && ( data[ data_index + 2 ] == 0 ) && ( data[ data_index + 3 ] == 0 ) ) { data_index += 4; break; } data_index += 4; } } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: string data:\n", function ); libcnotify_print_data( data, data_index, 0 ); } #endif } return( (ssize_t) data_index ); }
int main( int argc, char * const argv[] ) #endif { char destination[ 128 ]; libcerror_error_t *error = NULL; libcfile_file_t *source_file = NULL; uint8_t *buffer = NULL; uint8_t *uncompressed_data = NULL; char *program = "ascii7decompress"; libcstring_system_integer_t option = 0; char *source = NULL; size64_t source_size = 0; off_t source_offset = 0; size_t buffer_size = 0; size_t uncompressed_data_size = 0; ssize_t read_count = 0; int print_count = 0; int verbose = 0; assorted_output_version_fprint( stdout, program ); while( ( option = libcsystem_getopt( argc, argv, _LIBCSTRING_SYSTEM_STRING( "ho:s:vV" ) ) ) != (libcstring_system_integer_t) -1 ) { switch( option ) { case '?': default: fprintf( stderr, "Invalid argument: %" PRIs_LIBCSTRING_SYSTEM "\n", argv[ optind ] ); usage_fprint( stdout ); return( EXIT_FAILURE ); case 'h': usage_fprint( stdout ); return( EXIT_SUCCESS ); case 'o': source_offset = atol( optarg ); break; case 's': source_size = atol( optarg ); break; case 'v': verbose = 1; break; case 'V': assorted_output_copyright_fprint( stdout ); return( EXIT_SUCCESS ); } } if( optind == argc ) { fprintf( stderr, "Missing source file.\n" ); usage_fprint( stdout ); return( EXIT_FAILURE ); } source = argv[ optind ]; libcnotify_stream_set( stderr, NULL ); libcnotify_verbose_set( verbose ); /* Open the source file */ if( libcfile_file_initialize( &source_file, &error ) != 1 ) { fprintf( stderr, "Unable to create source file.\n" ); goto on_error; } if( libcfile_file_open( source_file, source, LIBCFILE_OPEN_READ, &error ) != 1 ) { fprintf( stderr, "Unable to open source file.\n" ); goto on_error; } if( source_size == 0 ) { if( libcfile_file_get_size( source_file, &source_size, &error ) == -1 ) { fprintf( stderr, "Unable to determine size of source file.\n" ); goto on_error; } } if( source_size == 0 ) { fprintf( stderr, "Invalid source size value is zero.\n" ); goto on_error; } if( source_size > (size_t) SSIZE_MAX ) { fprintf( stderr, "Invalid source size value exceeds maximum.\n" ); goto on_error; } /* Create the input buffer */ buffer_size = source_size; buffer = (uint8_t *) memory_allocate( sizeof( uint8_t ) * buffer_size ); if( buffer == NULL ) { fprintf( stderr, "Unable to create buffer.\n" ); return( EXIT_FAILURE ); } uncompressed_data_size = 1 + ( ( ( source_size - 1 ) * 8 ) / 7 ); uncompressed_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * uncompressed_data_size ); if( uncompressed_data == NULL ) { fprintf( stderr, "Unable to create uncompressed data buffer.\n" ); return( EXIT_FAILURE ); } /* Position the source file at the right offset */ if( libcfile_file_seek_offset( source_file, source_offset, SEEK_SET, &error ) == -1 ) { fprintf( stderr, "Unable to seek offset in source file.\n" ); goto on_error; } print_count = libcstring_narrow_string_snprintf( destination, 128, "%s.ascii7decompressed", source ); if( ( print_count < 0 ) || ( print_count > 128 ) ) { fprintf( stderr, "Unable to set destination filename.\n" ); memory_free( uncompressed_data ); memory_free( buffer ); return( EXIT_FAILURE ); } fprintf( stdout, "Starting 7-bit ASCII decompression of: %s at offset: %jd (0x%08jx).\n", source, source_offset, source_offset ); read_count = libcfile_file_read_buffer( source_file, buffer, source_size, &error ); if( read_count != (ssize_t) source_size ) { fprintf( stderr, "Unable to read from source file.\n" ); goto on_error; } /* Decompress the data */ fprintf( stderr, "Compressed data:\n" ); libcnotify_print_data( buffer, source_size, 0 ); if( ascii7_decompress( uncompressed_data, uncompressed_data_size, buffer, source_size, NULL ) != 1 ) { fprintf( stderr, "Unable to decompress data.\n" ); goto on_error; } fprintf( stderr, "Uncompressed data:\n" ); libcnotify_print_data( uncompressed_data, uncompressed_data_size, 0 ); source_offset += source_size; source_size -= source_size; #ifdef NOWRITE libcfile_file_t *destination_file = NULL; ssize_t write_count = 0; if( destination_file == NULL ) { /* Open the destination file */ if( libcfile_file_initialize( &destination_file, &error ) != 1 ) { fprintf( stderr, "Unable to create destination file.\n" ); goto on_error; } if( libcfile_file_open( destination_file, destination, LIBCFILE_OPEN_WRITE, &error ) != 1 ) { fprintf( stderr, "Unable to open destination file.\n" ); goto on_error; } } write_count = libcfile_file_write_buffer( destination_file, uncompressed_data, uncompressed_data_size, &error ); if( write_count != (ssize_t) uncompressed_data_size ) { fprintf( stderr, "Unable to write to destination file.\n" ); goto on_error; } /* Clean up */ if( destination_file != NULL ) { if( libcfile_file_close( destination_file, &error ) != 0 ) { fprintf( stderr, "Unable to close destination file.\n" ); goto on_error; } if( libcfile_file_free( &destination_file, &error ) != 1 ) { fprintf( stderr, "Unable to free destination file.\n" ); goto on_error; } } #endif /* Clean up */ if( libcfile_file_close( source_file, &error ) != 0 ) { fprintf( stderr, "Unable to close source file.\n" ); goto on_error; } if( libcfile_file_free( &source_file, &error ) != 1 ) { fprintf( stderr, "Unable to free source file.\n" ); goto on_error; } fprintf( stdout, "7-bit ASCII decompression:\tSUCCESS\n" ); memory_free( uncompressed_data ); memory_free( buffer ); return( EXIT_SUCCESS ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } #ifdef NOWRITE if( destination_file != NULL ) { libcfile_file_free( &destination_file, NULL ); } #endif if( uncompressed_data != NULL ) { memory_free( uncompressed_data ); } if( buffer != NULL ) { memory_free( buffer ); } if( source_file != NULL ) { libcfile_file_free( &source_file, NULL ); } return( EXIT_FAILURE ); }
/* Reads the security descriptor values * Returns 1 if successful or -1 on error */ int libfsntfs_security_descriptor_values_read( libfsntfs_security_descriptor_values_t *security_descriptor_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_values_read"; #if defined( HAVE_DEBUG_OUTPUT ) libfwnt_security_descriptor_t *security_descriptor = NULL; #endif if( security_descriptor_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor values.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: security descriptor data:\n", function ); libcnotify_print_data( data, data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfwnt_security_descriptor_initialize( &security_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create security descriptor.", function ); goto on_error; } if( libfwnt_security_descriptor_copy_from_byte_stream( security_descriptor, data, data_size, LIBFWNT_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy security descriptor from byte stream.", function ); goto on_error; } if( libfwnt_security_descriptor_free( &security_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free security descriptor.", function ); goto on_error; } libcnotify_printf( "\n" ); } #endif return( 1 ); on_error: #if defined( HAVE_DEBUG_OUTPUT ) if( security_descriptor != NULL ) { libfwnt_security_descriptor_free( &security_descriptor, NULL ); } #endif return( -1 ); }
/* Reads the debug data * Returns 1 if successful or -1 on error */ int libexe_debug_data_read( libexe_debug_data_t *debug_data, libbfio_handle_t *file_io_handle, uint32_t file_offset, uint32_t size, libcerror_error_t **error ) { uint8_t *data = NULL; static char *function = "libexe_debug_data_read"; size_t read_count = 0; if( debug_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid debug data.", function ); return( -1 ); } #if SIZEOF_SIZE_T <= 4 if( size > (uint32_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); return( -1 ); } #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading debug data at offset: %" PRIu32 " (0x%08" PRIx32 ")\n", function, file_offset, file_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, (off64_t) file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek debug data offset: %" PRIx32 ".", function, file_offset ); goto on_error; } data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * size ); if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create debug data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, data, size, error ); if( read_count != (ssize_t) size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read debug data.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: debug data:\n", function ); libcnotify_print_data( data, (size_t) size, 0 ); } #endif /* TODO extract values */ memory_free( data ); return( 1 ); on_error: if( data != NULL ) { memory_free( data ); } return( -1 ); }
int main( int argc, char * const argv[] ) #endif { libcerror_error_t *error = NULL; libcfile_file_t *destination_file = NULL; libcfile_file_t *source_file = NULL; libfcrypto_rc4_context_t *context = NULL; system_character_t *option_keys = NULL; system_character_t *option_target_path = NULL; system_character_t *source = NULL; uint8_t *buffer = NULL; uint8_t *decrypted_data = NULL; uint8_t *key_data = NULL; char *program = "rc4crypt"; system_integer_t option = 0; size64_t source_size = 0; size_t buffer_size = 0; size_t decrypted_data_size = 0; size_t key_data_size = 0; ssize_t read_count = 0; ssize_t write_count = 0; off_t source_offset = 0; int verbose = 0; libcnotify_stream_set( stderr, NULL ); libcnotify_verbose_set( 1 ); assorted_output_version_fprint( stdout, program ); while( ( option = assorted_getopt( argc, argv, _SYSTEM_STRING( "hk:o:s:t:vV" ) ) ) != (system_integer_t) -1 ) { switch( option ) { case (system_integer_t) '?': default: fprintf( stderr, "Invalid argument: %" PRIs_SYSTEM "\n", argv[ optind ] ); usage_fprint( stdout ); return( EXIT_FAILURE ); case (system_integer_t) 'h': usage_fprint( stdout ); return( EXIT_SUCCESS ); case (system_integer_t) 'k': option_keys = optarg; break; case (system_integer_t) 'o': source_offset = atol( optarg ); break; case (system_integer_t) 's': source_size = atol( optarg ); break; case (system_integer_t) 't': option_target_path = optarg; break; case (system_integer_t) 'v': verbose = 1; break; case (system_integer_t) 'V': assorted_output_copyright_fprint( stdout ); return( EXIT_SUCCESS ); } } if( optind == argc ) { fprintf( stderr, "Missing source file.\n" ); usage_fprint( stdout ); return( EXIT_FAILURE ); } source = argv[ optind ]; if( option_keys == NULL ) { fprintf( stderr, "Missing key.\n" ); usage_fprint( stdout ); return( EXIT_FAILURE ); } libcnotify_stream_set( stderr, NULL ); libcnotify_verbose_set( verbose ); /* Open the source file */ if( libcfile_file_initialize( &source_file, &error ) != 1 ) { fprintf( stderr, "Unable to create source file.\n" ); goto on_error; } if( libcfile_file_open( source_file, source, LIBCFILE_OPEN_READ, &error ) != 1 ) { fprintf( stderr, "Unable to open source file.\n" ); goto on_error; } if( source_size == 0 ) { if( libcfile_file_get_size( source_file, &source_size, &error ) == -1 ) { fprintf( stderr, "Unable to determine size of source file.\n" ); goto on_error; } } if( source_size == 0 ) { fprintf( stderr, "Invalid source size value is zero.\n" ); return( EXIT_FAILURE ); } if( source_size > (size_t) SSIZE_MAX ) { fprintf( stderr, "Invalid source size value exceeds maximum.\n" ); return( EXIT_FAILURE ); } /* Create the input buffer */ buffer_size = source_size; buffer = (uint8_t *) memory_allocate( sizeof( uint8_t ) * buffer_size ); if( buffer == NULL ) { fprintf( stderr, "Unable to create buffer.\n" ); return( EXIT_FAILURE ); } decrypted_data_size = source_size; decrypted_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * decrypted_data_size ); if( decrypted_data == NULL ) { fprintf( stderr, "Unable to create decrypted data buffer.\n" ); goto on_error; } /* Position the source file at the right offset */ if( libcfile_file_seek_offset( source_file, source_offset, SEEK_SET, &error ) == -1 ) { fprintf( stderr, "Unable to seek offset in source file.\n" ); goto on_error; } if( libfcrypto_rc4_context_initialize( &context, &error ) != 1 ) { fprintf( stderr, "Unable to create RC4 context.\n" ); goto on_error; } fprintf( stdout, "Starting RC4 decrypting data of: %" PRIs_SYSTEM " at offset: %" PRIjd " (0x%08" PRIjx ").\n", source, source_offset, source_offset ); read_count = libcfile_file_read_buffer( source_file, buffer, source_size, &error ); if( read_count != (ssize_t) source_size ) { fprintf( stderr, "Unable to read from source file.\n" ); goto on_error; } /* Decrypts the data */ if( rc4crypt_set_keys( option_keys, &key_data, &key_data_size, &error ) != 1 ) { fprintf( stderr, "Unable to retrieve key data from argument.\n" ); goto on_error; } if( libfcrypto_rc4_context_set_key( context, key_data, key_data_size * 8, &error ) != 1 ) { fprintf( stderr, "Unable to set key in context.\n" ); goto on_error; } if( memory_set( key_data, 0, key_data_size ) == NULL ) { fprintf( stderr, "Unable to clear key data.\n" ); goto on_error; } memory_free( key_data ); key_data = NULL; if( option_target_path == NULL ) { fprintf( stderr, "Encrypted data:\n" ); libcnotify_print_data( buffer, source_size, 0 ); } if( libfcrypto_rc4_crypt( context, buffer, source_size, decrypted_data, decrypted_data_size, &error ) != 1 ) { fprintf( stderr, "Unable to decode data.\n" ); goto on_error; } if( option_target_path == NULL ) { fprintf( stderr, "Decrypted data:\n" ); libcnotify_print_data( decrypted_data, decrypted_data_size, 0 ); } else { if( libcfile_file_initialize( &destination_file, &error ) != 1 ) { fprintf( stderr, "Unable to create destination file.\n" ); goto on_error; } if( libcfile_file_open( destination_file, option_target_path, LIBCFILE_OPEN_WRITE, &error ) != 1 ) { fprintf( stderr, "Unable to open destination file.\n" ); goto on_error; } write_count = libcfile_file_write_buffer( destination_file, decrypted_data, decrypted_data_size, &error ); if( write_count != (ssize_t) decrypted_data_size ) { fprintf( stderr, "Unable to write to destination file.\n" ); goto on_error; } if( libcfile_file_close( destination_file, &error ) != 0 ) { fprintf( stderr, "Unable to close destination file.\n" ); goto on_error; } if( libcfile_file_free( &destination_file, &error ) != 1 ) { fprintf( stderr, "Unable to free destination file.\n" ); goto on_error; } } /* Clean up */ if( libfcrypto_rc4_context_free( &context, &error ) != 1 ) { fprintf( stderr, "Unable to free RC4 context.\n" ); goto on_error; } if( libcfile_file_close( source_file, &error ) != 0 ) { fprintf( stderr, "Unable to close source file.\n" ); goto on_error; } if( libcfile_file_free( &source_file, &error ) != 1 ) { fprintf( stderr, "Unable to free source file.\n" ); goto on_error; } if( decrypted_data != NULL ) { memory_free( decrypted_data ); } if( buffer != NULL ) { memory_free( buffer ); } fprintf( stdout, "RC4 decryption:\tSUCCESS\n" ); return( EXIT_SUCCESS ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } if( destination_file != NULL ) { libcfile_file_free( &destination_file, NULL ); } if( decrypted_data != NULL ) { memory_free( decrypted_data ); } if( key_data != NULL ) { memory_set( key_data, 0, key_data_size ); memory_free( key_data ); } if( context != NULL ) { libfcrypto_rc4_context_free( &context, NULL ); } if( buffer != NULL ) { memory_free( buffer ); } if( source_file != NULL ) { libcfile_file_free( &source_file, NULL ); } fprintf( stdout, "RC4 decryption:\tFAILURE\n" ); return( EXIT_FAILURE ); }
/* Opens a file for reading * Returns 1 if successful or -1 on error */ int libevtx_file_open_read( libevtx_internal_file_t *internal_file, libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { libevtx_chunk_t *chunk = NULL; libevtx_record_values_t *record_values = NULL; libevtx_chunks_table_t *chunks_table = NULL; static char *function = "libevtx_file_open_read"; off64_t file_offset = 0; size64_t file_size = 0; uint16_t chunk_index = 0; uint16_t number_of_chunks = 0; uint16_t number_of_records = 0; uint16_t record_index = 0; int element_index = 0; int result = 0; int segment_index = 0; #if defined( HAVE_VERBOSE_OUTPUT ) uint64_t previous_record_identifier = 0; #endif #if defined( HAVE_DEBUG_OUTPUT ) uint8_t *trailing_data = NULL; size_t trailing_data_size = 0; ssize_t read_count = 0; #endif if( internal_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file.", function ); return( -1 ); } if( internal_file->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file - missing IO handle.", function ); return( -1 ); } if( internal_file->chunks_vector != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file - chunks vector already set.", function ); return( -1 ); } if( internal_file->chunks_cache != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file - chunks cache already set.", function ); return( -1 ); } if( internal_file->records_list != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file - records list already set.", function ); return( -1 ); } if( internal_file->recovered_records_list != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file - recovered records list already set.", function ); return( -1 ); } if( internal_file->records_cache != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file - records cache already set.", function ); return( -1 ); } if( libbfio_handle_get_size( file_io_handle, &file_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file size.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "Reading file header:\n" ); } #endif if( libevtx_io_handle_read_file_header( internal_file->io_handle, file_io_handle, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read file header.", function ); goto on_error; } internal_file->io_handle->chunks_data_size = file_size - internal_file->io_handle->chunks_data_offset; /* TODO clone function ? */ if( libfdata_vector_initialize( &( internal_file->chunks_vector ), (size64_t) internal_file->io_handle->chunk_size, (intptr_t *) internal_file->io_handle, NULL, NULL, (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfcache_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libevtx_io_handle_read_chunk, NULL, LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create chunks vector.", function ); goto on_error; } if( libfdata_vector_append_segment( internal_file->chunks_vector, &segment_index, 0, internal_file->io_handle->chunks_data_offset, internal_file->io_handle->chunks_data_size, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append segment to chunks vector.", function ); goto on_error; } if( libfcache_cache_initialize( &( internal_file->chunks_cache ), LIBEVTX_MAXIMUM_CACHE_ENTRIES_CHUNKS, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create chunks cache.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "Reading chunks:\n" ); } #endif if( libevtx_chunks_table_initialize( &chunks_table, internal_file->io_handle, internal_file->chunks_vector, internal_file->chunks_cache, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create chunks table.", function ); goto on_error; } /* TODO clone function ? */ if( libfdata_list_initialize( &( internal_file->records_list ), (intptr_t *) chunks_table, (int (*)(intptr_t **, libcerror_error_t **)) &libevtx_chunks_table_free, NULL, (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfcache_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libevtx_chunks_table_read_record, NULL, LIBFDATA_DATA_HANDLE_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create records list.", function ); goto on_error; } /* The chunks_table is managed by the list */ if( libfdata_list_initialize( &( internal_file->recovered_records_list ), (intptr_t *) chunks_table, NULL, NULL, (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfcache_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libevtx_chunks_table_read_record, NULL, LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create recovered records list.", function ); chunks_table = NULL; goto on_error; } chunks_table = NULL; if( libfcache_cache_initialize( &( internal_file->records_cache ), LIBEVTX_MAXIMUM_CACHE_ENTRIES_RECORDS, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create records cache.", function ); goto on_error; } file_offset = internal_file->io_handle->chunks_data_offset; while( ( file_offset + internal_file->io_handle->chunk_size ) <= (off64_t) file_size ) { if( libevtx_chunk_initialize( &chunk, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create chunk: %" PRIu16 ".", function, chunk_index ); goto on_error; } result = libevtx_chunk_read( chunk, internal_file->io_handle, file_io_handle, file_offset, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read chunk: %" PRIu16 ".", function, chunk_index ); goto on_error; } else if( result == 0 ) { if( chunk_index < internal_file->io_handle->number_of_chunks ) { #if defined( HAVE_VERBOSE_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: corruption detected in chunk: %" PRIu16 ".\n", function, chunk_index ); } #endif internal_file->io_handle->flags |= LIBEVTX_IO_HANDLE_FLAG_IS_CORRUPTED; } } else { if( ( chunk->flags & LIBEVTX_CHUNK_FLAG_IS_CORRUPTED ) != 0 ) { #if defined( HAVE_VERBOSE_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: corruption detected in chunk: %" PRIu16 ".\n", function, chunk_index ); } #endif if( chunk_index < internal_file->io_handle->number_of_chunks ) { internal_file->io_handle->flags |= LIBEVTX_IO_HANDLE_FLAG_IS_CORRUPTED; } } if( ( chunk_index < internal_file->io_handle->number_of_chunks ) || ( ( chunk->flags & LIBEVTX_CHUNK_FLAG_IS_CORRUPTED ) == 0 ) ) { number_of_chunks++; } if( libevtx_chunk_get_number_of_records( chunk, &number_of_records, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve chunk: %" PRIu16 " number of records.", function, chunk_index ); goto on_error; } for( record_index = 0; record_index < number_of_records; record_index++ ) { if( libevtx_chunk_get_record( chunk, record_index, &record_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve chunk: %" PRIu16 " record: %" PRIu16 ".", function, chunk_index, record_index ); goto on_error; } if( record_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing chunk: %" PRIu16 " record: %" PRIu16 ".", function, chunk_index, record_index ); goto on_error; } if( record_values->identifier < internal_file->io_handle->first_record_identifier ) { internal_file->io_handle->first_record_identifier = record_values->identifier; } if( record_values->identifier > internal_file->io_handle->last_record_identifier ) { internal_file->io_handle->last_record_identifier = record_values->identifier; } #if defined( HAVE_VERBOSE_OUTPUT ) if( ( chunk_index == 0 ) && ( record_index == 0 ) ) { previous_record_identifier = record_values->identifier; } else { previous_record_identifier++; if( record_values->identifier != previous_record_identifier ) { if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: detected gap in record identifier ( %" PRIu64 " != %" PRIu64 " ).\n", function, previous_record_identifier, record_values->identifier ); } previous_record_identifier = record_values->identifier; } } #endif /* The chunk index is stored in the element data size */ if( ( chunk_index < internal_file->io_handle->number_of_chunks ) || ( ( internal_file->io_handle->file_flags & LIBEVTX_FILE_FLAG_IS_DIRTY ) != 0 ) ) { if( libfdata_list_append_element( internal_file->records_list, &element_index, 0, file_offset + record_values->chunk_data_offset, (size64_t) chunk_index, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append element to records list.", function ); goto on_error; } } else { /* If the file is not dirty, records found in chunks outside the indicated * range are considered recovered */ if( libfdata_list_append_element( internal_file->recovered_records_list, &element_index, 0, file_offset + record_values->chunk_data_offset, (size64_t) chunk_index, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append element to recovered records list.", function ); goto on_error; } } /* TODO cache record values ? */ } if( libevtx_chunk_get_number_of_recovered_records( chunk, &number_of_records, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve chunk: %" PRIu16 " number of recovered records.", function, chunk_index ); goto on_error; } for( record_index = 0; record_index < number_of_records; record_index++ ) { if( libevtx_chunk_get_recovered_record( chunk, record_index, &record_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve chunk: %" PRIu16 " recovered record: %" PRIu16 ".", function, chunk_index, record_index ); goto on_error; } if( record_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing chunk: %" PRIu16 " recovered record: %" PRIu16 ".", function, chunk_index, record_index ); goto on_error; } /* TODO check for and remove duplicate identifiers ? */ /* The chunk index is stored in the element data size */ if( libfdata_list_append_element( internal_file->recovered_records_list, &element_index, 0, file_offset + record_values->chunk_data_offset, (size64_t) chunk_index, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append element to recovered records list.", function ); goto on_error; } } } file_offset += chunk->data_size; if( libevtx_chunk_free( &chunk, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free chunk: %" PRIu16 ".", function, chunk_index ); goto on_error; } chunk_index++; } internal_file->io_handle->chunks_data_size = file_offset - internal_file->io_handle->chunks_data_offset; if( number_of_chunks != internal_file->io_handle->number_of_chunks ) { #if defined( HAVE_VERBOSE_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: mismatch in number of chunks ( %" PRIu16 " != %" PRIu16 " ).\n", function, internal_file->io_handle->number_of_chunks, chunk_index ); } #endif internal_file->io_handle->flags |= LIBEVTX_IO_HANDLE_FLAG_IS_CORRUPTED; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( file_offset < (off64_t) file_size ) { trailing_data_size = (size_t) ( file_size - file_offset ); trailing_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * trailing_data_size ); if( trailing_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create trailing data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, trailing_data, trailing_data_size, error ); if( read_count != (ssize_t) trailing_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read trailing data.", function ); memory_free( trailing_data ); goto on_error; } file_offset += read_count; libcnotify_printf( "%s: trailing data:\n", function ); libcnotify_print_data( trailing_data, trailing_data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); memory_free( trailing_data ); trailing_data = NULL; } } #endif return( 1 ); on_error: #if defined( HAVE_DEBUG_OUTPUT ) if( trailing_data != NULL ) { memory_free( trailing_data ); } #endif if( chunk != NULL ) { libevtx_chunk_free( &chunk, NULL ); } if( internal_file->records_cache != NULL ) { libfcache_cache_free( &( internal_file->records_cache ), NULL ); } if( internal_file->records_list != NULL ) { libfdata_list_free( &( internal_file->records_list ), NULL ); } if( chunks_table != NULL ) { libevtx_chunks_table_free( &chunks_table, NULL ); } if( internal_file->chunks_cache != NULL ) { libfcache_cache_free( &( internal_file->chunks_cache ), NULL ); } if( internal_file->chunks_vector != NULL ) { libfdata_vector_free( &( internal_file->chunks_vector ), NULL ); } return( -1 ); }
/* Reads a data block header * Returns 1 if successful, 0 if no data block signature was found or -1 on error */ int libcreg_data_block_read_header( libcreg_data_block_t *data_block, libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { creg_data_block_header_t data_block_header; static char *function = "libcreg_data_block_read_header"; ssize_t read_count = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint16_t value_16bit = 0; #endif if( data_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data block.", function ); return( -1 ); } if( libbfio_handle_get_offset( file_io_handle, &( data_block->offset ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file offset.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading data block header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, data_block->offset, data_block->offset ); } #endif read_count = libbfio_handle_read_buffer( file_io_handle, (uint8_t *) &data_block_header, sizeof( creg_data_block_header_t ), error ); if( read_count != (ssize_t) sizeof( creg_data_block_header_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read data block header data.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: data block header:\n", function ); libcnotify_print_data( (uint8_t *) &data_block_header, sizeof( creg_data_block_header_t ), 0 ); } #endif if( memory_compare( data_block_header.signature, creg_data_block_signature, 4 ) != 0 ) { return( 0 ); } byte_stream_copy_to_uint32_little_endian( data_block_header.size, data_block->size ); byte_stream_copy_to_uint32_little_endian( data_block_header.unused_size, data_block->unused_size ); byte_stream_copy_to_uint32_little_endian( data_block_header.used_size, data_block->used_size ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: signature\t\t\t\t: %c%c%c%c\n", function, data_block_header.signature[ 0 ], data_block_header.signature[ 1 ], data_block_header.signature[ 2 ], data_block_header.signature[ 3 ] ); libcnotify_printf( "%s: size\t\t\t\t\t: %" PRIu32 "\n", function, data_block->size ); libcnotify_printf( "%s: unused size\t\t\t\t: %" PRIu32 "\n", function, data_block->unused_size ); byte_stream_copy_to_uint16_little_endian( data_block_header.unknown1, value_16bit ); libcnotify_printf( "%s: unknown1\t\t\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); byte_stream_copy_to_uint16_little_endian( data_block_header.index, value_16bit ); libcnotify_printf( "%s: index\t\t\t\t\t: %" PRIu16 "\n", function, value_16bit ); libcnotify_printf( "%s: used size\t\t\t\t: %" PRIi32 "\n", function, (int32_t) data_block->used_size ); byte_stream_copy_to_uint16_little_endian( data_block_header.unknown2, value_16bit ); libcnotify_printf( "%s: unknown2\t\t\t\t: %" PRIu16 "\n", function, value_16bit ); byte_stream_copy_to_uint16_little_endian( data_block_header.unknown3, value_16bit ); libcnotify_printf( "%s: unknown3\t\t\t\t: %" PRIu16 "\n", function, value_16bit ); libcnotify_printf( "%s: unknown3:\n", function ); libcnotify_print_data( data_block_header.unknown4, 8, 0 ); libcnotify_printf( "\n" ); } #endif /* TODO check if unused_size + used_size == size */ return( 1 ); }
/* Unwrap data using AES Key Wrap (RFC3394) * Returns 1 if successful or -1 on error */ int libfvde_encryption_aes_key_unwrap( const uint8_t *key, size_t key_bit_size, const uint8_t *wrapped_data, size_t wrapped_data_size, uint8_t *unwrapped_data, size_t unwrapped_data_size, libcerror_error_t **error ) { uint8_t block_data[ 16 ]; uint8_t vector_data[ 8 ]; libcaes_context_t *aes_context = NULL; uint8_t *initialization_vector = NULL; static char *function = "libfvde_encryption_aes_key_unwrap"; size_t block_offset = 0; size_t number_of_blocks = 0; size_t block_index = 0; int8_t round_index = 0; if( key == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid AES key.", function); return( -1 ); } if( ( key_bit_size != 128 ) && ( key_bit_size != 192 ) && ( key_bit_size != 256 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid AES key length value out of bounds.", function); return( -1 ); } if( wrapped_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid wrapped data.", function); return( -1 ); } if( wrapped_data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid wrapped data size value exceeds maximum.", function ); return( -1 ); } if( wrapped_data_size <= 8 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: invalid wrapped data size value too small.", function); return( -1 ); } if( ( wrapped_data_size % 8 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid wrapped data size value not a multitude of 8.", function); return( -1 ); } if( unwrapped_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid unwrapped data.", function); return( -1 ); } if( unwrapped_data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid unwrapped data size value exceeds maximum.", function ); return( -1 ); } if( unwrapped_data_size < wrapped_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: invalid unwrapped data size value too small.", function); return( -1 ); } if( libcaes_context_initialize( &aes_context, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize AES context.", function ); goto on_error; } if( libcaes_crypt_set_key( aes_context, LIBCAES_CRYPT_MODE_DECRYPT, key, key_bit_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set key in AES context.", function ); goto on_error; } if( memory_copy( unwrapped_data, wrapped_data, wrapped_data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy wrapped data.", function ); goto on_error; } number_of_blocks = wrapped_data_size / 8; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: number of blocks: %" PRIzd "\n", function, number_of_blocks ); libcnotify_printf( "%s: wrapped data:\n", function ); libcnotify_print_data( wrapped_data, wrapped_data_size, 0 ); } #endif /* TODO make this code more readable */ initialization_vector = unwrapped_data; for( round_index = 5; round_index >= 0; round_index-- ) { for( block_index = number_of_blocks - 1; block_index > 0; block_index-- ) { block_offset = block_index * 8; byte_stream_copy_from_uint64_big_endian( vector_data, (uint64_t) ( round_index * ( number_of_blocks - 1 ) + block_index ) ); vector_data[ 0 ] ^= initialization_vector[ 0 ]; vector_data[ 1 ] ^= initialization_vector[ 1 ]; vector_data[ 2 ] ^= initialization_vector[ 2 ]; vector_data[ 3 ] ^= initialization_vector[ 3 ]; vector_data[ 4 ] ^= initialization_vector[ 4 ]; vector_data[ 5 ] ^= initialization_vector[ 5 ]; vector_data[ 6 ] ^= initialization_vector[ 6 ]; vector_data[ 7 ] ^= initialization_vector[ 7 ]; if( memory_copy( &( block_data[ 0 ] ), vector_data, 8 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy vector data to block data.", function ); goto on_error; } if( memory_copy( &( block_data[ 8 ] ), &( unwrapped_data[ block_offset ] ), 8 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy unwrapped data to block data.", function ); goto on_error; } if( libcaes_crypt_ecb( aes_context, LIBCAES_CRYPT_MODE_DECRYPT, block_data, 16, block_data, 16, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ENCRYPTION, LIBCERROR_ENCRYPTION_ERROR_DECRYPT_FAILED, "%s: unable to decrypt block data.", function ); goto on_error; } if( memory_copy( initialization_vector, &( block_data[ 0 ] ), 8 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to decrypted block data to initialization vector.", function ); goto on_error; } if( memory_copy( &( unwrapped_data[ block_offset ] ), &( block_data[ 8 ] ), 8 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy decrypted block data to unwrapped data.", function ); goto on_error; } } } if( libcaes_context_free( &aes_context, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free AES context.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unwrapped data:\n", function ); libcnotify_print_data( unwrapped_data, wrapped_data_size, 0 ); } #endif return( 1 ); on_error: if( aes_context != NULL ) { libcaes_context_free( &aes_context, NULL); } return( -1 ); }
/* Reads a data block and determines its entries * Returns 1 if successful or -1 on error */ int libcreg_data_block_read_entries( libcreg_data_block_t *data_block, libbfio_handle_t *file_io_handle, int (*read_entry_size_function)( const uint8_t *data, size_t data_size, size_t *entry_size, libcerror_error_t **error ), int ascii_codepage, uint8_t have_debug_output LIBCREG_ATTRIBUTE_UNUSED, libcerror_error_t **error ) { libcreg_data_block_entry_t *data_block_entry = NULL; uint8_t *data_block_entry_data = NULL; static char *function = "libcreg_data_block_read_entries"; size_t data_block_data_size = 0; size_t data_block_entry_offset = 0; ssize_t read_count = 0; int entry_index = 0; int data_block_entry_index = 0; #if defined( HAVE_DEBUG_OUTPUT ) libcreg_key_name_entry_t *key_name_entry = NULL; #else LIBCREG_UNREFERENCED_PARAMETER( have_debug_output ); #endif if( data_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data block.", function ); return( -1 ); } if( data_block->data != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid data block - data already set.", function ); return( -1 ); } #if SIZEOF_SIZE_T <= 4 if( data_block->size > (size_t) SSIZE_MAX ) #else if( data_block->size > (uint32_t) SSIZE_MAX ) #endif { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid data block - size value exceeds maximum.", function ); return( -1 ); } if( read_entry_size_function == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid read entry size function.", function ); return( -1 ); } data_block->data_size = (size_t) data_block->size - sizeof( creg_data_block_header_t ); data_block->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * data_block->data_size ); if( data_block->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data block data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, data_block->data, data_block->data_size, error ); if( read_count != (ssize_t) data_block->data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read data block data.", function ); goto on_error; } data_block_entry_data = data_block->data; if( (int32_t) data_block->used_size < 0 ) { data_block_data_size = data_block->data_size; } else { data_block_data_size = (size_t) data_block->used_size - sizeof( creg_data_block_header_t ); } while( data_block_entry_offset < data_block_data_size ) { if( libcreg_data_block_entry_initialize( &data_block_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data block entry.", function ); goto on_error; } if( read_entry_size_function( &( data_block_entry_data[ data_block_entry_offset ] ), data_block->data_size - data_block_entry_offset, &( data_block_entry->size ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data block entry size.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: data block entry: %03d offset\t\t: %" PRIzd "\n", function, data_block_entry_index, data_block_entry_offset ); libcnotify_printf( "%s: data block entry: %03d size\t\t: %" PRIzd "\n", function, data_block_entry_index, data_block_entry->size ); } #endif data_block_entry->offset = data_block_entry_offset; #if defined( HAVE_DEBUG_OUTPUT ) if( ( libcnotify_verbose != 0 ) && ( have_debug_output != 0 ) ) { if( libcreg_key_name_entry_initialize( &key_name_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create key name entry.", function ); goto on_error; } if( libcreg_key_name_entry_read_data( key_name_entry, &( ( data_block->data )[ data_block_entry->offset ] ), data_block_entry->size, ascii_codepage, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read key name entry: %d.", function, data_block_entry_index ); goto on_error; } if( libcreg_key_name_entry_free( &key_name_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free key name entry.", function ); goto on_error; } } #endif data_block_entry_offset += (size_t) data_block_entry->size; if( libcdata_array_append_entry( data_block->entries_array, &entry_index, (intptr_t *) data_block_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append data block entry: %d.", function, data_block_entry_index ); goto on_error; } data_block_entry = NULL; data_block_entry_index++; } #if defined( HAVE_DEBUG_OUTPUT ) if( ( libcnotify_verbose != 0 ) && ( have_debug_output != 0 ) ) { if( data_block_entry_offset < data_block->data_size ) { libcnotify_printf( "%s: trailing data:\n", function ); libcnotify_print_data( &( ( data_block->data )[ data_block_entry_offset ] ), data_block->data_size - data_block_entry_offset, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } else { libcnotify_printf( "\n" ); } } #endif return( 1 ); on_error: #if defined( HAVE_DEBUG_OUTPUT ) if( key_name_entry != NULL ) { libcreg_key_name_entry_free( &key_name_entry, NULL ); } #endif if( data_block_entry != NULL ) { libcreg_data_block_entry_free( &data_block_entry, NULL ); } if( data_block->entries_array != NULL ) { libcdata_array_clear( data_block->entries_array, (int (*)(intptr_t **, libcerror_error_t **)) &libcreg_data_block_entry_free, NULL ); } if( data_block->data != NULL ) { memory_free( data_block->data ); data_block->data = NULL; } data_block->data_size = 0; return( -1 ); }
/* Reads the extent data * Returns 1 if successful or -1 on error */ int libfsext_extent_read_data( libfsext_extent_t *extent, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsext_extent_read_data"; uint32_t physical_block_number_upper = 0; uint16_t physical_block_number_lower = 0; if( extent == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid extent.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } if( data_size < sizeof( fsext_extent_ext4_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported data size.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid data size value exceeds maximum.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: extent data:\n", function ); libcnotify_print_data( data, data_size, 0 ); } #endif byte_stream_copy_to_uint32_little_endian( ( (fsext_extent_ext4_t *) data )->logical_block_number, extent->logical_block_number ); byte_stream_copy_to_uint16_little_endian( ( (fsext_extent_ext4_t *) data )->number_of_blocks, extent->number_of_blocks ); byte_stream_copy_to_uint16_little_endian( ( (fsext_extent_ext4_t *) data )->physical_block_number_upper, physical_block_number_upper ); byte_stream_copy_to_uint32_little_endian( ( (fsext_extent_ext4_t *) data )->physical_block_number_lower, physical_block_number_lower ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: logical block number\t\t\t\t: %" PRIu32 "\n", function, extent->logical_block_number ); libcnotify_printf( "%s: number of blocks\t\t\t\t: %" PRIu16 "\n", function, extent->number_of_blocks ); libcnotify_printf( "%s: physical block number (upper)\t\t: %" PRIu16 "\n", function, physical_block_number_upper ); libcnotify_printf( "%s: physical block number (lower)\t\t: %" PRIu32 "\n", function, physical_block_number_lower ); libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ extent->physical_block_number = ( (uint64_t) physical_block_number_upper << 32 ) | physical_block_number_lower; return( 1 ); }
/* Reads the known folder location * Returns the number of bytes read if successful or -1 on error */ int liblnk_known_folder_location_read( liblnk_known_folder_location_t *known_folder_location, liblnk_data_block_t *data_block, libcerror_error_t **error ) { lnk_data_block_known_folder_location_t *known_folder_location_data = NULL; static char *function = "liblnk_data_block_strings_read"; #if defined( HAVE_DEBUG_OUTPUT ) libcstring_system_character_t guid_string[ 48 ]; libfguid_identifier_t *guid = NULL; int result = 0; #endif if( known_folder_location == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid known folder location.", function ); return( -1 ); } if( data_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data block.", function ); return( -1 ); } if( data_block->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data block - missing data.", function ); return( -1 ); } if( data_block->data_size < sizeof( lnk_data_block_known_folder_location_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data block - data size too small.", function ); return( -1 ); } known_folder_location_data = (lnk_data_block_known_folder_location_t *) data_block->data; if( memory_copy( known_folder_location->folder_identifier, known_folder_location_data->folder_identifier, 16 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy folder identifier.", function ); goto on_error; } byte_stream_copy_to_uint32_little_endian( known_folder_location_data->first_child_segment_offset, known_folder_location->first_child_segment_offset ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfguid_identifier_initialize( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create GUID.", function ); goto on_error; } if( libfguid_identifier_copy_from_byte_stream( guid, known_folder_location->folder_identifier, 16, LIBFGUID_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy byte stream to GUID.", function ); goto on_error; } #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) result = libfguid_identifier_copy_to_utf16_string( guid, (uint16_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #else result = libfguid_identifier_copy_to_utf8_string( guid, (uint8_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy GUID to string.", function ); goto on_error; } libcnotify_printf( "%s: known folder identifier\t\t: %" PRIs_LIBCSTRING_SYSTEM "\n", function, guid_string ); libcnotify_printf( "%s: known folder name\t\t\t: %s\n", function, libfwsi_known_folder_identifier_get_name( known_folder_location->folder_identifier ) ); libcnotify_printf( "%s: first child segment offset\t\t: %" PRIu32 "\n", function, known_folder_location->first_child_segment_offset ); libcnotify_printf( "\n" ); if( libfguid_identifier_free( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free GUID.", function ); goto on_error; } } #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( data_block->data_size > sizeof( lnk_data_block_known_folder_location_t ) ) { libcnotify_printf( "%s: trailing data:\n", function ); libcnotify_print_data( &( data_block->data[ sizeof( lnk_data_block_known_folder_location_t ) ] ), data_block->data_size - sizeof( lnk_data_block_known_folder_location_t ), 0 ); } } #endif return( 1 ); on_error: #if defined( HAVE_DEBUG_OUTPUT ) if( guid != NULL ) { libfguid_identifier_free( &guid, NULL ); } #endif return( -1 ); }