!16 fscrypt:add keymanager implementation and setting user directory fscrypt policy

Merge pull request !16 from qilongzhang/fscrypt_for_merge
This commit is contained in:
openharmony_sig_ci 2022-01-13 07:58:04 +00:00 committed by Gitee
commit e44131a8fc
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
23 changed files with 866 additions and 75 deletions

View File

@ -79,6 +79,7 @@ ohos_executable("sdc") {
sources = [
"ipc/src/storage_daemon_proxy.cpp",
"client/storage_daemon_client.cpp",
"utils/file_utils.cpp",
"sdc.cpp"
]

View File

@ -35,6 +35,8 @@ public:
static int32_t DestroyUserDirs(int32_t userId, u_int32_t flags);
static int32_t InitGlobalKey(void);
static int32_t InitGlobalUserKeys(void);
static int32_t GenerateUserKeys(uint32_t userId, uint32_t flags);
static int32_t DeleteUserKeys(uint32_t userId);
private:
static sptr<IStorageDaemon> GetStorageDaemonProxy(void);

View File

@ -106,5 +106,26 @@ int32_t StorageDaemonClient::InitGlobalUserKeys(void)
return client->InitGlobalUserKeys();
}
int32_t StorageDaemonClient::GenerateUserKeys(uint32_t userId, uint32_t flags)
{
sptr<IStorageDaemon> client = GetStorageDaemonProxy();
if (client == nullptr) {
LOGE("get storage daemon service failed");
return -EAGAIN;
}
return client->GenerateUserKeys(userId, flags);
}
int32_t StorageDaemonClient::DeleteUserKeys(uint32_t userId)
{
sptr<IStorageDaemon> client = GetStorageDaemonProxy();
if (client == nullptr) {
LOGE("get storage daemon service failed");
return -EAGAIN;
}
return client->DeleteUserKeys(userId);
}
}
}

View File

