示例#1
0
bool protected_fs_file::flush(/*bool mc*/)
{
	bool result = false;

	int32_t result32 = sgx_thread_mutex_lock(&mutex);
	if (result32 != 0)
	{
		last_error = result32;
		file_status = SGX_FILE_STATUS_MEMORY_CORRUPTED;
		return false;
	}

	if (file_status != SGX_FILE_STATUS_OK)
	{
		last_error = SGX_ERROR_FILE_BAD_STATUS;
		sgx_thread_mutex_unlock(&mutex);
		return false;
	}
	
	result = internal_flush(/*mc,*/ true);
	if (result == false)
	{
		assert(file_status != SGX_FILE_STATUS_OK);
		if (file_status == SGX_FILE_STATUS_OK)
			file_status = SGX_FILE_STATUS_FLUSH_ERROR; // for release set this anyway
	}

	sgx_thread_mutex_unlock(&mutex);

	return result;
}
示例#2
0
size_t protected_fs_file::write(const void* ptr, size_t size, size_t count)
{
	if (ptr == NULL || size == 0 || count == 0)
		return 0;

	int32_t result32 = sgx_thread_mutex_lock(&mutex);
	if (result32 != 0)
	{
		last_error = result32;
		file_status = SGX_FILE_STATUS_MEMORY_CORRUPTED;
		return 0;
	}

	size_t data_left_to_write = size * count;

	// prevent overlap...
#if defined(_WIN64) || defined(__x86_64__)
	if (size > UINT32_MAX || count > UINT32_MAX)
	{
		last_error = EINVAL;
		sgx_thread_mutex_unlock(&mutex);
		return 0;
	}
#else
	if (((uint64_t)((uint64_t)size * (uint64_t)count)) != (uint64_t)data_left_to_write)
	{
		last_error = EINVAL;
		sgx_thread_mutex_unlock(&mutex);
		return 0;
	}
#endif

	if (sgx_is_outside_enclave(ptr, data_left_to_write))
	{
		last_error = SGX_ERROR_INVALID_PARAMETER;
		sgx_thread_mutex_unlock(&mutex);
		return 0;
	}

	if (file_status != SGX_FILE_STATUS_OK)
	{
		last_error = SGX_ERROR_FILE_BAD_STATUS;
		sgx_thread_mutex_unlock(&mutex);
		return 0;
	}

	if (open_mode.append == 0 && open_mode.update == 0 && open_mode.write == 0)
	{
		last_error = EACCES;
		sgx_thread_mutex_unlock(&mutex);
		return 0;
	}

	if (open_mode.append == 1)
		offset = encrypted_part_plain.size; // add at the end of the file

	const unsigned char* data_to_write = (const unsigned char*)ptr;

	// the first block of user data is written in the meta-data encrypted part
	if (offset < MD_USER_DATA_SIZE)
	{
		size_t empty_place_left_in_md = MD_USER_DATA_SIZE - (size_t)offset; // offset is smaller than MD_USER_DATA_SIZE
		if (data_left_to_write <= empty_place_left_in_md)
		{
			memcpy(&encrypted_part_plain.data[offset], data_to_write, data_left_to_write);
			offset += data_left_to_write;
			data_to_write += data_left_to_write; // not needed, to prevent future errors
			data_left_to_write = 0;
		}
		else
		{
			memcpy(&encrypted_part_plain.data[offset], data_to_write, empty_place_left_in_md);
			offset += empty_place_left_in_md;
			data_to_write += empty_place_left_in_md;
			data_left_to_write -= empty_place_left_in_md;
		}
		
		if (offset > encrypted_part_plain.size)
			encrypted_part_plain.size = offset; // file grew, update the new file size

		need_writing = true;
	}

	while (data_left_to_write > 0)
	{
		file_data_node_t* file_data_node = NULL;
		file_data_node = get_data_node(); // return the data node of the current offset, will read it from disk or create new one if needed (and also the mht node if needed)
		if (file_data_node == NULL)
			break;

		size_t offset_in_node = (size_t)((offset - MD_USER_DATA_SIZE) % NODE_SIZE);
		size_t empty_place_left_in_node = NODE_SIZE - offset_in_node;
		
		if (data_left_to_write <= empty_place_left_in_node)
		{ // this will be the last write
			memcpy(&file_data_node->plain.data[offset_in_node], data_to_write, data_left_to_write);
			offset += data_left_to_write;
			data_to_write += data_left_to_write; // not needed, to prevent future errors
			data_left_to_write = 0;
		}
		else
		{
			memcpy(&file_data_node->plain.data[offset_in_node], data_to_write, empty_place_left_in_node);
			offset += empty_place_left_in_node;
			data_to_write += empty_place_left_in_node;
			data_left_to_write -= empty_place_left_in_node;

		}

		if (offset > encrypted_part_plain.size)
			encrypted_part_plain.size = offset; // file grew, update the new file size

		if (file_data_node->need_writing == false)
		{
			file_data_node->need_writing = true;
			file_mht_node_t* file_mht_node = file_data_node->parent;
			while (file_mht_node->mht_node_number != 0) // set all the mht parent nodes as 'need writing'
			{
				file_mht_node->need_writing = true;
				file_mht_node = file_mht_node->parent;
			}
			root_mht.need_writing = true;
			need_writing = true;
		}
	}

	sgx_thread_mutex_unlock(&mutex);

	size_t ret_count = ((size * count) - data_left_to_write) / size;
	return ret_count;
}
示例#3
0
size_t protected_fs_file::read(void* ptr, size_t size, size_t count)
{
	if (ptr == NULL || size == 0 || count == 0)
		return 0;

	int32_t result32 = sgx_thread_mutex_lock(&mutex);
	if (result32 != 0)
	{
		last_error = result32;
		file_status = SGX_FILE_STATUS_MEMORY_CORRUPTED;
		return 0;
	}

	size_t data_left_to_read = size * count;

	// prevent overlap...
#if defined(_WIN64) || defined(__x86_64__)
	if (size > UINT32_MAX || count > UINT32_MAX)
	{
		last_error = EINVAL;
		sgx_thread_mutex_unlock(&mutex);
		return 0;
	}
#else
	if (((uint64_t)((uint64_t)size * (uint64_t)count)) != (uint64_t)data_left_to_read)
	{
		last_error = EINVAL;
		sgx_thread_mutex_unlock(&mutex);
		return 0;
	}
#endif


	if (sgx_is_outside_enclave(ptr, data_left_to_read))
	{
		last_error = EINVAL;
		sgx_thread_mutex_unlock(&mutex);
		return 0;
	}

	if (file_status != SGX_FILE_STATUS_OK)
	{
		last_error = SGX_ERROR_FILE_BAD_STATUS;
		sgx_thread_mutex_unlock(&mutex);
		return 0;
	}

	if (open_mode.read == 0 && open_mode.update == 0)
	{
		last_error = EACCES;
		sgx_thread_mutex_unlock(&mutex);
		return 0;
	}

	if (end_of_file == true)
	{// not an error
		sgx_thread_mutex_unlock(&mutex);
		return 0;
	}

	// this check is not really needed, can go on with the code and it will do nothing until the end, but it's more 'right' to check it here
	if (offset == encrypted_part_plain.size)
	{
		end_of_file = true;
		sgx_thread_mutex_unlock(&mutex);
		return 0;
	}

	if (((uint64_t)data_left_to_read) > (uint64_t)(encrypted_part_plain.size - offset)) // the request is bigger than what's left in the file
	{
		data_left_to_read = (size_t)(encrypted_part_plain.size - offset);
	}
	size_t data_attempted_to_read = data_left_to_read; // used at the end to return how much we actually read

	unsigned char* out_buffer = (unsigned char*)ptr;

	// the first block of user data is read from the meta-data encrypted part
	if (offset < MD_USER_DATA_SIZE)
	{
		size_t data_left_in_md = MD_USER_DATA_SIZE - (size_t)offset; // offset is smaller than MD_USER_DATA_SIZE
		if (data_left_to_read <= data_left_in_md)
		{
			memcpy(out_buffer, &encrypted_part_plain.data[offset], data_left_to_read);
			offset += data_left_to_read;
			out_buffer += data_left_to_read; // not needed, to prevent future errors
			data_left_to_read = 0;
		}
		else
		{
			memcpy(out_buffer, &encrypted_part_plain.data[offset], data_left_in_md);
			offset += data_left_in_md;
			out_buffer += data_left_in_md;
			data_left_to_read -= data_left_in_md;
		}
	}

	while (data_left_to_read > 0)
	{
		file_data_node_t* file_data_node = NULL;
		file_data_node = get_data_node(); // return the data node of the current offset, will read it from disk if needed (and also the mht node if needed)
		if (file_data_node == NULL)
			break;

		size_t offset_in_node = (offset - MD_USER_DATA_SIZE) % NODE_SIZE;
		size_t data_left_in_node = NODE_SIZE - offset_in_node;
		
		if (data_left_to_read <= data_left_in_node)
		{
			memcpy(out_buffer, &file_data_node->plain.data[offset_in_node], data_left_to_read);
			offset += data_left_to_read;
			out_buffer += data_left_to_read; // not needed, to prevent future errors
			data_left_to_read = 0;
		}
		else
		{
			memcpy(out_buffer, &file_data_node->plain.data[offset_in_node], data_left_in_node);
			offset += data_left_in_node;
			out_buffer += data_left_in_node;
			data_left_to_read -= data_left_in_node;

		}
	}

	sgx_thread_mutex_unlock(&mutex);

	if (data_left_to_read == 0 &&
		data_attempted_to_read != (size * count)) // user wanted to read more and we had to shrink the request
	{
		assert(offset == encrypted_part_plain.size);
		end_of_file = true;
	}

	size_t ret_count = (data_attempted_to_read - data_left_to_read) / size;
	return ret_count;
}