mirror of
https://gitee.com/openharmony/filemanagement_storage_service
synced 2025-02-17 05:20:39 +00:00
Merge branch 'master' of gitee.com:openharmony/filemanagement_storage_service into master
Signed-off-by: ZhongLufu <zhonglufu@huawei.com>
This commit is contained in:
commit
dea23f4c42
@ -32,7 +32,6 @@ const int MAX_APP_INDEX = 5;
|
||||
|
||||
namespace StorageDaemon {
|
||||
constexpr uint32_t GLOBAL_USER_ID = 0;
|
||||
constexpr uint32_t ANCO_USER_ID = 100;
|
||||
constexpr uint32_t USER_ID_SIZE_VALUE = 16;
|
||||
constexpr char FILE_SEPARATOR_CHAR = '/';
|
||||
static const std::string FILE_CONTENT_SEPARATOR = ";";
|
||||
|
@ -52,8 +52,6 @@ enum ErrNo {
|
||||
E_SYS_ERR,
|
||||
E_KEY_TYPE_INVAL,
|
||||
E_DIFF_UID_GID,
|
||||
E_JSON_PARSE_ERROR,
|
||||
E_OPEN_JSON_FILE_ERROR,
|
||||
E_PARAMS_INVAL,
|
||||
E_ACTIVE_EL2_FAILED,
|
||||
};
|
||||
|
@ -326,7 +326,6 @@ group("storage_daemon_unit_test") {
|
||||
testonly = true
|
||||
deps = [
|
||||
"client/test:storage_daemon_client_test",
|
||||
"crypto/test/anco_test:anco_crypto_test",
|
||||
"crypto/test/crypto_test:crypto_test",
|
||||
"crypto/test/fbex_test:fbex_test",
|
||||
"crypto/test/fscrypt_key_v1_ext_test:fscrypt_key_v1_ext_test",
|
||||
|
@ -41,7 +41,6 @@ ohos_static_library("libsdcrypto") {
|
||||
}
|
||||
|
||||
sources = [
|
||||
"src/anco_key_manager.cpp",
|
||||
"src/app_clone_key_manager.cpp",
|
||||
"src/base_key.cpp",
|
||||
"src/crypto_delay_handler.cpp",
|
||||
@ -51,6 +50,7 @@ ohos_static_library("libsdcrypto") {
|
||||
"src/fscrypt_key_v2.cpp",
|
||||
"src/huks_master.cpp",
|
||||
"src/iam_client.cpp",
|
||||
"src/key_backup.cpp",
|
||||
"src/key_manager.cpp",
|
||||
"src/openssl_crypto.cpp",
|
||||
]
|
||||
|
@ -1,208 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "anco_key_manager.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
|
||||
#include "crypto/key_manager.h"
|
||||
#include "storage_service_errno.h"
|
||||
#include "storage_service_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace StorageDaemon {
|
||||
const std::string MKDIR = "mkdir";
|
||||
const std::string ANCO_TYPE_NONE = "encryption=None";
|
||||
const std::string ANCO_TYPE_SYS_EL1 = "encryption=Require_Sys_EL1";
|
||||
const std::string ANCO_TYPE_USER_EL1 = "encryption=Require_User_EL1";
|
||||
const std::string DATA_PATH = "/data/virt_service/rgm_hmos/anco_hmos_data/";
|
||||
const int MIN_NUM = 4;
|
||||
const int MAX_NUM = 5;
|
||||
std::map<std::string, std::string> AncoKeyManager::ownerMap_;
|
||||
|
||||
int32_t AncoKeyManager::SetAncoDirectoryElPolicy(const std::string &path, const std::string &policyType,
|
||||
unsigned int user)
|
||||
{
|
||||
std::vector<FileList> vec;
|
||||
SetUserPermissionMap();
|
||||
auto ret = ReadFileAndCreateDir(path, policyType, vec);
|
||||
if (ret != E_OK) {
|
||||
LOGE("Read file and create dir failed, ret = %{public}d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
KeyType type;
|
||||
if (policyType == ANCO_TYPE_SYS_EL1 || policyType == ANCO_TYPE_USER_EL1) {
|
||||
type = EL1_KEY;
|
||||
} else {
|
||||
type = EL2_KEY;
|
||||
}
|
||||
|
||||
ret = KeyManager::GetInstance()->SetDirectoryElPolicy(user, type, vec);
|
||||
if (ret != E_OK) {
|
||||
LOGE(" Set directory el policy failed, ret = %{public}d", ret);
|
||||
return ret;
|
||||
}
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
int32_t AncoKeyManager::ReadFileAndCreateDir(const std::string &path, const std::string &type,
|
||||
std::vector<FileList> &vec)
|
||||
{
|
||||
char realPath[PATH_MAX] = {0x00};
|
||||
if (realpath(path.c_str(), realPath) == nullptr) {
|
||||
LOGE("path not valid, path = %{private}s", path.c_str());
|
||||
return E_JSON_PARSE_ERROR;
|
||||
}
|
||||
|
||||
std::ifstream infile(std::string(realPath), std::ios::in);
|
||||
if (!infile.is_open()) {
|
||||
LOGE("Open file failed, errno = %{public}d", errno);
|
||||
return E_OPEN_JSON_FILE_ERROR;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
while (getline(infile, line)) {
|
||||
if (line == "") {
|
||||
continue;
|
||||
}
|
||||
std::istringstream iss(line);
|
||||
AncoDirInfo ancoDirInfo;
|
||||
iss >> ancoDirInfo.mkdir;
|
||||
if (ancoDirInfo.mkdir != MKDIR) {
|
||||
continue;
|
||||
}
|
||||
if (!(iss >> ancoDirInfo.path >> ancoDirInfo.mode >> ancoDirInfo.uid >> ancoDirInfo.gid >>
|
||||
ancoDirInfo.policy)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto ret = CreatePolicyDir(ancoDirInfo, type, vec);
|
||||
if (ret != E_OK) {
|
||||
LOGE(" Create policy dir failed, ret = %{public}d", ret);
|
||||
}
|
||||
}
|
||||
|
||||
infile.close();
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
int32_t AncoKeyManager::CreatePolicyDir(const AncoDirInfo &ancoDirInfo,
|
||||
const std::string &type,
|
||||
std::vector<FileList> &vec)
|
||||
{
|
||||
auto ret = CheckMemberValid(ancoDirInfo);
|
||||
if (ret != E_OK) {
|
||||
LOGE("Check Valid failed, ret = %{public}d", ret);
|
||||
return E_JSON_PARSE_ERROR;
|
||||
}
|
||||
auto mode = std::stoi(ancoDirInfo.mode, nullptr, 8);
|
||||
auto iter = AncoKeyManager::ownerMap_.find(ancoDirInfo.uid);
|
||||
if (iter == AncoKeyManager::ownerMap_.end()) {
|
||||
LOGE("AncoDirInfo.uid not found, uid = %{public}s", ancoDirInfo.uid.c_str());
|
||||
return E_JSON_PARSE_ERROR;
|
||||
}
|
||||
if (iter->second.empty() || !std::all_of(iter->second.begin(), iter->second.end(), ::isdigit)) {
|
||||
LOGE("Invalid uid: %{public}s", iter->second.c_str());
|
||||
return E_JSON_PARSE_ERROR;
|
||||
}
|
||||
auto uid = static_cast<uid_t>(std::stoi(iter->second));
|
||||
iter = AncoKeyManager::ownerMap_.find(ancoDirInfo.gid);
|
||||
if (iter == AncoKeyManager::ownerMap_.end()) {
|
||||
LOGE("AncoDirInfo.gid not found, gid = %{public}s", ancoDirInfo.gid.c_str());
|
||||
return E_JSON_PARSE_ERROR;
|
||||
}
|
||||
if (iter->second.empty() || !std::all_of(iter->second.begin(), iter->second.end(), ::isdigit)) {
|
||||
LOGE("Invalid gid: %{public}s", iter->second.c_str());
|
||||
return E_JSON_PARSE_ERROR;
|
||||
}
|
||||
auto gid = static_cast<gid_t>(std::stoi(iter->second));
|
||||
|
||||
if (ancoDirInfo.policy == ANCO_TYPE_NONE && type == ANCO_TYPE_SYS_EL1) {
|
||||
if (!PrepareDir(ancoDirInfo.path, mode, uid, gid)) {
|
||||
LOGE("Prepare dir failed");
|
||||
return E_PREPARE_DIR;
|
||||
}
|
||||
}
|
||||
if (ancoDirInfo.policy == type) {
|
||||
std::error_code errorCode;
|
||||
if (!std::filesystem::exists(ancoDirInfo.path, errorCode)) {
|
||||
FileList fileList;
|
||||
fileList.path = ancoDirInfo.path;
|
||||
vec.push_back(fileList);
|
||||
}
|
||||
if (!PrepareDir(ancoDirInfo.path, mode, uid, gid)) {
|
||||
LOGE("Prepare dir failed");
|
||||
return E_PREPARE_DIR;
|
||||
}
|
||||
}
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
int32_t AncoKeyManager::CheckMemberValid(const AncoDirInfo &ancoDirInfo)
|
||||
{
|
||||
if (ancoDirInfo.mode.empty() || ancoDirInfo.mode.length() < MIN_NUM || ancoDirInfo.mode.length() > MAX_NUM) {
|
||||
LOGE("Check ancoDirInfo.mode rule failed, mode = %{public}s", ancoDirInfo.mode.c_str());
|
||||
return E_JSON_PARSE_ERROR;
|
||||
}
|
||||
for (auto c : ancoDirInfo.mode) {
|
||||
if (!isdigit(c)) {
|
||||
LOGE("AncoDirInfo.mod not number type, mode = %{public}s", ancoDirInfo.mode.c_str());
|
||||
return E_JSON_PARSE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (ancoDirInfo.path.find(DATA_PATH) != 0) {
|
||||
LOGE("AncoDirInfo.path not valid, path = %{public}s", ancoDirInfo.path.c_str());
|
||||
return E_JSON_PARSE_ERROR;
|
||||
}
|
||||
|
||||
auto size = strnlen(ancoDirInfo.path.c_str(), PATH_MAX);
|
||||
if (size == 0 || size == PATH_MAX) {
|
||||
LOGE("AncoDirInfo.path not valid, path = %{public}s", ancoDirInfo.path.c_str());
|
||||
return E_JSON_PARSE_ERROR;
|
||||
}
|
||||
|
||||
std::regex pathRegex("^[a-zA-Z0-9_\\-/\\\\]*$");
|
||||
if (!std::regex_match(ancoDirInfo.path.c_str(), pathRegex)) {
|
||||
LOGE("AncoDirInfo.path not valid, path = %{public}s", ancoDirInfo.path.c_str());
|
||||
return E_JSON_PARSE_ERROR;
|
||||
}
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
void AncoKeyManager::SetUserPermissionMap()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(Mutex_);
|
||||
AncoKeyManager::ownerMap_["root"] = "0";
|
||||
AncoKeyManager::ownerMap_["system"] = "1000";
|
||||
AncoKeyManager::ownerMap_["media_rw"] = "1023";
|
||||
AncoKeyManager::ownerMap_["media"] = "1013";
|
||||
AncoKeyManager::ownerMap_["misc"] = "9998";
|
||||
AncoKeyManager::ownerMap_["shell"] = "2000";
|
||||
AncoKeyManager::ownerMap_["cache"] = "2001";
|
||||
AncoKeyManager::ownerMap_["log"] = "1007";
|
||||
AncoKeyManager::ownerMap_["file_manager"] = "1006";
|
||||
AncoKeyManager::ownerMap_["drm"] = "1019";
|
||||
AncoKeyManager::ownerMap_["1003"] = "1003";
|
||||
AncoKeyManager::ownerMap_["nfc"] = "1027";
|
||||
AncoKeyManager::ownerMap_["5506"] = "5506";
|
||||
AncoKeyManager::ownerMap_["1031"] = "1031";
|
||||
}
|
||||
} // namespace StorageDaemon
|
||||
} // namespace OHOS
|
@ -159,6 +159,7 @@ int FBEX::InstallEL5KeyToKernel(uint32_t userIdSingle, uint32_t userIdDouble, ui
|
||||
if (static_cast<uint32_t>(fbeRet) == FILE_ENCRY_ERROR_UECE_ALREADY_CREATED) {
|
||||
LOGE("class uece has already create, ret: 0x%{public}x, errno: %{public}d", fbeRet, errno);
|
||||
isNeedEncryptClassE = false;
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
int ret = 0;
|
||||
@ -189,6 +190,7 @@ int FBEX::InstallKeyToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32
|
||||
auto err = memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
|
||||
if (err != EOK) {
|
||||
LOGE("memcpy failed %{public}d", err);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
int ret = ioctl(fd, FBEX_IOC_ADD_IV, &ops);
|
||||
@ -226,6 +228,7 @@ int FBEX::UninstallOrLockUserKeyToKernel(uint32_t userId, uint32_t type, uint8_t
|
||||
auto err = memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
|
||||
if (err != EOK) {
|
||||
LOGE("memcpy failed %{public}d", err);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
int ret = ioctl(fd, destroy ? FBEX_IOC_DEL_IV : FBEX_IOC_USER_LOGOUT, &ops);
|
||||
@ -385,6 +388,7 @@ int FBEX::UnlockScreenToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint
|
||||
auto err = memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
|
||||
if (err != EOK) {
|
||||
LOGE("memcpy failed %{public}d", err);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
int ret = ioctl(fd, FBEX_IOC_UNLOCK_SCREEN, &ops);
|
||||
@ -430,6 +434,7 @@ int FBEX::ReadESecretToKernel(UserIdToFbeStr &userIdToFbe, uint32_t status, uint
|
||||
auto err = memcpy_s(ops.eBuffer, sizeof(ops.eBuffer), eBuffer, length);
|
||||
if (err != EOK) {
|
||||
LOGE("memcpy failed %{public}d", err);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
auto ret = ioctl(fd, FBEX_READ_CLASS_E, &ops);
|
||||
@ -479,6 +484,7 @@ int FBEX::WriteESecretToKernel(UserIdToFbeStr &userIdToFbe, uint32_t status, uin
|
||||
auto err = memcpy_s(ops.eBuffer, sizeof(ops.eBuffer), eBuffer, length);
|
||||
if (err != EOK) {
|
||||
LOGE("memcpy failed %{public}d", err);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
auto ret = ioctl(fd, FBEX_WRITE_CLASS_E, &ops);
|
||||
|
692
services/storage_daemon/crypto/src/key_backup.cpp
Normal file
692
services/storage_daemon/crypto/src/key_backup.cpp
Normal file
@ -0,0 +1,692 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "key_backup.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "securec.h"
|
||||
#include "storage_service_log.h"
|
||||
#include "unique_fd.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace StorageDaemon {
|
||||
const uint32_t INVALID_LOOP_NUM = 0xFFFFFFFF;
|
||||
|
||||
struct FileNode {
|
||||
std::string baseName;
|
||||
std::string origFile;
|
||||
std::string backFile;
|
||||
bool isSame;
|
||||
};
|
||||
|
||||
void KeyBackup::CreateBackup(const std::string &from, const std::string &to, bool removeOld)
|
||||
{
|
||||
LOGI("create backup from: %s to: %s removeOld: %d", from.c_str(), to.c_str(), removeOld ? 1 : 0);
|
||||
if (access(from.c_str(), 0) != 0) {
|
||||
LOGE("from path s not exist, path is %s", from.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (access(to.c_str(), 0) == 0) {
|
||||
if (removeOld) {
|
||||
if (RemoveNode(to) != 0) {
|
||||
LOGE("faled to remove to: %s", to.c_str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (MkdirParent(to, DEFAULT_DIR_PERM) != 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CheckAndCopyFiles(from, to);
|
||||
FsyncDirectory(to);
|
||||
}
|
||||
|
||||
int32_t KeyBackup::RemoveNode(const std::string &pathName)
|
||||
{
|
||||
LOGI("remove node pathName %s", pathName.c_str());
|
||||
struct stat st;
|
||||
if (lstat(pathName.c_str(), &st) < 0) {
|
||||
return (errno == ENOENT) ? 0 : -1;
|
||||
}
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
CleanFile(pathName);
|
||||
return remove(pathName.c_str());
|
||||
}
|
||||
|
||||
DIR *dir = opendir(pathName.c_str());
|
||||
if (dir == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct dirent *de = nullptr;
|
||||
bool rmSubNodeFail = false;
|
||||
errno = 0;
|
||||
while ((de = readdir(dir)) != nullptr) {
|
||||
if (!strcmp(de->d_name, "..") || !strcmp(de->d_name, ".")) {
|
||||
continue;
|
||||
}
|
||||
std::string dn = pathName + "/" + std::string(de->d_name);
|
||||
if (RemoveNode(dn) < 0) {
|
||||
rmSubNodeFail = true;
|
||||
break;
|
||||
}
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
if (errno < 0 || rmSubNodeFail) {
|
||||
closedir(dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (closedir(dir) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return rmdir(pathName.c_str());
|
||||
}
|
||||
|
||||
int32_t KeyBackup::TryRestoreKey(std::shared_ptr<BaseKey> &baseKey, const UserAuth &auth)
|
||||
{
|
||||
if (baseKey == nullptr) {
|
||||
LOGE("basekey is nullptr");
|
||||
return -1;
|
||||
}
|
||||
std::string keyDir = baseKey->GetDir();
|
||||
std::string backupDir;
|
||||
GetBackupDir(keyDir, backupDir);
|
||||
if (baseKey->DoRestoreKeyEx(auth, keyDir + PATH_LATEST)) {
|
||||
CheckAndFixFiles(keyDir, backupDir);
|
||||
return 0;
|
||||
}
|
||||
LOGI("origKey failed, try backupKey");
|
||||
if (baseKey->DoRestoreKeyEx(auth, backupDir + PATH_LATEST)) {
|
||||
CheckAndFixFiles(backupDir, keyDir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOGI("origKey failed, backupKey failed, so mix key");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t KeyBackup::GetBackupDir(std::string &origDir, std::string &backupDir)
|
||||
{
|
||||
LOGI("get backup dir origDir %s", origDir.c_str());
|
||||
if (origDir == DEVICE_EL1_DIR) {
|
||||
backupDir = DEVICE_EL1_DIR + BACKUP_NAME;
|
||||
LOGI("backup dir is: %s", backupDir.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto slashIndex = origDir.rfind("/");
|
||||
if (slashIndex == std::string::npos || slashIndex == 0) {
|
||||
return -1;
|
||||
}
|
||||
std::string prefixStr = origDir.substr(0, slashIndex);
|
||||
std::string endStr = origDir.substr(slashIndex);
|
||||
backupDir = prefixStr + BACKUP_NAME + endStr;
|
||||
LOGI("backup dir is: %s", backupDir.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KeyBackup::ListAndCheckDir(std::string &origDir)
|
||||
{
|
||||
LOGI("list and check dir %s", origDir.c_str());
|
||||
if (access(origDir.c_str(), F_OK) == 0) {
|
||||
return;
|
||||
}
|
||||
LOGW("list and check dir origDir is not exist %s", origDir.c_str());
|
||||
std::string backupDir;
|
||||
int32_t ret = GetBackupDir(origDir, backupDir);
|
||||
if (ret != 0) {
|
||||
LOGE("list and check dir failed %s", origDir.c_str());
|
||||
return;
|
||||
}
|
||||
if (access(backupDir.c_str(), F_OK) == 0) {
|
||||
LOGW("list and check dir origDir: %s backupDir: %s", origDir.c_str(), backupDir.c_str());
|
||||
ret = MkdirParent(origDir, DEFAULT_DIR_PERM);
|
||||
if (ret != 0) {
|
||||
return;
|
||||
}
|
||||
CheckAndCopyFiles(backupDir, origDir);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t KeyBackup::DoResotreKeyMix(std::shared_ptr<BaseKey> &baseKey, const UserAuth &auth, const std::string &keyDir,
|
||||
const std::string &backupDir)
|
||||
{
|
||||
std::string origKeyDir = keyDir + PATH_LATEST;
|
||||
std::string backupKeyDir = backupDir + PATH_LATEST;
|
||||
std::vector<struct FileNode> fileList;
|
||||
uint32_t diffNum = 0;
|
||||
int32_t ret = GetFileList(origKeyDir, backupKeyDir, fileList, diffNum);
|
||||
if (ret != 0 || diffNum <= 1) {
|
||||
LOGE("get file list failed or diffNum too least, ret: %d, diffNum: %d", ret, diffNum);
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string tempKeyDir;
|
||||
ret = CopySameFilesToTempDir(backupKeyDir, tempKeyDir, fileList);
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
diffNum = fileList.size();
|
||||
uint32_t loopNum = GetLoopMaxNum(diffNum);
|
||||
if (loopNum == INVALID_LOOP_NUM) {
|
||||
RemoveNode(tempKeyDir);
|
||||
return -1;
|
||||
}
|
||||
for (uint32_t i = 0; i <= loopNum; i++) {
|
||||
LOGI("try mix key files to decrypt i: %d loopNum: %d", i, loopNum);
|
||||
ret = CopyMixFilesToTempDir(diffNum, i, tempKeyDir, fileList);
|
||||
if (ret != 0) {
|
||||
LOGE("copy mix files to temp dir failed");
|
||||
continue;
|
||||
}
|
||||
if (baseKey->DoRestoreKeyEx(auth, tempKeyDir)) {
|
||||
LOGI("mix key files descrpt succ, fix orig and backup");
|
||||
CheckAndFixFiles(tempKeyDir, origKeyDir);
|
||||
CheckAndFixFiles(tempKeyDir, backupKeyDir);
|
||||
RemoveNode(tempKeyDir);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
RemoveNode(tempKeyDir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t KeyBackup::GetFileList(const std::string &origDir, const std::string &backDir,
|
||||
std::vector<struct FileNode> &fileList, uint32_t diffNum)
|
||||
{
|
||||
LOGI("get file list origDir: %s backDir: %s", origDir.c_str(), backDir.c_str());
|
||||
DIR *dir = opendir(origDir.c_str());
|
||||
if (dir == nullptr) {
|
||||
LOGE("fail to open %s", origDir.c_str());
|
||||
return -1;
|
||||
}
|
||||
struct dirent *de = nullptr;
|
||||
while ((de = readdir(dir)) != nullptr) {
|
||||
AddOrigFileToList(std::string(de->d_name), origDir, fileList);
|
||||
}
|
||||
closedir(dir);
|
||||
dir = nullptr;
|
||||
|
||||
dir = opendir(backDir.c_str());
|
||||
if (dir == nullptr) {
|
||||
LOGE("fail to open %s", backDir.c_str());
|
||||
return -1;
|
||||
}
|
||||
while ((de = readdir(dir)) != nullptr) {
|
||||
AddBackupFileToList(std::string(de->d_name), backDir, fileList);
|
||||
}
|
||||
closedir(dir);
|
||||
dir = nullptr;
|
||||
|
||||
diffNum = GetDiffFilesNum(fileList);
|
||||
LOGI("get file list origDir: %s backDir: %s diffNum: %d", origDir.c_str(), backDir.c_str(), diffNum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool KeyBackup::IsRegFile(const std::string &filePath)
|
||||
{
|
||||
struct stat st;
|
||||
if (lstat(filePath.c_str(), &st) < 0) {
|
||||
LOGE("lstat failed %s", filePath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
LOGE("filePath is not reg file %s", filePath.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void KeyBackup::AddOrigFileToList(const std::string &fileName, const std::string &origDir,
|
||||
std::vector<struct FileNode> &fileList)
|
||||
{
|
||||
if (fileName.compare("..") == 0 || fileName.compare(".") == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string filePath = origDir + "/" + fileName;
|
||||
if (!IsRegFile(filePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct FileNode fl;
|
||||
fl.baseName = fileName;
|
||||
fl.origFile = filePath;
|
||||
fl.backFile = "";
|
||||
fl.isSame = false;
|
||||
fileList.push_back(fl);
|
||||
return;
|
||||
}
|
||||
|
||||
void KeyBackup::AddBackupFileToList(const std::string &fileName, const std::string &backDir,
|
||||
std::vector<struct FileNode> &fileList)
|
||||
{
|
||||
if (fileName.compare("..") == 0 || fileName.compare(".") == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string filePath = backDir + "/" + fileName;
|
||||
if (!IsRegFile(filePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto iter = fileList.begin(); iter != fileList.end(); ++iter) {
|
||||
if (iter->baseName.compare(fileName) == 0) {
|
||||
iter->backFile = backDir + "/" + fileName;
|
||||
if (CompareFile(iter->origFile, iter->backFile) == 0) {
|
||||
iter->isSame = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct FileNode fl;
|
||||
fl.baseName = fileName;
|
||||
fl.origFile = "";
|
||||
fl.backFile = filePath;
|
||||
fl.isSame = false;
|
||||
fileList.push_back(fl);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t KeyBackup::GetDiffFilesNum(const std::vector<struct FileNode> &fileList)
|
||||
{
|
||||
uint32_t diffNum = 0;
|
||||
for (auto iter = fileList.begin(); iter != fileList.end(); ++iter) {
|
||||
LOGI("fileList contain origFile: %s, backupFile: %s, isSame: %d, fileName: %s", iter->origFile.c_str(),
|
||||
iter->backFile.c_str(), iter->isSame ? 0 : 1, iter->baseName.c_str());
|
||||
if (!iter->isSame) {
|
||||
diffNum++;
|
||||
}
|
||||
}
|
||||
LOGI("diff files num %d", diffNum);
|
||||
return diffNum;
|
||||
}
|
||||
|
||||
int32_t KeyBackup::CopySameFilesToTempDir(const std::string &backupDir, std::string &tempDir,
|
||||
std::vector<struct FileNode> &fileList)
|
||||
{
|
||||
LOGI("copy same files to temp dir, backupDir: %s tempDir: %s", backupDir.c_str(), tempDir.c_str());
|
||||
int32_t ret = CreateTempDirForMixFiles(backupDir, tempDir);
|
||||
if (ret != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (auto iter = fileList.begin(); iter != fileList.end();) {
|
||||
if (iter->isSame || iter->backFile.empty()) {
|
||||
ret = CheckAndCopyOneFile(iter->origFile, tempDir + "/" + iter->baseName);
|
||||
if (ret != 0) {
|
||||
RemoveNode(tempDir);
|
||||
return -1;
|
||||
}
|
||||
iter = fileList.erase(iter);
|
||||
} else if (iter->origFile.empty()) {
|
||||
ret = CheckAndCopyOneFile(iter->backFile, tempDir + "/" + iter->baseName);
|
||||
if (ret != 0) {
|
||||
RemoveNode(tempDir);
|
||||
return -1;
|
||||
}
|
||||
iter = fileList.erase(iter);
|
||||
} else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t KeyBackup::CreateTempDirForMixFiles(const std::string &backupDir, std::string &tempDir)
|
||||
{
|
||||
int32_t pos = backupDir.rfind("/");
|
||||
std::string parentDir = backupDir.substr(0, pos);
|
||||
tempDir = parentDir + "/temp";
|
||||
|
||||
RemoveNode(tempDir);
|
||||
int32_t ret = HandleCopyDir(backupDir, tempDir);
|
||||
if (ret != 0) {
|
||||
LOGE("create temp dir for mix files failed, ret: %d, tempDir: %s", ret, tempDir.c_str());
|
||||
} else {
|
||||
LOGI("create temp dir for mix files success, tempDir: %s", tempDir.c_str());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t KeyBackup::GetLoopMaxNum(uint32_t diffNum)
|
||||
{
|
||||
if (diffNum > MAX_FILE_NUM) {
|
||||
LOGE("there are too many different files, diffNum: %d", diffNum);
|
||||
return INVALID_LOOP_NUM;
|
||||
}
|
||||
|
||||
const double fileNum = 2;
|
||||
return static_cast<uint32_t>(pow(fileNum, diffNum) - 1);
|
||||
}
|
||||
|
||||
int32_t KeyBackup::CopyMixFilesToTempDir(uint32_t diffNum, uint32_t num, const std::string &tempDir,
|
||||
const std::vector<struct FileNode> &fileList)
|
||||
{
|
||||
for (uint32_t i = 0; i < diffNum; i++) {
|
||||
std::string from;
|
||||
if (num & (1UL << i)) {
|
||||
from = fileList[i].backFile;
|
||||
} else {
|
||||
from = fileList[i].origFile;
|
||||
}
|
||||
std::string to = tempDir + "/" + fileList[i].baseName;
|
||||
if (CheckAndCopyOneFile(from, to) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KeyBackup::CheckAndFixFiles(const std::string &from, const std::string &to)
|
||||
{
|
||||
LOGI("check fix files from: %s to: %s", from.c_str(), to.c_str());
|
||||
CreateBackup(from, to, false);
|
||||
FsyncDirectory(to);
|
||||
}
|
||||
|
||||
void KeyBackup::FsyncDirectory(const std::string &dirName)
|
||||
{
|
||||
LOGI("sync directory dirName %s", dirName.c_str());
|
||||
UniqueFd fd(open(dirName.c_str(), O_RDONLY | O_CLOEXEC));
|
||||
if (fd < 0) {
|
||||
LOGE("failed to open %s", dirName.c_str());
|
||||
return;
|
||||
}
|
||||
if (fsync(fd) == -1) {
|
||||
if (errno == EROFS || errno == EINVAL) {
|
||||
LOGE("file system does not support sync, dirName: %s", dirName.c_str());
|
||||
} else {
|
||||
LOGE("sync failed: %s", dirName.c_str());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t KeyBackup::MkdirParent(const std::string &pathName, mode_t mode)
|
||||
{
|
||||
LOGI("mkdir parent dirName %s", pathName.c_str());
|
||||
std::string::size_type pos = 0;
|
||||
pos = pathName.find("/", pos + 1);
|
||||
while (pos != std::string::npos) {
|
||||
std::string dirName = pathName.substr(0, pos);
|
||||
if (access(dirName.c_str(), F_OK) != 0) {
|
||||
if (mkdir(dirName.c_str(), mode) < 0) {
|
||||
LOGE("mkdr dir %s failed", dirName.c_str());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
pos = pathName.find("/", pos + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KeyBackup::CleanFile(const std::string &path)
|
||||
{
|
||||
LOGI("clean file path %s", path.c_str());
|
||||
int fd = open(path.c_str(), O_WRONLY);
|
||||
if (fd < 0) {
|
||||
LOGE("open %s failed", path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
int len = lseek(fd, 0, SEEK_END);
|
||||
std::string data(len, '\0');
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
if (write(fd, data.c_str(), data.size()) < 0) {
|
||||
LOGE("failed to write file %s", path.c_str());
|
||||
}
|
||||
if (fsync(fd) == -1) {
|
||||
LOGE("failed to sync file %s", path.c_str());
|
||||
}
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
void KeyBackup::CheckAndCopyFiles(const std::string &from, const std::string &to)
|
||||
{
|
||||
LOGI("check and copy files from: %s to: %s", from.c_str(), to.c_str());
|
||||
struct stat st;
|
||||
if (lstat(from.c_str(), &st) < 0) {
|
||||
LOGE("lstat file failed, %s", from.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
CheckAndCopyOneFile(from, to);
|
||||
return;
|
||||
} else if (!S_ISDIR(st.st_mode)) {
|
||||
LOGE("file: %s is not reg file or dir, skip it", from.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
HandleCopyDir(from, to);
|
||||
DIR *dir = opendir(from.c_str());
|
||||
if (dir == nullptr) {
|
||||
LOGE("open dr failed, %s", from.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
struct dirent *de = nullptr;
|
||||
while ((de = readdir(dir)) != nullptr) {
|
||||
if (strcmp(de->d_name, "..") == 0 || strcmp(de->d_name, ".") == 0) {
|
||||
continue;
|
||||
}
|
||||
std::string dfrom = from + "/" + de->d_name;
|
||||
std::string dto = to + "/" + de->d_name;
|
||||
CheckAndCopyFiles(dfrom, dto);
|
||||
}
|
||||
|
||||
if (closedir(dir) < 0) {
|
||||
LOGE("close dir failed, %s", from.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
int32_t KeyBackup::HandleCopyDir(const std::string &from, const std::string &to)
|
||||
{
|
||||
struct FileAttr attr;
|
||||
int32_t ret = mkdir(to.c_str(), DEFAULT_DIR_PERM);
|
||||
if (ret && errno != EEXIST) {
|
||||
LOGE("mkdir dir %s failed", to.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (GetAttr(from, attr) == 0) {
|
||||
SetAttr(to, attr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t KeyBackup::CheckAndCopyOneFile(const std::string &from, const std::string &to)
|
||||
{
|
||||
LOGI("check and copy one file from: %s to: %s", from.c_str(), to.c_str());
|
||||
if (CompareFile(from, to) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CopyRegfileData(from, to) != 0) {
|
||||
LOGE("copy from: %s to file: %s failed", from.c_str(), to.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct FileAttr attr;
|
||||
if (GetAttr(from, attr) == 0) {
|
||||
SetAttr(to, attr);
|
||||
}
|
||||
LOGI("copy from: %s to file %s succ", from.c_str(), to.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool KeyBackup::ReadFileToString(const std::string &filePath, std::string &content)
|
||||
{
|
||||
std::string realPath;
|
||||
if (!GetRealPath(filePath, realPath)) {
|
||||
return false;
|
||||
}
|
||||
int fd = open(realPath.c_str(), O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
LOGE("%s realpath failed", realPath.c_str());
|
||||
return false;
|
||||
}
|
||||
struct stat sb {};
|
||||
if (fstat(fd, &sb) != -1 && sb.st_size > 0) {
|
||||
content.resize(sb.st_size);
|
||||
}
|
||||
|
||||
ssize_t remaining = sb.st_size;
|
||||
bool readStatus = true;
|
||||
char* p = const_cast<char*>(content.data());
|
||||
|
||||
while (remaining > 0) {
|
||||
ssize_t n = read(fd, p, remaining);
|
||||
if (n < 0) {
|
||||
readStatus = false;
|
||||
break;
|
||||
}
|
||||
p += n;
|
||||
remaining -= n;
|
||||
}
|
||||
close(fd);
|
||||
return readStatus;
|
||||
}
|
||||
|
||||
bool KeyBackup::GetRealPath(const std::string &path, std::string &realPath)
|
||||
{
|
||||
char resolvedPath[PATH_MAX] = { 0 };
|
||||
if (path.size() > PATH_MAX || !realpath(path.c_str(), resolvedPath)) {
|
||||
LOGE("%s realpath failed", path.c_str());
|
||||
return false;
|
||||
}
|
||||
realPath = std::string(resolvedPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KeyBackup::WriteStringToFd(int fd, const std::string &content)
|
||||
{
|
||||
const char *p = content.data();
|
||||
size_t remaining = content.size();
|
||||
while (remaining > 0) {
|
||||
ssize_t n = write(fd, p, remaining);
|
||||
if (n == -1) {
|
||||
return false;
|
||||
}
|
||||
p += n;
|
||||
remaining -= n;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KeyBackup::WriteStringToFile(const std::string &payload, const std::string &fileName)
|
||||
{
|
||||
UniqueFd fd(open(fileName.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, DEFAULT_WRITE_FILE_PERM));
|
||||
if (fd < 0) {
|
||||
LOGE("open file failed, %s", fileName.c_str());
|
||||
return false;
|
||||
}
|
||||
if (!WriteStringToFd(fd, payload)) {
|
||||
LOGE("failed to write file, %s", fileName.c_str());
|
||||
unlink(fileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fsync(fd) == -1) {
|
||||
if (errno == EROFS || errno == EINVAL) {
|
||||
LOGE("file system does not support sync, fileName: %s", fileName.c_str());
|
||||
} else {
|
||||
LOGE("sync failed: %s", fileName.c_str());
|
||||
unlink(fileName.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t KeyBackup::CompareFile(const std::string &fileA, const std::string fileB)
|
||||
{
|
||||
std::string dataA;
|
||||
if (!ReadFileToString(fileA, dataA)) {
|
||||
LOGE("failed to read from %s", fileA.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string dataB;
|
||||
if (!ReadFileToString(fileB, dataB)) {
|
||||
LOGE("failed to read from %s", fileB.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dataA.compare(dataB);
|
||||
}
|
||||
|
||||
int32_t KeyBackup::CopyRegfileData(const std::string &from, const std::string &to)
|
||||
{
|
||||
std::string data;
|
||||
if (!ReadFileToString(from, data)) {
|
||||
LOGE("failed to read from: %s", from.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!WriteStringToFile(data, to)) {
|
||||
LOGE("failed to write file: %s", to.c_str());
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t KeyBackup::GetAttr(const std::string &path, struct FileAttr &attr)
|
||||
{
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st) < 0) {
|
||||
return (errno == ENOENT) ? 0 : -1;
|
||||
}
|
||||
|
||||
attr.uid = st.st_uid;
|
||||
attr.gid = st.st_gid;
|
||||
attr.mode = st.st_mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t KeyBackup::SetAttr(const std::string &path, struct FileAttr &attr)
|
||||
{
|
||||
int32_t ret = lchown(path.c_str(), attr.uid, attr.gid);
|
||||
if (ret != 0) {
|
||||
LOGE("lchown failed path: %s, uid: %d, gid: %d", path.c_str(), attr.uid, attr.gid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = chmod(path.c_str(), attr.mode);
|
||||
if (ret != 0) {
|
||||
LOGE("chmod failed, path: %s, mode: %d", path.c_str(), attr.mode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
} // namespace StorageDaemon
|
||||
} // namespace HOHS
|
@ -705,6 +705,15 @@ int KeyManager::UpdateESecret(unsigned int user, struct UserTokenSecret &tokenSe
|
||||
{
|
||||
LOGI("UpdateESecret enter");
|
||||
std::shared_ptr<BaseKey> el5Key = GetUserElKey(user, EL5_KEY);
|
||||
std::string el5Path = USER_EL5_DIR + "/" + std::to_string(user);
|
||||
if (IsUeceSupport() && el5Key == nullptr) {
|
||||
if (!MkDirRecurse(el5Path, S_IRWXU)) {
|
||||
LOGE("MkDirRecurse %{public}u failed!", user);
|
||||
return -EFAULT;
|
||||
}
|
||||
LOGI("MkDirRecurse %{public}u success!", user);
|
||||
el5Key = GetUserElKey(user, EL5_KEY);
|
||||
}
|
||||
if (el5Key == nullptr) {
|
||||
LOGE("Have not found user %{public}u el key", user);
|
||||
return -ENOENT;
|
||||
@ -1086,38 +1095,22 @@ int KeyManager::UnlockUserScreen(uint32_t user, const std::vector<uint8_t> &toke
|
||||
if (iter == saveLockScreenStatus.end()) {
|
||||
saveLockScreenStatus.insert(std::make_pair(user, false));
|
||||
}
|
||||
if (!IsUserCeDecrypt(user)) {
|
||||
LOGE("user ce does not decrypt, skip");
|
||||
return 0;
|
||||
}
|
||||
if (!KeyCtrlHasFscryptSyspara()) {
|
||||
saveLockScreenStatus[user] = true;
|
||||
LOGI("saveLockScreenStatus is %{public}d", saveLockScreenStatus[user]);
|
||||
return 0;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(keyMutex_);
|
||||
auto el4Key = GetUserElKey(user, EL4_KEY);
|
||||
if (el4Key == nullptr) {
|
||||
saveLockScreenStatus[user] = true;
|
||||
LOGE("The user %{public}u not been actived and saveLockScreenStatus is %{public}d", user,
|
||||
saveLockScreenStatus[user]);
|
||||
return 0;
|
||||
int ret = 0;
|
||||
if (!UnlockEceSece(user, token, secret, ret)) {
|
||||
return ret;
|
||||
}
|
||||
if (!el4Key->RestoreKey({ token, secret }) && !el4Key->RestoreKey(NULL_KEY_AUTH)) {
|
||||
LOGE("Restore user %{public}u el4 key failed", user);
|
||||
return -EFAULT;
|
||||
}
|
||||
if (!el4Key->UnlockUserScreen(user, FSCRYPT_SDP_ECE_CLASS)) {
|
||||
LOGE("UnlockUserScreen user %{public}u el4 key failed", user);
|
||||
return -EFAULT;
|
||||
}
|
||||
LOGI("DecryptClassE user %{public}u saveESecretStatus %{public}d", user, saveESecretStatus[user]);
|
||||
UserAuth auth = { .token = token, .secret = secret };
|
||||
saveESecretStatus[user] = !auth.token.IsEmpty();
|
||||
auto el5Key = GetUserElKey(user, EL5_KEY);
|
||||
if (el5Key != nullptr && !el5Key->DecryptClassE(auth, saveESecretStatus[user], user, USER_UNLOCK)) {
|
||||
LOGE("Unlock user %{public}u uece failed", user);
|
||||
return -EFAULT;
|
||||
}
|
||||
if (UnlockUserAppKeys(user, false) != E_OK) {
|
||||
LOGE("failed to delete appkey2");
|
||||
return -EFAULT;
|
||||
if (!UnlockUece(user, token, secret, ret)) {
|
||||
return ret;
|
||||
}
|
||||
saveLockScreenStatus[user] = true;
|
||||
LOGI("UnlockUserScreen user %{public}u el3 and el4 success and saveLockScreenStatus is %{public}d", user,
|
||||
@ -1125,6 +1118,54 @@ int KeyManager::UnlockUserScreen(uint32_t user, const std::vector<uint8_t> &toke
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool KeyManager::UnlockEceSece(uint32_t user,
|
||||
const std::vector<uint8_t> &token,
|
||||
const std::vector<uint8_t> &secret,
|
||||
int &ret)
|
||||
{
|
||||
auto el4Key = GetUserElKey(user, EL4_KEY);
|
||||
if (el4Key == nullptr) {
|
||||
saveLockScreenStatus[user] = true;
|
||||
LOGE("The user %{public}u not been actived and saveLockScreenStatus is %{public}d", user,
|
||||
saveLockScreenStatus[user]);
|
||||
ret = 0;
|
||||
return false;
|
||||
}
|
||||
if (!el4Key->RestoreKey({token, secret}) && !el4Key->RestoreKey(NULL_KEY_AUTH)) {
|
||||
LOGE("Restore user %{public}u el4 key failed", user);
|
||||
ret = -EFAULT;
|
||||
return false;
|
||||
}
|
||||
if (!el4Key->UnlockUserScreen(user, FSCRYPT_SDP_ECE_CLASS)) {
|
||||
LOGE("UnlockUserScreen user %{public}u el4 key failed", user);
|
||||
ret = -EFAULT;
|
||||
return false;
|
||||
}
|
||||
LOGI("DecryptClassE user %{public}u saveESecretStatus %{public}d", user, saveESecretStatus[user]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KeyManager::UnlockUece(uint32_t user,
|
||||
const std::vector<uint8_t> &token,
|
||||
const std::vector<uint8_t> &secret,
|
||||
int &ret)
|
||||
{
|
||||
UserAuth auth = {.token = token, .secret = secret};
|
||||
saveESecretStatus[user] = !auth.token.IsEmpty();
|
||||
auto el5Key = GetUserElKey(user, EL5_KEY);
|
||||
if (el5Key != nullptr && !el5Key->DecryptClassE(auth, saveESecretStatus[user], user, USER_UNLOCK)) {
|
||||
LOGE("Unlock user %{public}u uece failed", user);
|
||||
ret = -EFAULT;
|
||||
return false;
|
||||
}
|
||||
if (UnlockUserAppKeys(user, false) != E_OK) {
|
||||
LOGE("failed to delete appkey2");
|
||||
ret = -EFAULT;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int KeyManager::GetLockScreenStatus(uint32_t user, bool &lockScreenStatus)
|
||||
{
|
||||
LOGI("start");
|
||||
@ -1138,6 +1179,10 @@ int KeyManager::GetLockScreenStatus(uint32_t user, bool &lockScreenStatus)
|
||||
int KeyManager::GenerateAppkey(uint32_t userId, uint32_t hashId, std::string &keyId)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(keyMutex_);
|
||||
if (!IsUserCeDecrypt(userId)) {
|
||||
LOGE("user ce does not decrypt, skip");
|
||||
return -ENOENT;
|
||||
}
|
||||
auto el2Key = GetUserElKey(userId, EL2_KEY);
|
||||
if (el2Key == nullptr) {
|
||||
LOGE("userEl2Key_ has not existed");
|
||||
@ -1153,6 +1198,10 @@ int KeyManager::GenerateAppkey(uint32_t userId, uint32_t hashId, std::string &ke
|
||||
int KeyManager::DeleteAppkey(uint32_t userId, const std::string keyId)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(keyMutex_);
|
||||
if (!IsUserCeDecrypt(userId)) {
|
||||
LOGE("user ce does not decrypt, skip");
|
||||
return -ENOENT;
|
||||
}
|
||||
auto el2Key = GetUserElKey(userId, EL2_KEY);
|
||||
if (el2Key == nullptr) {
|
||||
LOGE("userEl2Key_ has not existed");
|
||||
@ -1290,6 +1339,10 @@ int KeyManager::LockUserScreen(uint32_t user)
|
||||
if (iter == saveLockScreenStatus.end()) {
|
||||
saveLockScreenStatus.insert(std::make_pair(user, false));
|
||||
}
|
||||
if (!IsUserCeDecrypt(user)) {
|
||||
LOGE("user ce does not decrypt, skip");
|
||||
return 0;
|
||||
}
|
||||
if (!KeyCtrlHasFscryptSyspara()) {
|
||||
saveLockScreenStatus[user] = false;
|
||||
LOGI("KeyCtrlHasFscryptSyspara is false, saveLockScreenStatus is %{public}d",
|
||||
@ -1493,6 +1546,18 @@ int KeyManager::GetFileEncryptStatus(uint32_t userId, bool &isEncrypted)
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
bool KeyManager::IsUserCeDecrypt(uint32_t userId)
|
||||
{
|
||||
bool isCeEncrypt = false;
|
||||
int ret = GetFileEncryptStatus(userId, isCeEncrypt);
|
||||
if (ret != E_OK || isCeEncrypt) {
|
||||
LOGE("User %{public}d de has not decrypt.", userId);
|
||||
return false;
|
||||
}
|
||||
LOGI("User %{public}d de decrypted.", userId);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USER_CRYPTO_MIGRATE_KEY
|
||||
int KeyManager::RestoreUserKey(uint32_t userId, KeyType type)
|
||||
{
|
||||
|
@ -1,50 +0,0 @@
|
||||
# Copyright (C) 2024 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import("//build/test.gni")
|
||||
import("//foundation/filemanagement/storage_service/storage_service_aafwk.gni")
|
||||
|
||||
ohos_unittest("AncoKeyManagerTest") {
|
||||
module_out_path = "storage_service/storage_daemon"
|
||||
|
||||
defines = [
|
||||
"STORAGE_LOG_TAG = \"StorageDaemon\"",
|
||||
"LOG_DOMAIN = 0xD004301",
|
||||
"private=public",
|
||||
]
|
||||
|
||||
include_dirs = [
|
||||
"${storage_daemon_path}/include",
|
||||
"${storage_daemon_path}/include/crypto",
|
||||
"${storage_service_common_path}/include",
|
||||
]
|
||||
|
||||
sources = [ "anco_key_manager_test.cpp" ]
|
||||
|
||||
deps = [ "//third_party/googletest:gtest_main" ]
|
||||
|
||||
deps += [
|
||||
"${storage_daemon_path}/crypto:libsdcrypto",
|
||||
"${storage_daemon_path}/libfscrypt:libfscryptutils",
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
"c_utils:utils",
|
||||
"hilog:libhilog",
|
||||
"huks:libhukssdk",
|
||||
]
|
||||
}
|
||||
|
||||
group("anco_crypto_test") {
|
||||
testonly = true
|
||||
deps = [ ":AncoKeyManagerTest" ]
|
||||
}
|
@ -1,215 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <gtest/gtest.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "anco_key_manager.h"
|
||||
#include "storage_service_errno.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace StorageDaemon {
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::StorageDaemon;
|
||||
|
||||
class AncoKeyManagerTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase(void);
|
||||
static void TearDownTestCase(void);
|
||||
void SetUp();
|
||||
void TearDown();
|
||||
};
|
||||
|
||||
|
||||
void AncoKeyManagerTest::SetUpTestCase(void)
|
||||
{
|
||||
// input testsuit setup step,setup invoked before all testcases
|
||||
}
|
||||
|
||||
void AncoKeyManagerTest::TearDownTestCase(void)
|
||||
{
|
||||
// input testsuit teardown step,teardown invoked after all testcases
|
||||
}
|
||||
|
||||
void AncoKeyManagerTest::SetUp(void)
|
||||
{
|
||||
// input testcase setup step,setup invoked before each testcases
|
||||
}
|
||||
|
||||
void AncoKeyManagerTest::TearDown(void)
|
||||
{
|
||||
// input testcase teardown step,teardown invoked after each testcases
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: SetAnDirectoryElpolicy_0100
|
||||
* @tc.desc: Verify the SetAnDirectoryElpolicy_0100 function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: SR20231213615940
|
||||
*/
|
||||
HWTEST_F(AncoKeyManagerTest, Set_Anco_Directory_El_Policy_utils_001, TestSize.Level1)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_SetAnDirectoryElpolicy_0100 start";
|
||||
const std::string path = "";
|
||||
const std::string policyType = "";
|
||||
const uint32_t user = 0;
|
||||
EXPECT_EQ(AncoKeyManager::GetInstance()->SetAncoDirectoryElPolicy(path, policyType, user),
|
||||
OHOS::E_JSON_PARSE_ERROR);
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_SetAnDirectoryElpolicy_0100 end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: SetAnDirectoryElpolicy_0200
|
||||
* @tc.desc: Verify the SetAnDirectoryElpolicy_0200 function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: SR20231213615940
|
||||
*/
|
||||
HWTEST_F(AncoKeyManagerTest, Set_Anco_Directory_El_Policy_utils_002, TestSize.Level1)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_SetAnDirectoryElpolicy_0200 start";
|
||||
const std::string path = "/data/virt_serivce/rgm_manager/rgm_homs/config/storage/test.json";
|
||||
const std::string policyType = "encryption=Require_Sys_EL1";
|
||||
const uint32_t user = 0;
|
||||
auto result = AncoKeyManager::GetInstance()->SetAncoDirectoryElPolicy(path, policyType, user);
|
||||
EXPECT_NE(result, OHOS::E_OK);
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_SetAnDirectoryElpolicy_0200 end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: SetAnDirectoryElpolicy_0200
|
||||
* @tc.desc: Verify the SetAnDirectoryElpolicy_0200 function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: SR20231213615940
|
||||
*/
|
||||
HWTEST_F(AncoKeyManagerTest, Set_Anco_Directory_El_Policy_utils_003, TestSize.Level1)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_SetAnDirectoryElpolicy_0300 start";
|
||||
const std::string path = "/data/virt_serivce/rgm_manager/rgm_homs/config/storage/direnc.json";
|
||||
const std::string policyType = "encryption=Require_Sys_EL1";
|
||||
uint32_t user = 0;
|
||||
auto result = AncoKeyManager::GetInstance()->SetAncoDirectoryElPolicy(path, policyType, user);
|
||||
EXPECT_NE(result, OHOS::E_OK);
|
||||
user = 100;
|
||||
result = AncoKeyManager::GetInstance()->SetAncoDirectoryElPolicy(path, policyType, user);
|
||||
EXPECT_NE(result, OHOS::E_OK);
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_SetAnDirectoryElpolicy_0300 end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: ReadFileAndCreateDir_0100
|
||||
* @tc.desc: Verify the ReadFileAndCreateDir_0100 function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: SR20231213615940
|
||||
*/
|
||||
HWTEST_F(AncoKeyManagerTest, Read_File_And_Create_Dir_utils_001, TestSize.Level1)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_ReadFileAndCreateDir_0100 start";
|
||||
const std::string path = "";
|
||||
const std::string policyType = "";
|
||||
std::vector<FileList> fileList = {};
|
||||
auto result = AncoKeyManager::GetInstance()->ReadFileAndCreateDir(path, policyType, fileList);
|
||||
EXPECT_EQ(result, OHOS::E_JSON_PARSE_ERROR);
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_ReadFileAndCreateDir_0100 end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: ReadFileAndCreateDir_0200
|
||||
* @tc.desc: Verify the ReadFileAndCreateDir_0200 function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: SR20231213615940
|
||||
*/
|
||||
HWTEST_F(AncoKeyManagerTest, Read_File_And_Create_Dir_utils_002, TestSize.Level1)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_ReadFileAndCreateDir_0200 start";
|
||||
const std::string path = "/data/virt_serivce/rgm_manager/rgm_homs/config/storage/test.json";
|
||||
const std::string policyType = "encryption=Require_Sys_EL1";
|
||||
std::vector<FileList> fileList = {};
|
||||
auto result = AncoKeyManager::GetInstance()->ReadFileAndCreateDir(path, policyType, fileList);
|
||||
EXPECT_NE(result, OHOS::E_OK);
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_ReadFileAndCreateDir_0200 end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: CreatePolicyDir_0100
|
||||
* @tc.desc: Verify the CreatePolicyDir_0100 function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: SR20231213615940
|
||||
*/
|
||||
HWTEST_F(AncoKeyManagerTest, Create_Policy_Dir_utils_001, TestSize.Level1)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_CreatePolicyDir_0100 start";
|
||||
const AncoDirInfo ancoDirInfo;
|
||||
const std::string policyType = "";
|
||||
std::vector<FileList> fileList = {};
|
||||
auto result = AncoKeyManager::GetInstance()->CreatePolicyDir(ancoDirInfo, policyType, fileList);
|
||||
EXPECT_EQ(result, OHOS::E_JSON_PARSE_ERROR);
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_CreatePolicyDir_0100 end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: CreatePolicyDir_0200
|
||||
* @tc.desc: Verify the CreatePolicyDir_0200 function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: SR20231213615940
|
||||
*/
|
||||
HWTEST_F(AncoKeyManagerTest, Create_Policy_Dir_utils_002, TestSize.Level1)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_CreatePolicyDir_0200 start";
|
||||
const AncoDirInfo ancoDirInfo { .mode = "test" };
|
||||
const std::string policyType = "";
|
||||
std::vector<FileList> fileList = {};
|
||||
auto result = AncoKeyManager::GetInstance()->CreatePolicyDir(ancoDirInfo, policyType, fileList);
|
||||
EXPECT_EQ(result, OHOS::E_JSON_PARSE_ERROR);
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_CreatePolicyDir_0200 end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: CreatePolicyDir_0300
|
||||
* @tc.desc: Verify the CreatePolicyDir_0300 function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: SR20231213615940
|
||||
*/
|
||||
HWTEST_F(AncoKeyManagerTest, Create_Policy_Dir_utils_003, TestSize.Level1)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_CreatePolicyDir_0300 start";
|
||||
const AncoDirInfo ancoDirInfo { .mode = "0711", .path = "aaabbbccc" };
|
||||
const std::string policyType = "";
|
||||
std::vector<FileList> fileList = {};
|
||||
auto result = AncoKeyManager::GetInstance()->CreatePolicyDir(ancoDirInfo, policyType, fileList);
|
||||
EXPECT_EQ(result, OHOS::E_JSON_PARSE_ERROR);
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_CreatePolicyDir_0300 end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: CreatePolicyDir_0400
|
||||
* @tc.desc: Verify the CreatePolicyDir_0400 function.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: SR20231213615940
|
||||
*/
|
||||
HWTEST_F(AncoKeyManagerTest, Create_Policy_Dir_utils_004, TestSize.Level1)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_CreatePolicyDir_0400 start";
|
||||
const AncoDirInfo ancoDirInfo { .mode = "0711", .path = "/data/virt_serivce" };
|
||||
const std::string policyType = "";
|
||||
std::vector<FileList> fileList = {};
|
||||
auto result = AncoKeyManager::GetInstance()->CreatePolicyDir(ancoDirInfo, policyType, fileList);
|
||||
EXPECT_EQ(result, OHOS::E_JSON_PARSE_ERROR);
|
||||
GTEST_LOG_(INFO) << "AnKeyManagerTest_CreatePolicyDir_0400 end";
|
||||
}
|
||||
} // namespace StorageDaemon
|
||||
} // namespace OHOS
|
@ -38,7 +38,6 @@ ohos_moduletest("FscryptKeyV1Test") {
|
||||
]
|
||||
|
||||
sources = [
|
||||
"${storage_daemon_path}/crypto/src/anco_key_manager.cpp",
|
||||
"${storage_daemon_path}/crypto/src/base_key.cpp",
|
||||
"${storage_daemon_path}/crypto/src/crypto_delay_handler.cpp",
|
||||
"${storage_daemon_path}/crypto/src/fbex.cpp",
|
||||
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef STORAGE_DAEMON_CRYPTO_ANCO_KEY_MANAGER_H
|
||||
#define STORAGE_DAEMON_CRYPTO_ANCO_KEY_MANAGER_H
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "storage_service_constant.h"
|
||||
#include "utils/file_utils.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace StorageDaemon {
|
||||
class AncoKeyManager {
|
||||
public:
|
||||
static AncoKeyManager *GetInstance(void)
|
||||
{
|
||||
static AncoKeyManager instance;
|
||||
return &instance;
|
||||
}
|
||||
int32_t SetAncoDirectoryElPolicy(const std::string &path, const std::string &policyType, unsigned int user);
|
||||
|
||||
private:
|
||||
int32_t ReadFileAndCreateDir(const std::string &path, const std::string &type, std::vector<FileList> &vec);
|
||||
int32_t CreatePolicyDir(const AncoDirInfo &ancoDirInfo, const std::string &type, std::vector<FileList> &vec);
|
||||
int32_t CheckMemberValid(const AncoDirInfo &ancoDirInfo);
|
||||
void SetUserPermissionMap();
|
||||
static std::map<std::string, std::string> ownerMap_;
|
||||
std::mutex Mutex_;
|
||||
};
|
||||
} // namespace StorageDaemon
|
||||
} // namespace OHOS
|
||||
|
||||
#endif // STORAGE_DAEMON_CRYPTO_ANCO_KEY_MANAGER_H
|
@ -58,6 +58,7 @@ public:
|
||||
virtual bool EncryptClassE(const UserAuth &auth, bool &isSupport, uint32_t user, uint32_t status) = 0;
|
||||
virtual bool ChangePinCodeClassE(bool &isFbeSupport, uint32_t userId) = 0;
|
||||
virtual bool LockUece(bool &isFbeSupport) = 0;
|
||||
bool DoRestoreKeyEx(const UserAuth &auth, const std::string &keypath);
|
||||
bool EncryptKeyBlob(const UserAuth &auth, const std::string &keyPath, KeyBlob &planKey, KeyBlob &encryptedKey);
|
||||
bool DecryptKeyBlob(const UserAuth &auth, const std::string &keyPath, KeyBlob &planKey, KeyBlob &decryptedKey);
|
||||
bool RenameKeyPath(const std::string &keyPath);
|
||||
@ -95,7 +96,6 @@ private:
|
||||
bool DoRestoreKeyDe(const UserAuth &auth, const std::string &path);
|
||||
bool DoRestoreKeyOld(const UserAuth &auth, const std::string &keypath);
|
||||
bool DoUpdateRestore(const UserAuth &auth, const std::string &keyPath);
|
||||
bool DoRestoreKeyEx(const UserAuth &auth, const std::string &keypath);
|
||||
static bool GenerateAndSaveKeyBlob(KeyBlob &blob, const std::string &path, const uint32_t size);
|
||||
static bool GenerateKeyBlob(KeyBlob &blob, const uint32_t size);
|
||||
static bool LoadKeyBlob(KeyBlob &blob, const std::string &path, const uint32_t size);
|
||||
|
96
services/storage_daemon/include/crypto/key_backup.h
Normal file
96
services/storage_daemon/include/crypto/key_backup.h
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef STORAGE_DAEMON_KEY_BACKUP_H
|
||||
#define STORAGE_DAEMON_KEY_BACKUP_H
|
||||
|
||||
#include <string>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "base_key.h"
|
||||
#include "key_blob.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace StorageDaemon {
|
||||
const std::string BACKUP_NAME = "_bak";
|
||||
|
||||
struct FileAttr {
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
mode_t mode;
|
||||
};
|
||||
|
||||
class KeyBackup {
|
||||
public:
|
||||
static KeyBackup &GetInstance()
|
||||
{
|
||||
static KeyBackup instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void CreateBackup(const std::string &from, const std::string &to, bool removeOld = true);
|
||||
int32_t RemoveNode(const std::string &pathName);
|
||||
int32_t TryRestoreKey(std::shared_ptr<BaseKey> &baseKey, const UserAuth &auth);
|
||||
int32_t GetBackupDir(std::string &origDir, std::string &backupDir);
|
||||
void ListAndCheckDir(std::string &origDir);
|
||||
|
||||
private:
|
||||
KeyBackup();
|
||||
~KeyBackup();
|
||||
KeyBackup(const KeyBackup &) = delete;
|
||||
KeyBackup &operator=(const KeyBackup &) = delete;
|
||||
|
||||
void FsyncDirectory(const std::string &dirName);
|
||||
int32_t MkdirParent(const std::string &pathName, mode_t mode);
|
||||
void CleanFile(const std::string &path);
|
||||
void CheckAndCopyFiles(const std::string &from, const std::string &to);
|
||||
int32_t CheckAndCopyOneFile(const std::string &from, const std::string &to);
|
||||
bool ReadFileToString(const std::string &filePath, std::string &content);
|
||||
bool GetRealPath(const std::string &path, std::string &realPath);
|
||||
bool WriteStringToFd(int fd, const std::string &content);
|
||||
bool WriteStringToFile(const std::string &payload, const std::string &fileName);
|
||||
int32_t CompareFile(const std::string &fileA, const std::string fileB);
|
||||
int32_t CopyRegfileData(const std::string &from, const std::string &to);
|
||||
int32_t GetAttr(const std::string &path, struct FileAttr &attr);
|
||||
int32_t SetAttr(const std::string &path, struct FileAttr &attr);
|
||||
int32_t HandleCopyDir(const std::string &from, const std::string &to);
|
||||
void CheckAndFixFiles(const std::string &from, const std::string &to);
|
||||
int32_t GetFileList(const std::string &origDir, const std::string &backDir,
|
||||
std::vector<struct FileNode> &fileListm, uint32_t diffNum);
|
||||
void AddOrigFileToList(const std::string &fileName, const std::string &origDir,
|
||||
std::vector<struct FileNode> &fileList);
|
||||
void AddBackupFileToList(const std::string &fileName, const std::string &backDir,
|
||||
std::vector<struct FileNode> &fileList);
|
||||
uint32_t GetDiffFilesNum(const std::vector<struct FileNode> &fileList);
|
||||
int32_t CopySameFilesToTempDir(const std::string &backupDir, std::string &tempDir,
|
||||
std::vector<struct FileNode> &fileList);
|
||||
int32_t CreateTempDirForMixFiles(const std::string &backupDir, std::string &tempDir);
|
||||
uint32_t GetLoopMaxNum(uint32_t diffNum);
|
||||
int32_t CopyMixFilesToTempDir(uint32_t diffNum, uint32_t num, const std::string &tempDir,
|
||||
const std::vector<struct FileNode> &fileList);
|
||||
bool IsRegFile(const std::string &filePath);
|
||||
int32_t DoResotreKeyMix(std::shared_ptr<BaseKey> &baseKey, const UserAuth &auth, const std::string &keyDir,
|
||||
const std::string &backupDir);
|
||||
|
||||
private:
|
||||
constexpr static mode_t DEFAULT_DIR_PERM = 0700;
|
||||
constexpr static mode_t DEFAULT_WRITE_FILE_PERM = 0666;
|
||||
constexpr static uint32_t MAX_FILE_NUM = 5;
|
||||
};
|
||||
} // namespace StorageDaemon
|
||||
} // namespace OHOS
|
||||
|
||||
#endif // STORAGE_DAEMON_KEY_BACKUP_H
|
@ -128,6 +128,9 @@ private:
|
||||
int CheckAndDeleteEmptyEl5Directory(std::string keyDir, unsigned int user);
|
||||
bool GetUserDelayHandler(uint32_t userId, std::shared_ptr<DelayHandler> &delayHandler);
|
||||
bool IsUeceSupport();
|
||||
bool IsUserCeDecrypt(uint32_t userId);
|
||||
bool UnlockEceSece(uint32_t user, const std::vector<uint8_t> &token, const std::vector<uint8_t> &secret, int &ret);
|
||||
bool UnlockUece(uint32_t user, const std::vector<uint8_t> &token, const std::vector<uint8_t> &secret, int &ret);
|
||||
|
||||
std::map<unsigned int, std::shared_ptr<BaseKey>> userEl1Key_;
|
||||
std::map<unsigned int, std::shared_ptr<BaseKey>> userEl2Key_;
|
||||
|
@ -126,8 +126,6 @@ private:
|
||||
const std::vector<uint8_t> &secret);
|
||||
int32_t RestoreconElX(uint32_t userId);
|
||||
void ActiveAppCloneUserKey();
|
||||
void AncoInitCryptKey();
|
||||
void AncoActiveCryptKey(uint32_t userId);
|
||||
void SetDeleteFlag4KeyFiles();
|
||||
};
|
||||
} // StorageDaemon
|
||||
|
@ -55,6 +55,7 @@ constexpr uid_t OID_DLP_CREDENTIAL = 3553;
|
||||
constexpr uid_t OID_RSS = 1096;
|
||||
constexpr uid_t OID_HIVIEW = 1201;
|
||||
constexpr uid_t OID_PARENT_CONTROL = 7007;
|
||||
constexpr uid_t OID_ACCOUNT = 3058;
|
||||
constexpr uid_t USER_ID_BASE = 200000;
|
||||
|
||||
class MountManager final {
|
||||
|
@ -30,18 +30,10 @@ struct FileList {
|
||||
std::string path;
|
||||
};
|
||||
|
||||
struct AncoDirInfo {
|
||||
std::string mkdir;
|
||||
std::string path;
|
||||
std::string mode;
|
||||
std::string uid;
|
||||
std::string gid;
|
||||
std::string policy;
|
||||
};
|
||||
|
||||
int32_t ChMod(const std::string &path, mode_t mode);
|
||||
int32_t MkDir(const std::string &path, mode_t mode);
|
||||
bool IsDir(const std::string &path);
|
||||
bool IsFile(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 MkDirRecurse(const std::string& path, mode_t mode);
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "utils/storage_radar.h"
|
||||
|
||||
#ifdef USER_CRYPTO_MANAGER
|
||||
#include "crypto/anco_key_manager.h"
|
||||
#include "crypto/app_clone_key_manager.h"
|
||||
#include "crypto/iam_client.h"
|
||||
#include "crypto/key_manager.h"
|
||||
@ -68,11 +67,6 @@ static const std::string VFS_CACHE_PRESSURE = "/proc/sys/vm/vfs_cache_pressure";
|
||||
const std::string DATA_SERVICE_EL2 = "/data/service/el2/";
|
||||
const std::string DATA_SERVICE_EL3 = "/data/service/el3/";
|
||||
const std::string DATA_SERVICE_EL4 = "/data/service/el4/";
|
||||
const std::string CONFIG_FILE_PATH = "/data/virt_service/rgm_manager/rgm_hmos/config/storage/direnc.json";
|
||||
const std::string USER_PATH = "/data/app/el1/100";
|
||||
const std::string ANCO_TYPE_SYS_EL1 = "encryption=Require_Sys_EL1";
|
||||
const std::string ANCO_TYPE_USER_EL1 = "encryption=Require_User_EL1";
|
||||
const std::string ANCO_TYPE_USER_EL2 = "encryption=Require_User_EL2";
|
||||
const std::string DATA_SERVICE_EL1_PUBLIC_STORAGE_DAEMON_SD = "/data/service/el1/public/storage_daemon/sd";
|
||||
const std::string DATA_SERVICE_EL0_STORAGE_DAEMON_SD = "/data/service/el0/storage_daemon/sd";
|
||||
|
||||
@ -408,9 +402,7 @@ int32_t StorageDaemon::InitGlobalUserKeys(void)
|
||||
StorageService::StorageRadar::GetInstance().RecordFuctionResult(
|
||||
"PrepareUserDirs", BizScene::USER_KEY_ENCRYPTION, BizStage::BIZ_STAGE_GENERATE_USER_KEYS, "EL1", result);
|
||||
}
|
||||
#ifdef USER_CRYPTO_MANAGER
|
||||
AncoInitCryptKey();
|
||||
#endif
|
||||
|
||||
std::thread thread([this]() { SetDeleteFlag4KeyFiles(); });
|
||||
thread.detach();
|
||||
return result;
|
||||
@ -692,16 +684,12 @@ int32_t StorageDaemon::ActiveUserKey(uint32_t userId,
|
||||
UserManager::GetInstance()->CreateBundleDataDir(userId);
|
||||
}
|
||||
std::thread([this]() { ActiveAppCloneUserKey(); }).detach();
|
||||
AncoActiveCryptKey(userId);
|
||||
return ret;
|
||||
#else
|
||||
std::thread([this, userId]() { RestoreconElX(userId); }).detach();
|
||||
if (updateFlag) {
|
||||
UserManager::GetInstance()->CreateBundleDataDir(userId);
|
||||
}
|
||||
#ifdef USER_CRYPTO_MANAGER
|
||||
AncoActiveCryptKey(userId);
|
||||
#endif
|
||||
return E_OK;
|
||||
#endif
|
||||
}
|
||||
@ -1005,40 +993,5 @@ void StorageDaemon::ActiveAppCloneUserKey()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void StorageDaemon::AncoInitCryptKey()
|
||||
{
|
||||
#ifdef USER_CRYPTO_MANAGER
|
||||
std::error_code errorCode;
|
||||
if (std::filesystem::exists(CONFIG_FILE_PATH, errorCode)) {
|
||||
auto ret = AncoKeyManager::GetInstance()->SetAncoDirectoryElPolicy(CONFIG_FILE_PATH, ANCO_TYPE_SYS_EL1,
|
||||
GLOBAL_USER_ID);
|
||||
if (ret != E_OK) {
|
||||
LOGE("SetAncoDirectoryElPolicy failed, ret = %{public}d", ret);
|
||||
}
|
||||
if (std::filesystem::exists(USER_PATH, errorCode)) {
|
||||
ret = AncoKeyManager::GetInstance()->SetAncoDirectoryElPolicy(CONFIG_FILE_PATH, ANCO_TYPE_USER_EL1,
|
||||
ANCO_USER_ID);
|
||||
if (ret != E_OK) {
|
||||
LOGE("SetAncoDirectoryElPolicy failed, ret = %{public}d", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void StorageDaemon::AncoActiveCryptKey(uint32_t userId)
|
||||
{
|
||||
#ifdef USER_CRYPTO_MANAGER
|
||||
std::error_code errorCode;
|
||||
if (std::filesystem::exists(CONFIG_FILE_PATH, errorCode)) {
|
||||
auto ret = AncoKeyManager::GetInstance()->SetAncoDirectoryElPolicy(CONFIG_FILE_PATH, ANCO_TYPE_USER_EL2,
|
||||
userId);
|
||||
if (ret != E_OK) {
|
||||
LOGE("SetAncoDirectoryElPolicy failed, ret = %{public}d", ret);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace StorageDaemon
|
||||
} // namespace OHOS
|
||||
|
@ -51,7 +51,6 @@ ohos_unittest("storage_daemon_test") {
|
||||
]
|
||||
|
||||
sources = [
|
||||
"$ROOT_DIR/crypto/src/anco_key_manager.cpp",
|
||||
"$ROOT_DIR/crypto/src/app_clone_key_manager.cpp",
|
||||
"$ROOT_DIR/crypto/test/key_manager_mock.cpp",
|
||||
"$ROOT_DIR/disk/src/disk_config.cpp",
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2021-2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
@ -106,7 +106,7 @@ int32_t NetlinkListener::ReadMsg(int32_t fd_count, struct pollfd ufds[2])
|
||||
return E_ERR;
|
||||
}
|
||||
if (msg == 0) {
|
||||
LOGI("Stop listener");
|
||||
LOGE("Stop listener");
|
||||
return E_ERR;
|
||||
}
|
||||
} else if (ufds[i].fd == socketFd_) {
|
||||
@ -126,34 +126,33 @@ int32_t NetlinkListener::ReadMsg(int32_t fd_count, struct pollfd ufds[2])
|
||||
void NetlinkListener::RunListener()
|
||||
{
|
||||
struct pollfd ufds[2];
|
||||
int32_t idle_time = POLL_IDLE_TIME;
|
||||
int32_t idleTime = POLL_IDLE_TIME;
|
||||
|
||||
while (1) {
|
||||
int32_t fd_count = 0;
|
||||
|
||||
ufds[fd_count].fd = socketPipe_[0];
|
||||
ufds[fd_count].events = POLLIN;
|
||||
ufds[fd_count].revents = 0;
|
||||
fd_count++;
|
||||
int32_t fdCount = 0;
|
||||
ufds[fdCount].fd = socketPipe_[0];
|
||||
ufds[fdCount].events = POLLIN;
|
||||
ufds[fdCount].revents = 0;
|
||||
fdCount++;
|
||||
|
||||
if (socketFd_ > -1) {
|
||||
ufds[fd_count].fd = socketFd_;
|
||||
ufds[fd_count].events = POLLIN;
|
||||
ufds[fd_count].revents = 0;
|
||||
fd_count++;
|
||||
ufds[fdCount].fd = socketFd_;
|
||||
ufds[fdCount].events = POLLIN;
|
||||
ufds[fdCount].revents = 0;
|
||||
fdCount++;
|
||||
}
|
||||
|
||||
int32_t n = poll(ufds, fd_count, idle_time);
|
||||
if (n < 0) {
|
||||
int32_t fdEventCount = poll(ufds, fdCount, idleTime);
|
||||
if (fdEventCount < 0) {
|
||||
if (errno == EAGAIN || errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} else if (!n) {
|
||||
} else if (fdEventCount == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ReadMsg(fd_count, ufds) != 0) {
|
||||
if (ReadMsg(fdCount, ufds) != 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -162,16 +161,18 @@ void NetlinkListener::RunListener()
|
||||
void NetlinkListener::EventProcess(void *object)
|
||||
{
|
||||
if (object == nullptr) {
|
||||
LOGE("object is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
NetlinkListener* me = reinterpret_cast<NetlinkListener *>(object);
|
||||
me->RunListener();
|
||||
NetlinkListener* client = reinterpret_cast<NetlinkListener *>(object);
|
||||
client->RunListener();
|
||||
}
|
||||
|
||||
int32_t NetlinkListener::StartListener()
|
||||
{
|
||||
if (socketFd_ < 0) {
|
||||
LOGE("socketFD < 0");
|
||||
return E_ERR;
|
||||
}
|
||||
|
||||
@ -183,7 +184,8 @@ int32_t NetlinkListener::StartListener()
|
||||
if (socketThread_ == nullptr) {
|
||||
(void)close(socketPipe_[0]);
|
||||
(void)close(socketPipe_[1]);
|
||||
socketPipe_[0] = socketPipe_[1] = -1;
|
||||
socketPipe_[0] = -1;
|
||||
socketPipe_[1] = -1;
|
||||
return E_ERR;
|
||||
}
|
||||
|
||||
@ -201,7 +203,8 @@ int32_t NetlinkListener::StopListener()
|
||||
|
||||
(void)close(socketPipe_[0]);
|
||||
(void)close(socketPipe_[1]);
|
||||
socketPipe_[0] = socketPipe_[1] = -1;
|
||||
socketPipe_[0] = -1;
|
||||
socketPipe_[1] = -1;
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
|
@ -144,6 +144,7 @@ MountManager::MountManager()
|
||||
{"/data/service/el2/%d/huks_service", MODE_0711, OID_HUKS, OID_HUKS},
|
||||
{"/data/service/el2/%d/parentcontrol", MODE_0711, OID_PARENT_CONTROL, OID_PARENT_CONTROL},
|
||||
{"/data/service/el4/%d/huks_service", MODE_0711, OID_HUKS, OID_HUKS},
|
||||
{"/data/service/el2/%d/account", MODE_0711, OID_ACCOUNT, OID_ACCOUNT},
|
||||
{"/data/service/el2/%d/dlp_credential_service", MODE_0711, OID_DLP_CREDENTIAL, OID_DLP_CREDENTIAL},
|
||||
{"/data/service/el2/%d/xpower", MODE_0711, OID_HIVIEW, OID_HIVIEW}},
|
||||
fileManagerDir_{{"/data/service/el2/%d/hmdfs/account/files/Docs", MODE_02771, OID_FILE_MANAGER, OID_FILE_MANAGER},
|
||||
|
@ -85,6 +85,16 @@ bool IsDir(const std::string &path)
|
||||
return S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
bool IsFile(const std::string &path)
|
||||
{
|
||||
// check whether the path exists
|
||||
struct stat buf = {};
|
||||
if (stat(path.c_str(), &buf) != 0) {
|
||||
return false;
|
||||
}
|
||||
return S_ISREG(buf.st_mode);
|
||||
}
|
||||
|
||||
bool MkDirRecurse(const std::string& path, mode_t mode)
|
||||
{
|
||||
std::string::size_type index = 0;
|
||||
@ -439,10 +449,12 @@ int ForkExec(std::vector<std::string> &cmd, std::vector<std::string> *output)
|
||||
LOGI("get result %{public}s", buf);
|
||||
output->push_back(buf);
|
||||
}
|
||||
(void)close(pipe_fd[0]);
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
waitpid(pid, &status, 0);
|
||||
(void)close(pipe_fd[0]);
|
||||
if (errno == ECHILD) {
|
||||
return E_NO_CHILD;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "utils/set_flag_utils.h"
|
||||
#include "utils/file_utils.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <filesystem>
|
||||
@ -31,13 +32,20 @@ namespace StorageService {
|
||||
|
||||
void SetFlagUtils::ParseDirPath(const std::string &path)
|
||||
{
|
||||
if (!StorageDaemon::IsDir(path)) {
|
||||
LOGE("Input path is not a directory.");
|
||||
return;
|
||||
}
|
||||
SetDirDelFlags(path);
|
||||
std::filesystem::directory_iterator pathList(path);
|
||||
for (const auto& resPath : pathList) {
|
||||
if (std::filesystem::is_directory(resPath)) {
|
||||
if (StorageDaemon::IsDir(resPath.path())) {
|
||||
ParseDirPath(resPath.path().c_str());
|
||||
} else if (StorageDaemon::IsFile(resPath.path())) {
|
||||
SetFileDelFlags(resPath.path().c_str());
|
||||
} else {
|
||||
LOGE("Invalid file path.");
|
||||
}
|
||||
SetFileDelFlags(resPath.path().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -421,7 +421,7 @@ HWTEST_F(FileSystemCryptoTest, Storage_manager_crypto_GenerateAppkey_0000, testi
|
||||
uint32_t hashId = 108;
|
||||
std::string keyId = "keys"; // UserKeys type
|
||||
ASSERT_TRUE(fileSystemCrypto_ != nullptr);
|
||||
uint32_t result = fileSystemCrypto_->GenerateAppkey(userId, hashId, keyId);
|
||||
uint32_t result = fileSystemCrypto_->GenerateAppkey(hashId, userId, keyId);
|
||||
EXPECT_EQ(result, E_USERID_RANGE);
|
||||
|
||||
fileSystemCrypto_->DeleteAppkey(keyId);
|
||||
|
@ -35,7 +35,6 @@ ohos_fuzztest("StorageDaemonFuzzTest") {
|
||||
"-fno-omit-frame-pointer",
|
||||
]
|
||||
sources = [
|
||||
"${storage_daemon_path}/crypto/src/anco_key_manager.cpp",
|
||||
"${storage_daemon_path}/crypto/src/key_manager.cpp",
|
||||
"${storage_daemon_path}/ipc/src/storage_daemon.cpp",
|
||||
"${storage_daemon_path}/ipc/src/storage_daemon_stub.cpp",
|
||||
|
@ -34,7 +34,6 @@ ohos_fuzztest("StorageDaemonCreateShareFileFuzzTest") {
|
||||
"-fno-omit-frame-pointer",
|
||||
]
|
||||
sources = [
|
||||
"${storage_daemon_path}/crypto/src/anco_key_manager.cpp",
|
||||
"${storage_daemon_path}/crypto/src/key_manager.cpp",
|
||||
"${storage_daemon_path}/ipc/src/storage_daemon.cpp",
|
||||
"${storage_daemon_path}/ipc/src/storage_daemon_stub.cpp",
|
||||
|
@ -34,7 +34,6 @@ ohos_fuzztest("StorageDaemonDeleteShareFileFuzzTest") {
|
||||
"-fno-omit-frame-pointer",
|
||||
]
|
||||
sources = [
|
||||
"${storage_daemon_path}/crypto/src/anco_key_manager.cpp",
|
||||
"${storage_daemon_path}/crypto/src/key_manager.cpp",
|
||||
"${storage_daemon_path}/ipc/src/storage_daemon.cpp",
|
||||
"${storage_daemon_path}/ipc/src/storage_daemon_stub.cpp",
|
||||
|
Loading…
x
Reference in New Issue
Block a user