@ -385,6 +385,7 @@ bool BaseKey::ClearKey(const std::string& mnt)
if (arg.removal_status_flags & FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS) {
LOGE("Other users still have this key added");
} else if (arg.removal_status_flags & FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY) {
// is the key fully removed?
LOGE("Some files using this key are still in-use");
} else {
LOGD("RemoveKey success");

View File

@ -25,6 +25,9 @@
#include <linux/keyctl.h>
#include "utils/log.h"
#include "securec.h"
#include "file_ex.h"
#include "string_ex.h"
namespace OHOS {
namespace StorageDaemon {
@ -128,5 +131,39 @@ bool KeyCtrl::GetPolicy(const std::string &path, fscrypt_get_policy_ex_arg &poli
return FsIoctl(path, FS_IOC_GET_ENCRYPTION_POLICY_EX, reinterpret_cast<void *>(&policy));
}
static bool ParseOption(const std::map<std::string, uint8_t> &policy, const std::string &defaultStr, uint8_t &value)
{
if (policy.find(defaultStr) != policy.end()) {
LOGI("use default: %{public}s", defaultStr.c_str());
value = policy.at(defaultStr);
return true;
}
LOGE("bad default policy: %{public}s, value not filled!", defaultStr.c_str());
return false;
}
bool KeyCtrl::LoadAndSetPolicy(const std::string &keyIdPath, const std::string &policyFile, const std::string &toEncrypt)
{
LOGD("enter");
std::string keyId;
if (OHOS::LoadStringFromFile(keyIdPath, keyId) == false || keyId.length() != FSCRYPT_KEY_IDENTIFIER_SIZE) {
LOGE("bad kid file content, length=%{public}d", keyId.length());
return false;
}
// Add parsing options from the policy file, now using default.
(void)policyFile;
struct fscrypt_policy_v2 arg = {.version = FSCRYPT_POLICY_V2};
(void)memcpy_s(arg.master_key_identifier, FSCRYPT_KEY_IDENTIFIER_SIZE, keyId.data(), keyId.length());
if (!ParseOption(FILENAME_MODES, DEFAULT_POLICY.fileName, arg.filenames_encryption_mode) ||
!ParseOption(CONTENTS_MODES, DEFAULT_POLICY.content, arg.contents_encryption_mode) ||
!ParseOption(POLICY_FLAGS, DEFAULT_POLICY.flags, arg.flags)) {
LOGE("parse option failed");
return false;
}
return KeyCtrl::SetPolicy(toEncrypt, arg);
}
} // namespace StorageDaemon
} // namespace OHOS

View File

@ -18,98 +18,495 @@
#include "directory_ex.h"
#include "file_ex.h"
#include "utils/log.h"
#include "utils/errno.h"
#include "key_ctrl.h"
namespace OHOS {
namespace StorageDaemon {
const UserAuth NULL_KEY_AUTH = {
.token = ""
};
const std::string DATA_EL0_DIR = std::string() + "/data/service/el0";
const std::string STORAGE_DAEMON_DIR = DATA_EL0_DIR + "/storage_daemon";
const std::string DEVICE_EL1_DIR = STORAGE_DAEMON_DIR + "/sd";
int KeyManager::GenerateDeviceKey(const std::string &dir)
const std::string FSCRYPT_USER_EL1_PUBLIC = std::string() + "/data/service/el1/public";
const std::string SERVICE_STORAGE_DAEMON_DIR = FSCRYPT_USER_EL1_PUBLIC + "/storage_daemon";
const std::string FSCRYPT_EL_DIR = SERVICE_STORAGE_DAEMON_DIR + "/sd";
const std::string USER_EL1_DIR = FSCRYPT_EL_DIR + "/el1";
const std::string USER_EL2_DIR = FSCRYPT_EL_DIR + "/el2";
int KeyManager::GenerateAndInstallDeviceKey(const std::string &dir)
{
globalEl1Key_ = std::make_unique<BaseKey>(dir);
LOGI("enter");
globalEl1Key_ = std::make_shared<BaseKey>(dir);
if (globalEl1Key_ == nullptr) {
LOGE("No memory for device el1 key");
return -ENOMEM;
}
if (globalEl1Key_->InitKey() == false) {
globalEl1Key_ = nullptr;
LOGE("global security key init failed");
return -EFAULT;
}
if (globalEl1Key_->StoreKey(NULL_KEY_AUTH) == false) {
globalEl1Key_->ClearKey();
globalEl1Key_ = nullptr;
LOGE("global security key store failed");
return -EFAULT;
}
if (globalEl1Key_->ActiveKey() == false) {
// should clear saved file ?
globalEl1Key_->ClearKey();
globalEl1Key_ = nullptr;
LOGE("global security key active failed");
return -EFAULT;
}
hasGlobalDeviceKey_ = true;
LOGI("key create success");
return 0;
}
int KeyManager::RestoreDeviceKey(const std::string &dir)
{
LOGI("enter");
if (globalEl1Key_ != nullptr) {
LOGD("device key has existed");
return 0;
}
globalEl1Key_ = std::make_shared<BaseKey>(dir);
if (globalEl1Key_ == nullptr) {
LOGE("No memory for device el1 key");
return -ENOMEM;
}
if (globalEl1Key_->InitKey() == false) {
globalEl1Key_ = nullptr;
LOGE("global security key init failed");
return -EFAULT;
}
if (globalEl1Key_->RestoreKey(NULL_KEY_AUTH) == false) {
globalEl1Key_->ClearKey();
globalEl1Key_ = nullptr;
LOGE("global security key store failed");
return -EFAULT;
}
if (globalEl1Key_->ActiveKey() == false) {
globalEl1Key_->ClearKey();
globalEl1Key_ = nullptr;
LOGE("global security key active failed");
return -EFAULT;
}
hasGlobalDeviceKey_ = true;
LOGI("key restore success");
// GetFileEncryptPattern
// SaveFileEncryptPatternToFile
return 0;
}
int KeyManager::InitGlobalDeviceKey(void)
{
LOGD("InitGlobalDeviceKey::start");
LOGI("enter");
std::lock_guard<std::mutex> lock(keyMutex_);
if (hasGlobalDeviceKey_ || globalEl1Key_ != nullptr) {
LOGD("glabal device el1 have existed");
return 0;
}
int ret = MkDir(STORAGE_DAEMON_DIR, 0700);
if (ret && errno != EEXIST) {
LOGE("create storage daemon dir error");
return ret;
}
ret = MkDir(DEVICE_EL1_DIR, 0700);
if (ret) {
if (errno != EEXIST) {
LOGE("make device el1 dir error");
return ret;
}
return RestoreDeviceKey(DEVICE_EL1_DIR);
}
return GenerateAndInstallDeviceKey(DEVICE_EL1_DIR);
}
int KeyManager::GenerateAndInstallUserKey(uint32_t userId, const std::string &dir, const UserAuth &auth, KeyType type)
{
LOGI("enter");
if (HasElkey(userId, type)) {
LOGD("The user %{public}u el %{public}u have existed", userId, type);
return 0;
}
std::shared_ptr<BaseKey> elKey = std::make_shared<BaseKey>(dir);
if (elKey == nullptr) {
LOGE("No memory for device el1 key");
return -ENOMEM;
}
if (elKey->InitKey() == false) {
LOGE("global security key init failed");
return -EFAULT;
}
if (elKey->StoreKey(auth) == false) {
elKey->ClearKey();
LOGE("global security key store failed");
return -EFAULT;
}
if (elKey->ActiveKey() == false) {
elKey->ClearKey();
LOGE("global security key active failed");
return -EFAULT;
}
if (type == EL1_KEY) {
userEl1Key_[userId] = elKey;
} else if (type == EL2_KEY) {
userEl2Key_[userId] = elKey;
}
LOGI("key create success");
return 0;
}
int KeyManager::RestoreUserKey(uint32_t userId, const std::string &dir, const UserAuth &auth, KeyType type)
{
LOGI("enter");
if (HasElkey(userId, type)) {
LOGD("The user %{public}u el %{public}u have existed", userId, type);
return 0;
}
std::shared_ptr<BaseKey> elKey = std::make_shared<BaseKey>(dir);
if (elKey == nullptr) {
LOGE("No memory for device el1 key");
return -ENOMEM;
}
if (elKey->InitKey() == false) {
LOGE("global security key init failed");
return -EFAULT;
}
if (elKey->RestoreKey(auth) == false) {
elKey->ClearKey();
LOGE("global security key store failed");
return -EFAULT;
}
if (elKey->ActiveKey() == false) {
elKey->ClearKey();
LOGE("global security key active failed");
return -EFAULT;
}
if (type == EL1_KEY) {
userEl1Key_[userId] = elKey;
} else if (type == EL2_KEY) {
userEl2Key_[userId] = elKey;
}
LOGI("key restore success");
return 0;
}
bool KeyManager::HasElkey(uint32_t userId, KeyType type)
{
LOGI("enter");
if (type == EL1_KEY) {
if (userEl1Key_.find(userId) != userEl1Key_.end()) {
LOGD("user el1 key has existed");
return true;
}
} else if (type == EL2_KEY) {
if (userEl2Key_.find(userId) != userEl2Key_.end()) {
LOGD("user el2 key has existed");
return true;
}
} else {
LOGE("key type error");
}
return false;
}
int KeyManager::LoadAllUsersEl1Key(void)
{
LOGI("enter");
std::vector<FileList> dirInfo;
ReadDigitDir(USER_EL1_DIR, dirInfo);
for (auto item : dirInfo) {
if (RestoreUserKey(item.userId, item.path, NULL_KEY_AUTH, EL1_KEY) != 0) {
LOGE("user %{public}u el1 key restore error", item.userId);
return -EFAULT;
}
}
return 0;
}
int KeyManager::InitUserElkeyStorageDir(void)
{
int ret = MkDir(SERVICE_STORAGE_DAEMON_DIR, 0700);
if (ret && errno != EEXIST) {
LOGE("make service storage daemon dir error");
return ret;
}
ret = MkDir(FSCRYPT_EL_DIR, 0700);
if (ret && errno != EEXIST) {
LOGE("make service storage daemon dir error");
return ret;
}
ret = MkDir(USER_EL1_DIR, 0700);
if (ret && errno != EEXIST) {
LOGE("make el1 storage dir error");
return ret;
}
ret = MkDir(USER_EL2_DIR, 0700);
if (ret && errno != EEXIST) {
LOGE("make el2 storage dir error");
return ret;
}
return 0;
}
int KeyManager::InitGlobalUserKeys(void)
{
LOGD("InitGlobalUserKeys start");
LOGI("enter");
std::lock_guard<std::mutex> lock(keyMutex_);
int ret = InitUserElkeyStorageDir();
if (ret) {
LOGE("Init user el storage dir failed");
return ret;
}
std::string globalUserEl1Path = USER_EL1_DIR + "/" + std::to_string(GLOBAL_USER_ID);
if (IsDir(globalUserEl1Path)) {
ret = RestoreUserKey(GLOBAL_USER_ID, globalUserEl1Path, NULL_KEY_AUTH, EL1_KEY);
if (ret != 0) {
LOGE("Restore el1 failed");
return ret;
}
} else {
ret = GenerateAndInstallUserKey(GLOBAL_USER_ID, globalUserEl1Path, NULL_KEY_AUTH, EL1_KEY);
if (ret != 0) {
LOGE("Generate el1 failed");
return ret;
}
}
std::string globalUserEl2Path = USER_EL2_DIR + "/" + std::to_string(GLOBAL_USER_ID);
if (!IsDir(globalUserEl2Path)) {
ret = GenerateAndInstallUserKey(GLOBAL_USER_ID, globalUserEl2Path, NULL_KEY_AUTH, EL2_KEY);
if (ret != 0) {
DoDeleteUserKeys(GLOBAL_USER_ID);
LOGE("Generate el2 failed");
return ret;
}
}
ret = LoadAllUsersEl1Key();
if (ret) {
LOGE("Load all users el1 failed");
return ret;
}
LOGI("Init global user key success");
return 0;
}
int KeyManager::CreateUserKeys(unsigned int user, bool isSave)
int KeyManager::GenerateUserKeys(unsigned int user, uint32_t flags)
{
LOGD("start, user:%{public}d", user);
LOGI("start, user:%{public}u", user);
std::lock_guard<std::mutex> lock(keyMutex_);
if ((!IsDir(USER_EL1_DIR)) || (!IsDir(USER_EL2_DIR))) {
LOGD("El storage dir is not existed, fbe may not be enabled");
return 0;
}
std::string el1Path = USER_EL1_DIR + "/" + std::to_string(user);
std::string el2Path = USER_EL2_DIR + "/" + std::to_string(user);
if (IsDir(el1Path) || IsDir(el2Path)) {
LOGE("user %{public}d el key have existed, create error", user);
return -EEXIST;
}
int ret = GenerateAndInstallUserKey(user, el1Path, NULL_KEY_AUTH, EL1_KEY);
if (ret) {
LOGE("user el1 create error");
return ret;
}
ret = GenerateAndInstallUserKey(user, el2Path, NULL_KEY_AUTH, EL2_KEY);
if (ret) {
DoDeleteUserKeys(user);
LOGE("user el2 create error");
return ret;
}
LOGI("Create user el success");
return 0;
}
void KeyManager::DoDeleteUserKeys(unsigned int user)
{
auto it = userEl1Key_.find(user);
if (it != userEl1Key_.end()) {
auto elKey = it->second;
elKey->ClearKey();
std::string path = elKey->GetDir();
RmDirRecurse(path);
userEl1Key_.erase(user);
}
it = userEl2Key_.find(user);
if (it != userEl2Key_.end()) {
auto elKey = it->second;
elKey->ClearKey();
std::string path = elKey->GetDir();
RmDirRecurse(path);
userEl2Key_.erase(user);
}
}
int KeyManager::DeleteUserKeys(unsigned int user)
{
LOGD("start, user:%{public}d", user);
LOGI("start, user:%{public}d", user);
std::lock_guard<std::mutex> lock(keyMutex_);
DoDeleteUserKeys(user);
LOGI("delete user key success");
return 0;
}
int KeyManager::UpdateUserAuth(unsigned int user, const std::string &token)
int KeyManager::UpdateUserAuth(unsigned int user, const std::string &token,
const std::string &composePwd)
{
LOGD("start, user:%{public}d", user);
LOGI("start, user:%{public}d", user);
std::lock_guard<std::mutex> lock(keyMutex_);
if (userEl2Key_.find(user) == userEl2Key_.end()) {
LOGE("Have not found user %{public}u el2 key", user);
return -ENOENT;
}
auto item = userEl2Key_[user];
UserAuth auth = {
.token = token,
};
if (item->RestoreKey(auth) == false) {
LOGE("Restoore key error");
return -EFAULT;
}
if (item->StoreKey(auth) == false) {
LOGE("Store key error");
return -EFAULT;
}
item->keyInfo_.key.Clear();
return 0;
}
int KeyManager::ActiveUserKey(unsigned int user)
int KeyManager::ActiveUserKey(unsigned int user, const std::string &token,
const std::string &secret)
{
LOGD("start");
LOGI("start");
std::lock_guard<std::mutex> lock(keyMutex_);
if (userEl2Key_.find(user) != userEl2Key_.end()) {
LOGE("The user %{public}u el2 have been actived", user);
return 0;
}
std::string keyDir = USER_EL2_DIR + "/" + std::to_string(user);
if (!IsDir(keyDir)) {
LOGE("Have not found user %{public}u el2", user);
return -ENOENT;
}
std::shared_ptr<BaseKey> elKey = std::make_shared<BaseKey>(keyDir);
if (elKey->InitKey() == false) {
LOGE("Init el failed");
return -EFAULT;
}
UserAuth auth = {
.token = token
};
if (elKey->RestoreKey(auth) == false) {
LOGE("Restore el failed");
return -EFAULT;
}
if (elKey->ActiveKey() == false) {
LOGE("Active user %{public}u key failed", user);
return -EFAULT;
}
userEl2Key_[user] = elKey;
LOGI("Active user %{public}u el2 success", user);
return 0;
}
int KeyManager::InActiveUserKey(unsigned int user)
int KeyManager::InActiveUserKey(unsigned int user, KeyType type)
{
LOGD("start");
LOGI("start");
std::lock_guard<std::mutex> lock(keyMutex_);
if (userEl2Key_.find(user) == userEl2Key_.end()) {
LOGE("Have not found user %{public}u el2", user);
return -ENOENT;
}
auto elKey = userEl2Key_[user];
if (elKey->ClearKey() == false) {
LOGE("Clear user %{public}u key failed", user);
return -EFAULT;
}
userEl2Key_.erase(user);
LOGI("Inactive user %{public}u el2 success", user);
return 0;
}
int KeyManager::UpdateKeyContext(unsigned int user)
int KeyManager::SetDirectoryElPolicy(unsigned int user, KeyType type,
const std::vector<FileList> &vec)
{
LOGD("start");
return 0;
}
LOGI("start");
std::string kidPath;
std::lock_guard<std::mutex> lock(keyMutex_);
if (type == EL1_KEY) {
if (userEl1Key_.find(user) == userEl1Key_.end()) {
LOGE("Have not found user %{public}u el1 key", user);
return -EINVAL;
}
kidPath = userEl1Key_[user]->GetKeyIdPath();
} else if (type == EL2_KEY) {
if (userEl2Key_.find(user) == userEl2Key_.end()) {
LOGE("Have not found user %{public}u el2 key", user);
return -EINVAL;
}
kidPath = userEl2Key_[user]->GetKeyIdPath();
} else {
LOGD("Not specify el flags, no need to crypt");
return 0;
}
int KeyManager::PrepareUserSpace(unsigned int user)
{
LOGD("start");
return 0;
}
std::string policy = "";
for (auto item : vec) {
if(KeyCtrl::LoadAndSetPolicy(kidPath, policy, item.path) == false) {
LOGE("Set directory el policy error!");
return -EFAULT;
}
}
LOGI("Set user %{public}u el policy success", user);
std::string KeyManager::GetKeyDesc(unsigned int user)
{
LOGD("start");
return "";
return 0;
}
} // namespace StorageDaemon
} // namespace OHOS

View File

@ -14,7 +14,6 @@
*/
#include <vector>
#include <string>
#include <iostream>
#include <gtest/gtest.h>
#include "base_key.h"
@ -38,9 +37,11 @@ std::string toEncryptMnt("/data");
std::string toEncryptDirLegacy("/data/test/crypto_dir_legacy");
std::string toEncryptDir("/data/test/crypto_dir");
std::string testKeyPath("/data/test/sys_de");
std::string policyPath("/data/test/policy");
OHOS::StorageDaemon::BaseKey deKey {testKeyPath};
void CryptoKeyTest::SetUpTestCase(void)
{
OHOS::RemoveFile(policyPath);
// input testsuit setup stepsetup invoked before all testcases
}
@ -180,7 +181,6 @@ HWTEST_F(CryptoKeyTest, basekey_fscrypt_v1_policy_set, TestSize.Level1)
EXPECT_EQ(true, OHOS::ForceCreateDirectory(toEncryptDirLegacy + "/test_dir"));
EXPECT_EQ(true, OHOS::SaveStringToFile(toEncryptDirLegacy + "/test_file1", "hello, world!\n"));
EXPECT_EQ(true, OHOS::SaveStringToFile(toEncryptDirLegacy + "/test_file2", "AA"));
sleep(1);
}
/**
@ -264,7 +264,6 @@ HWTEST_F(CryptoKeyTest, basekey_fscrypt_v2_policy_set, TestSize.Level1)
EXPECT_EQ(true, OHOS::ForceCreateDirectory(toEncryptDir + "/test_dir"));
EXPECT_EQ(true, OHOS::SaveStringToFile(toEncryptDir + "/test_file1", "hello, world!\n"));
EXPECT_EQ(true, OHOS::SaveStringToFile(toEncryptDir + "/test_file2", "AA"));
sleep(1);
}
/**
@ -296,6 +295,7 @@ HWTEST_F(CryptoKeyTest, basekey_fscrypt_v2_policy_get, TestSize.Level1)
HWTEST_F(CryptoKeyTest, basekey_fscrypt_v2_policy_clear, TestSize.Level1)
{
EXPECT_EQ(true, deKey.ClearKey(toEncryptMnt));
// When the v2 policy removed, the files are encrypted.
EXPECT_EQ(false, OHOS::FileExists(toEncryptDir + "/test_dir"));
EXPECT_EQ(false, OHOS::FileExists(toEncryptDir + "/test_file1"));
EXPECT_EQ(false, OHOS::FileExists(toEncryptDir + "/test_file2"));
@ -328,3 +328,55 @@ HWTEST_F(CryptoKeyTest, basekey_fscrypt_v2_policy_restore, TestSize.Level1)
EXPECT_EQ(true, deKey.ClearKey(toEncryptMnt));
}
/**
* @tc.name: basekey_fscrypt_v2_load_and_set_policy_default
* @tc.desc: Verify the KeyCtrl::LoadAndSetPolicy function.
* @tc.type: FUNC
* @tc.require: AR000GK0BP
*/
HWTEST_F(CryptoKeyTest, basekey_fscrypt_v2_load_and_set_policy_default, TestSize.Level1)
{
EXPECT_EQ(true, deKey.InitKey());
// the ext4 disk with `mke2fs -O encrypt` mounted for test
EXPECT_EQ(true, deKey.StoreKey(emptyUserAuth));
EXPECT_EQ(true, deKey.ActiveKey(toEncryptMnt));
OHOS::ForceRemoveDirectory(toEncryptDir);
OHOS::ForceCreateDirectory(toEncryptDir);
OHOS::ForceRemoveDirectory(policyPath);
EXPECT_EQ(true, OHOS::StorageDaemon::KeyCtrl::LoadAndSetPolicy(testKeyPath + "/kid", policyPath, toEncryptDir));
EXPECT_EQ(true, OHOS::ForceCreateDirectory(toEncryptDir + "/test_dir"));
EXPECT_EQ(true, OHOS::SaveStringToFile(toEncryptDir + "/test_file1", "hello, world!\n"));
EXPECT_EQ(true, OHOS::SaveStringToFile(toEncryptDir + "/test_file2", "AA"));
EXPECT_EQ(true, OHOS::SaveStringToFile(toEncryptDir + "/1111111111111111111111111111111111111111111111111", "AA"));
EXPECT_EQ(true, deKey.ClearKey(toEncryptMnt));
}
/**
* @tc.name: basekey_fscrypt_v2_load_and_set_policy_from_file
* @tc.desc: Verify the fscrypt V2 setpolicy function.
* @tc.type: FUNC
* @tc.require: AR000GK0BP
*/
HWTEST_F(CryptoKeyTest, basekey_fscrypt_v2_load_and_set_policy_from_file, TestSize.Level1)
{
EXPECT_EQ(true, deKey.InitKey());
// the ext4 disk with `mke2fs -O encrypt` mounted for test
EXPECT_EQ(true, deKey.StoreKey(emptyUserAuth));
EXPECT_EQ(true, deKey.ActiveKey(toEncryptMnt));
OHOS::ForceRemoveDirectory(toEncryptDir);
OHOS::ForceCreateDirectory(toEncryptDir);
// the `aes-128-cts/aes-128-cbc` need the CONFIG_CRYPTO_ESSIV, and the policy from file not finished yet
EXPECT_EQ(true, OHOS::SaveStringToFile(policyPath, "v2;aes-256-cts;aes-256-xts;padding-8"));
EXPECT_EQ(true, OHOS::StorageDaemon::KeyCtrl::LoadAndSetPolicy(testKeyPath + "/kid", policyPath, toEncryptDir));
EXPECT_EQ(true, OHOS::ForceCreateDirectory(toEncryptDir + "/test_dir"));
EXPECT_EQ(true, OHOS::SaveStringToFile(toEncryptDir + "/test_file1", "hello, world!\n"));
EXPECT_EQ(true, OHOS::SaveStringToFile(toEncryptDir + "/test_file2", "AA"));
EXPECT_EQ(true, OHOS::SaveStringToFile(toEncryptDir + "/1111111111111111111111111111111111111111111111111", "AA"));
EXPECT_EQ(true, deKey.ClearKey(toEncryptMnt));
}

