Construction function
- check key validity
- create report
- check if file exist
- open file
- 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;
}
}
}