SDK_PF_New

 April 8, 2021 at 11:45 am

Construction function

  1. check key validity
  2. create report
  3. check if file exist
  4. open file
  5. check if it's a valid SGX SDK PF (by size)

https://github.com/intel/linux-sgx/blob/master/sdk/protected_fs/sgx_tprotected_fs/file_init.cpp

protected_fs_file::protected_fs_file(const char* filename, const char* mode, const sgx_aes_gcm_128bit_key_t* import_key, const sgx_aes_gcm_128bit_key_t* kdk_key)
{
	sgx_status_t status = SGX_SUCCESS;
	uint8_t result = 0;
	int32_t result32 = 0;
	
	init_fields();

	if (filename == NULL || mode == NULL || 
		strnlen(filename, 1) == 0 || strnlen(mode, 1) == 0)
	{
		last_error = EINVAL;
		return;
	}

	if (strnlen(filename, FULLNAME_MAX_LEN) >= FULLNAME_MAX_LEN - 1)
	{
		last_error = ENAMETOOLONG;
		return;
	}

	if (import_key != NULL && kdk_key != NULL)
	{// import key is used only with auto generated keys
		last_error = EINVAL;
		return;
	}

	status = sgx_create_report(NULL, NULL, &report);
	if (status != SGX_SUCCESS)
	{
		last_error = status;
		return;
	}

	result32 = sgx_thread_mutex_init(&mutex, NULL);
	if (result32 != 0)
	{
		last_error = result32;
		return;
	}

	if (init_session_master_key() == false) 
		// last_error already set
		return;

	if (kdk_key != NULL)
	{
		// for new file, this value will later be saved in the meta data plain part (init_new_file)
		// for existing file, we will later compare this value with the value from the file (init_existing_file)
		use_user_kdk_key = 1; 
		memcpy(user_kdk_key, kdk_key, sizeof(sgx_aes_gcm_128bit_key_t));
	}
	
	// get the clean file name (original name might be clean or with relative path or with absolute path...)
	char clean_filename[FILENAME_MAX_LEN];
	if (cleanup_filename(filename, clean_filename) == false)
		// last_error already set
		return;
	
	if (import_key != NULL)
	{// verify the key is not empty - note from SAFE review
		sgx_aes_gcm_128bit_key_t empty_aes_key = {0};
		if (consttime_memequal(import_key, &empty_aes_key, sizeof(sgx_aes_gcm_128bit_key_t)) == 1)
		{
			last_error = EINVAL;
			return;
		}
	}

	if (parse_mode(mode) == false)
	{
		last_error = EINVAL;
		return;
	}

	status = u_sgxprotectedfs_check_if_file_exists(&result, filename); // if result == 1 --> file exists
	if (status != SGX_SUCCESS)
	{
		last_error = status;
		return;
	}

	if (open_mode.write == 1 && result == 1)
	{// try to delete existing file
		int32_t saved_errno = 0;

		result32 = remove(filename);
		if (result32 != 0)
		{
			// either can't delete or the file was already deleted by someone else
			saved_errno = errno;
			errno = 0;
		}

		// re-check
		status = u_sgxprotectedfs_check_if_file_exists(&result, filename);
		if (status != SGX_SUCCESS || result == 1)
		{
			last_error = (status != SGX_SUCCESS) ? status :
						 (saved_errno != 0) ? saved_errno : EACCES;
			return;
		}
	}

	if (open_mode.read == 1 && result == 0)
	{// file must exists
		last_error = ENOENT;
		return;
	}

	if (import_key != NULL && result == 0)
	{// file must exists - otherwise the user key is not used
		last_error = ENOENT;
		return;
	}

	// now open the file
	read_only = (open_mode.read == 1 && open_mode.update == 0); // read only files can be opened simultaneously by many enclaves

	do {
		status = u_sgxprotectedfs_exclusive_file_open(&file, filename, read_only, &real_file_size, &result32);
		if (status != SGX_SUCCESS || file == NULL)
		{
			last_error = (status != SGX_SUCCESS) ? status :
					     (result32 != 0) ? result32 : EACCES;
			break;
		}

		if (real_file_size < 0)
		{
			last_error = EINVAL;
			break;
		}

		if (real_file_size % NODE_SIZE != 0)
		{
			last_error = SGX_ERROR_FILE_NOT_SGX_FILE;
			break;
		}
		
		strncpy(recovery_filename, filename, FULLNAME_MAX_LEN - 1); // copy full file name
		recovery_filename[FULLNAME_MAX_LEN - 1] = '\0'; // just to be safe
		size_t full_name_len = strnlen(recovery_filename, RECOVERY_FILE_MAX_LEN);
		strncpy(&recovery_filename[full_name_len], "_recovery", 10);

		if (real_file_size > 0)
		{// existing file
			if (open_mode.write == 1) // redundant check, just in case
			{
				last_error = EACCES;
				break;
			}

			if (init_existing_file(filename, clean_filename, import_key) == false)
				break;
				
			if (open_mode.append == 1 && open_mode.update == 0)
				offset = encrypted_part_plain.size;
		}
		else
		{// new file
			if (init_new_file(clean_filename) == false)
				break;
		}

		file_status = SGX_FILE_STATUS_OK;

	} while(0);

	if (file_status != SGX_FILE_STATUS_OK)
	{
		if (file != NULL)
		{
			u_sgxprotectedfs_fclose(&result32, file); // we don't care about the result
			file = NULL;
		}
	}
}