View File

@ -37,6 +37,14 @@ public:
bool ClearKey(const std::string &mnt = "/data");
KeyInfo keyInfo_;
std::string GetDir() const
{
return dir_;
}
std::string GetKeyIdPath() const
{
return dir_ + "/kid";
}
private:
bool DoStoreKey(const UserAuth &auth);

View File

@ -49,30 +49,45 @@ public:
static bool SetPolicy(const std::string &path, fscrypt_policy_v2 &policy);
static bool GetPolicy(const std::string &path, fscrypt_get_policy_ex_arg &options);
static bool LoadAndSetPolicy(const std::string &policy, const std::string &toEncrypt);
static bool LoadAndSetPolicy(const std::string &keyIdPath, const std::string &policyFile, const std::string &toEncrypt);
};
struct CryptoOptions {
int version { 0 };
int contentsMode { 0 };
int filenamesMode { 0 };
int flags { 0 };
bool useHwWrappedKey { false };
struct EncryptPolicy {
std::string version;
std::string fileName;
std::string content;
std::string flags;
bool hwWrappedKey;
};
static const EncryptPolicy DEFAULT_POLICY = {
.version = "2",
.fileName = "aes-256-cts",
.content = "aes-256-xts",
.flags = "padding-32",
.hwWrappedKey = false,
};
static const auto CONTENTS_MODES = std::map<std::string, uint8_t> {
{"aes-256-xts", FSCRYPT_MODE_AES_256_XTS},
{"software", FSCRYPT_MODE_AES_256_XTS},
{"aes-128-cbc", FSCRYPT_MODE_AES_128_CBC},
{"adiantum", FSCRYPT_MODE_ADIANTUM},
// {"ice", FSCRYPT_MODE_PRIVATE}
};
static const auto FILENAME_MODES = std::map<std::string, uint8_t> {
{"aes-256-cts", FSCRYPT_MODE_AES_256_CTS},
// {"aes-256-heh", FSCRYPT_MODE_AES_256_HEH}
{"aes-128-cts", FSCRYPT_MODE_AES_128_CTS},
{"adiantum", FSCRYPT_MODE_ADIANTUM},
};
static const auto POLICY_FLAGS = std::map<std::string, uint8_t> {
{"padding-4", FSCRYPT_POLICY_FLAGS_PAD_4},
{"padding-8", FSCRYPT_POLICY_FLAGS_PAD_8},
{"padding-16", FSCRYPT_POLICY_FLAGS_PAD_16},
{"padding-32", FSCRYPT_POLICY_FLAGS_PAD_32},
{"direct-key", FSCRYPT_POLICY_FLAG_DIRECT_KEY}, // use with adiantum
};
} // namespace StorageDaemon
} // namespace OHOS

View File

@ -23,9 +23,16 @@
#include "key_utils.h"
#include "base_key.h"
#include "utils/file_utils.h"
namespace OHOS {
namespace StorageDaemon {
constexpr uint32_t GLOBAL_USER_ID = 0;
enum KeyType {
EL1_KEY = 1,
EL2_KEY = 2,
};
class KeyManager {
public:
static KeyManager *GetInstance(void)
@ -35,14 +42,14 @@ public:
}
int InitGlobalDeviceKey(void);
int InitGlobalUserKeys(void);
int CreateUserKeys(unsigned int user, bool isSave);
int GenerateUserKeys(unsigned int user, uint32_t flags);
int DeleteUserKeys(unsigned int user);
int UpdateUserAuth(unsigned int user, const std::string &token);
int ActiveUserKey(unsigned int user);
int InActiveUserKey(unsigned int user);
int UpdateKeyContext(unsigned int user);
std::string GetKeyDesc(unsigned int user);
int PrepareUserSpace(unsigned int user);
int UpdateUserAuth(unsigned int user, const std::string &token, const std::string &composePwd);
int ActiveUserKey(unsigned int user, const std::string &token,
const std::string &secret);
int InActiveUserKey(unsigned int user, KeyType type);
int SetDirectoryElPolicy(unsigned int user, KeyType type,
const std::vector<FileList> &vec);
private:
KeyManager()
@ -50,11 +57,18 @@ private:
hasGlobalDeviceKey_ = false;
}
~KeyManager() {}
int GenerateDeviceKey(const std::string &dir);
int GenerateAndInstallDeviceKey(const std::string &dir);
int RestoreDeviceKey(const std::string &dir);
int GenerateAndInstallUserKey(uint32_t userId, const std::string &dir, const UserAuth &auth, KeyType type);
int RestoreUserKey(uint32_t userId, const std::string &dir, const UserAuth &auth, KeyType type);
int LoadAllUsersEl1Key(void);
int InitUserElkeyStorageDir(void);
bool HasElkey(uint32_t userId, KeyType type);
void DoDeleteUserKeys(unsigned int user);
std::map<unsigned int, std::unique_ptr<BaseKey>> userEl1Key_;
std::map<unsigned int, std::unique_ptr<BaseKey>> userEl2Key_;
std::unique_ptr<BaseKey> globalEl1Key_ { nullptr };
std::map<unsigned int, std::shared_ptr<BaseKey>> userEl1Key_;
std::map<unsigned int, std::shared_ptr<BaseKey>> userEl2Key_;
std::shared_ptr<BaseKey> globalEl1Key_ { nullptr };
std::mutex keyMutex_;
bool hasGlobalDeviceKey_;

View File

@ -87,14 +87,6 @@ struct KeyContext {
KeyBlob aad;
};
struct EncryptPolicy {
std::string version;
std::string fileName;
std::string content;
int flags;
bool hwWrappedKey;
};
struct UserAuth {
std::string token;
// synthetic

View File

@ -37,6 +37,8 @@ public:
STOP_USER,
INIT_GLOBAL_KEY,
INIT_GLOBAL_USER_KEYS,
CREATE_USER_KEYS,
DELETE_USER_KEYS,
};
enum {
@ -59,6 +61,8 @@ public:
// fscrypt api
virtual int32_t InitGlobalKey(void) = 0;
virtual int32_t InitGlobalUserKeys(void) = 0;
virtual int32_t GenerateUserKeys(uint32_t userId, uint32_t flags) = 0;
virtual int32_t DeleteUserKeys(uint32_t userId) = 0;
DECLARE_INTERFACE_DESCRIPTOR(u"ohos.StorageDaemon");
};

View File

@ -37,13 +37,14 @@ public:
virtual int32_t PrepareUserDirs(int32_t userId, uint32_t flags) override;
virtual int32_t DestroyUserDirs(int32_t userId, uint32_t flags) override;
// fscrypt api
// fscrypt api, add fs mutex in KeyManager
virtual int32_t InitGlobalKey(void) override;
virtual int32_t InitGlobalUserKeys(void) override;
virtual int32_t GenerateUserKeys(uint32_t userId, uint32_t flags) override;
virtual int32_t DeleteUserKeys(uint32_t userId) override;
private:
std::mutex mutex_;
std::mutex keyMutex_;
};
} // StorageDaemon
} // OHOS

View File

@ -39,6 +39,8 @@ public:
// fscrypt api
virtual int32_t InitGlobalKey(void) override;
virtual int32_t InitGlobalUserKeys(void) override;
virtual int32_t GenerateUserKeys(uint32_t userId, uint32_t flags) override;
virtual int32_t DeleteUserKeys(uint32_t userId) override;
private:
static inline BrokerDelegator<StorageDaemonProxy> delegator_;

View File

@ -42,6 +42,8 @@ private:
// fscrypt api
int32_t HandleInitGlobalKey(MessageParcel &data, MessageParcel &reply);
int32_t HandleInitGlobalUserKeys(MessageParcel &data, MessageParcel &reply);
int32_t HandleGenerateUserKeys(MessageParcel &data, MessageParcel &reply);
int32_t HandleDeleteUserKeys(MessageParcel &data, MessageParcel &reply);
};
} // StorageDaemon
} // OHOS

View File

@ -31,6 +31,7 @@ enum ErrNo {
E_DESTROY_DIR = 8, // failed to destroy dir
E_MOUNT, // mount error
E_UMOUNT, // umount error
E_SET_POLICY,
};
}
}

View File

@ -17,17 +17,29 @@
#include <stdint.h>
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <sys/types.h>
#include <sys/mount.h>
namespace OHOS {
namespace StorageDaemon {
struct FileList {
uint32_t userId;
std::string path;
};
int32_t MkDir(const std::string &path, mode_t mode);
bool IsDir(const std::string &path);
bool PrepareDir(const std::string &path, mode_t mode, uid_t uid, gid_t gid);
bool DestroyDir(const std::string &path);
bool RmDirRecurse(const std::string &path);
int32_t Mount(const std::string &source, const std::string &target, const char *type,
unsigned long flags, const void *data);
int32_t UMount(const std::string &path);
void ReadDigitDir(const std::string &path, std::vector<FileList> &dirInfo);
bool StringToUint32(const std::string &str, uint32_t &num);
}
}

View File

@ -17,6 +17,7 @@
#include "user/user_manager.h"
#include "utils/errno.h"
#include "crypto/key_manager.h"
#include "utils/log.h"
namespace OHOS {
namespace StorageDaemon {
@ -71,15 +72,28 @@ int32_t StorageDaemon::StopUser(int32_t userId)
int32_t StorageDaemon::InitGlobalKey(void)
{
std::lock_guard<std::mutex> lock(keyMutex_);
return KeyManager::GetInstance()->InitGlobalDeviceKey();
}
int32_t StorageDaemon::InitGlobalUserKeys(void)
{
std::lock_guard<std::mutex> lock(keyMutex_);
return KeyManager::GetInstance()->InitGlobalUserKeys();
int ret = KeyManager::GetInstance()->InitGlobalUserKeys();
if (ret) {
LOGE("Init global users els failed");
return ret;
}
std::lock_guard<std::mutex> lock(mutex_);
return UserManager::Instance()->PrepareUserDirs(GLOBAL_USER_ID, CRYPTO_FLAG_EL1 | CRYPTO_FLAG_EL2);
}
int32_t StorageDaemon::GenerateUserKeys(uint32_t userId, uint32_t flags)
{
return KeyManager::GetInstance()->GenerateUserKeys(userId, flags);
}
int32_t StorageDaemon::DeleteUserKeys(uint32_t userId)
{
return KeyManager::GetInstance()->DeleteUserKeys(userId);
}
} // StorageDaemon
} // OHOS

View File

@ -15,6 +15,7 @@
#include "ipc/storage_daemon_proxy.h"
#include "utils/errno.h"
#include "utils/log.h"
namespace OHOS {
namespace StorageDaemon {
@ -152,6 +153,7 @@ int32_t StorageDaemonProxy::InitGlobalUserKeys(void)
{
MessageParcel data, reply;
MessageOption option(MessageOption::TF_SYNC);
LOGI("start");
if (!data.WriteInterfaceToken(StorageDaemonProxy::GetDescriptor())) {
return E_IPC_ERROR;
}
@ -164,5 +166,50 @@ int32_t StorageDaemonProxy::InitGlobalUserKeys(void)
return reply.ReadUint32();
}
int32_t StorageDaemonProxy::GenerateUserKeys(uint32_t userId, uint32_t flags)
{
MessageParcel data, reply;
MessageOption option(MessageOption::TF_SYNC);
LOGI("start");
if (!data.WriteInterfaceToken(StorageDaemonProxy::GetDescriptor())) {
return E_IPC_ERROR;
}
if(!data.WriteUint32(userId)) {
return E_IPC_ERROR;
}
if (!data.WriteUint32(flags)) {
return E_IPC_ERROR;
}
int err = Remote()->SendRequest(CREATE_USER_KEYS, data, reply, option);
if (err != E_OK) {
return E_IPC_ERROR;
}
return reply.ReadUint32();
}
int32_t StorageDaemonProxy::DeleteUserKeys(uint32_t userId)
{
MessageParcel data, reply;
MessageOption option(MessageOption::TF_SYNC);
if (!data.WriteInterfaceToken(StorageDaemonProxy::GetDescriptor())) {
return E_IPC_ERROR;
}
if (!data.WriteUint32(userId)) {
return E_IPC_ERROR;
}
int err = Remote()->SendRequest(DELETE_USER_KEYS, data, reply, option);
if (err != E_OK) {
return E_IPC_ERROR;
}
return reply.ReadInt32();
}
} // StorageDaemon
} // OHOS

View File

@ -50,6 +50,11 @@ int32_t StorageDaemonStub::OnRemoteRequest(uint32_t code, MessageParcel &data,
case INIT_GLOBAL_USER_KEYS:
err = HandleInitGlobalUserKeys(data, reply);
break;
case CREATE_USER_KEYS:
err = HandleGenerateUserKeys(data, reply);
break;
case DELETE_USER_KEYS:
err = HandleDeleteUserKeys(data, reply);
default: {
LOGI(" use IPCObjectStub default OnRemoteRequest");
err = IPCObjectStub::OnRemoteRequest(code, data, reply, option);
@ -137,7 +142,7 @@ int32_t StorageDaemonStub::HandleStopUser(MessageParcel &data, MessageParcel &re
int32_t StorageDaemonStub::HandleInitGlobalKey(MessageParcel &data, MessageParcel &reply)
{
int err = InitGlobalKey();
if (reply.WriteInt32(err)){
if (!reply.WriteInt32(err)){
return E_IPC_ERROR;
}
@ -147,12 +152,34 @@ int32_t StorageDaemonStub::HandleInitGlobalKey(MessageParcel &data, MessageParce
int32_t StorageDaemonStub::HandleInitGlobalUserKeys(MessageParcel &data, MessageParcel &reply)
{
int err = InitGlobalUserKeys();
if (reply.WriteInt32(err)){
if (!reply.WriteInt32(err)){
return E_IPC_ERROR;
}
return E_OK;
}
int32_t StorageDaemonStub::HandleGenerateUserKeys(MessageParcel &data, MessageParcel &reply)
{
uint32_t userId = data.ReadUint32();
uint32_t flags = data.ReadUint32();
int err = GenerateUserKeys(userId, flags);
if (!reply.WriteInt32(err)) {
return E_IPC_ERROR;
}
return E_OK;
}
int32_t StorageDaemonStub::HandleDeleteUserKeys(MessageParcel &data, MessageParcel &reply)
{
uint32_t userId = data.ReadUint32();
int err = DeleteUserKeys(userId);
if (!reply.WriteInt32(err)) {
return E_IPC_ERROR;
}
return E_OK;
}
} // StorageDaemon
} // OHOS

View File

@ -18,11 +18,12 @@
#include <vector>
#include "utils/log.h"
#include "utils/file_utils.h"
#include "storage_daemon_client.h"
static void HandleFileCrypt(const std::string &cmd, const std::vector<std::string> &args)
{
LOGI("fscrypt cmd: %s", cmd.c_str());
LOGI("fscrypt cmd: %{public}s", cmd.c_str());
if (cmd == "init_global_key") {
// sdc filecrypt init_global_key /data
int32_t ret = OHOS::StorageDaemon::StorageDaemonClient::InitGlobalKey();
@ -37,6 +38,56 @@ static void HandleFileCrypt(const std::string &cmd, const std::vector<std::strin
LOGE("Init global user keys failed");
return;
}
} else if (cmd == "generate_user_keys") {
// sdc filecrypt generate_user_keys userId flag
if (args.size() < 5) {
LOGE("Parameter nums is less than 5, please retry");
return;
}
uint32_t userId, flags;
if ((OHOS::StorageDaemon::StringToUint32(args[3], userId) == false) ||
(OHOS::StorageDaemon::StringToUint32(args[4], flags) == false)) {
LOGE("Parameter input error, please retry");
return;
}
int32_t ret = OHOS::StorageDaemon::StorageDaemonClient::GenerateUserKeys(userId, flags);
if (ret) {
LOGE("Create user %{public}u el error", userId);
return;
}
} else if (cmd == "prepare_user_storage") {
// sdc filecrypt prepare_user_storage userId flag
if (args.size() < 5) {
LOGE("Parameter nums is less than 5, please retry");
return;
}
uint32_t userId, flags;
if ((OHOS::StorageDaemon::StringToUint32(args[3], userId) == false) ||
(OHOS::StorageDaemon::StringToUint32(args[4], flags) == false)) {
LOGE("Parameter input error, please retry");
return;
}
int32_t ret = OHOS::StorageDaemon::StorageDaemonClient::PrepareUserDirs(userId, flags);
if (ret) {
LOGE("Prepare user %{public}u storage error", userId);
return;
}
} else if (cmd == "delete_user_keys") {
// sdc filecrypt delete_user_keys userId
if (args.size() < 4) {
LOGE("Parameter nums is less than 4, please retry");
return;
}
uint32_t userId;
if (OHOS::StorageDaemon::StringToUint32(args[3], userId) == false) {
LOGE("Parameter input error, please retry");
return;
}
int ret = OHOS::StorageDaemon::StorageDaemonClient::DeleteUserKeys(userId);
if (ret) {
LOGE("Delete user %{public}u key error", userId);
return;
}
}
}

View File

@ -20,6 +20,7 @@
#include "utils/string_utils.h"
#include "utils/log.h"
#include "ipc/istorage_daemon.h"
#include "crypto/key_manager.h"
using namespace std;
@ -113,12 +114,13 @@ int32_t UserManager::PrepareUserDirs(int32_t userId, uint32_t flags)
if (err != E_OK) {
return err;
}
}
// get syspara: hmdfs
err = PrepareHmdfsDirs(userId);
if (err != E_OK) {
return err;
// get syspara: hmdfs
err = PrepareHmdfsDirs(userId);
if (err != E_OK) {
LOGE("Prepare hmdfs dir error");
return err;
}
}
return E_OK;
@ -176,6 +178,24 @@ int32_t UserManager::PrepareDirsFromIdAndLevel(int32_t userId, const std::string
}
// set policy here
std::vector<FileList> list;
for (auto item : rootDirVec_) {
FileList temp;
temp.userId = userId;
temp.path = StringPrintf(item.path.c_str(), level.c_str(), userId);
list.push_back(temp);
}
if (level == el1_) {
if (KeyManager::GetInstance()->SetDirectoryElPolicy(userId, EL1_KEY, list)) {
LOGE("Set user dir el1 policy error");
return E_SET_POLICY;
}
} else if (level == el2_) {
if (KeyManager::GetInstance()->SetDirectoryElPolicy(userId, EL2_KEY, list)) {
LOGE("Set user dir el1 policy error");
return E_SET_POLICY;
}
}
if (!PrepareDirsFromVec(userId, level, subDirVec_)) {
LOGE("failed to prepare %{public}s sub dirs for userid %{public}d", level.c_str(), userId);

View File

@ -21,6 +21,7 @@
#include <sys/stat.h>
#include "utils/errno.h"
#include "utils/log.h"
#include "string_ex.h"
namespace OHOS {
namespace StorageDaemon {
@ -57,6 +58,18 @@ int32_t UMount(const std::string &path)
return TEMP_FAILURE_RETRY(umount(path.c_str()));
}
bool IsDir(const std::string &path)
{
// check whether the path exists
struct stat st;
int ret = TEMP_FAILURE_RETRY(lstat(path.c_str(), &st));
if (ret) {
return false;
}
return S_ISDIR(st.st_mode);
}
// On success, true is returned. On error, false is returned, and errno is set appropriately.
bool PrepareDir(const std::string &path, mode_t mode, uid_t uid, gid_t gid)
{
@ -142,5 +155,62 @@ bool RmDirRecurse(const std::string &path)
return true;
}
bool StringToUint32(const std::string &str, uint32_t &num)
{
if (str.empty()) {
return false;
}
if (!IsNumericStr(str)) {
LOGE("Not numeric entry");
return false;
}
int value;
if (!StrToInt(str, value)) {
LOGE("String to int convert failed");
return false;
}
num = static_cast<uint32_t>(value);
return true;
}
void ReadDigitDir(const std::string &path, std::vector<FileList> &dirInfo)
{
struct stat st;
int ret = TEMP_FAILURE_RETRY(lstat(path.c_str(), &st));
if (ret != 0 || ((st.st_mode & S_IFDIR) != S_IFDIR)) {
LOGE("path is not dir");
return;
}
DIR *dir = opendir(path.c_str());
if (!dir) {
LOGE("failed to open dir %{public}s, errno %{public}d", path.c_str(), errno);
return;
}
for (struct dirent *ent = readdir(dir); ent != nullptr; ent = readdir(dir)) {
if ((ent->d_type != DT_DIR) ||
(strcmp(ent->d_name, ".") == 0) ||
(strcmp(ent->d_name, "..") == 0)) {
continue;
}
uint32_t userId;
std::string name(ent->d_name);
if (StringToUint32(name, userId) == false) {
continue;
}
FileList entry = {
.userId = userId,
.path = path + "/" + name
};
dirInfo.push_back(entry);
}
closedir(dir);
}
} // STORAGE_DAEMON
} // OHOS