diff --git a/services/storage_daemon/crypto/src/base_key.cpp b/services/storage_daemon/crypto/src/base_key.cpp index db673f18845b0c3a8495a4b098979e8b374307d5..bc053ca6876a4e752eacf75c67d33ae52fcb39bf 100644 --- a/services/storage_daemon/crypto/src/base_key.cpp +++ b/services/storage_daemon/crypto/src/base_key.cpp @@ -37,7 +37,6 @@ namespace { const std::string PATH_LATEST_BACKUP = "/latest_bak"; -const std::string PATH_KEY_VERSION = "/version_"; const std::string PATH_KEY_TEMP = "/temp"; const std::string PATH_NEED_RESTORE_SUFFIX = "/latest/need_restore"; const std::string PATH_USER_EL1_DIR = "/data/service/el1/public/storage_daemon/sd/el1/"; @@ -356,9 +355,13 @@ bool BaseKey::LoadAndSaveShield(const UserAuth &auth, const std::string &pathShi } // update the latest and do cleanups. -bool BaseKey::UpdateKey(const std::string &keypath) +bool BaseKey::UpdateKey(const std::string &keypath, bool needSyncCandidate) { LOGI("enter"); + if (!needSyncCandidate) { + LOGE("Do not update candidate file !"); + return true; + } auto candidate = keypath.empty() ? GetCandidateDir() : keypath; if (candidate.empty() && GetTypeFromDir() == TYPE_EL5) { LOGI("no uece candidate dir, do not need updateKey."); @@ -368,28 +371,13 @@ bool BaseKey::UpdateKey(const std::string &keypath) LOGE("no candidate dir"); return false; } - - // backup the latest - std::string pathLatest = dir_ + PATH_LATEST; - std::string pathLatestBak = dir_ + PATH_LATEST_BACKUP; + DoLatestBackUp(); bool hasLatest = IsDir(dir_ + PATH_LATEST); - if (hasLatest) { - OHOS::ForceRemoveDirectory(pathLatestBak); - if (rename(pathLatest.c_str(), - pathLatestBak.c_str()) != 0) { - LOGE("backup the latest fail errno:%{public}d", errno); - } - LOGI("backup the latest success"); - } - - // rename {candidate} to latest OHOS::ForceRemoveDirectory(dir_ + PATH_LATEST); - if (rename(candidate.c_str(), pathLatest.c_str()) != 0) { + if (rename(candidate.c_str(), (dir_ + PATH_LATEST).c_str()) != 0) { // rename {candidate} to latest LOGE("rename candidate to latest fail return %{public}d", errno); - if (hasLatest) { - // revert from the backup - if (rename(pathLatestBak.c_str(), - pathLatest.c_str()) != 0) { + if (hasLatest) { // revert from the backup + if (rename((dir_ + PATH_LATEST_BACKUP).c_str(), (dir_ + PATH_LATEST).c_str()) != 0) { LOGE("restore the latest_backup fail errno:%{public}d", errno); } else { LOGI("restore the latest_backup success"); @@ -400,10 +388,9 @@ bool BaseKey::UpdateKey(const std::string &keypath) } LOGI("rename candidate %{public}s to latest success", candidate.c_str()); - // cleanup backup and other versions std::vector files; GetSubDirs(dir_, files); - for (const auto &it: files) { + for (const auto &it: files) { // cleanup backup and other versions if (it != PATH_LATEST.substr(1)) { OHOS::ForceRemoveDirectory(dir_ + "/" + it); } @@ -412,11 +399,26 @@ bool BaseKey::UpdateKey(const std::string &keypath) std::string backupDir; KeyBackup::GetInstance().GetBackupDir(dir_, backupDir); KeyBackup::GetInstance().CreateBackup(dir_, backupDir, true); - SyncKeyDir(); return true; } +void BaseKey::DoLatestBackUp() const +{ + // backup the latest + std::string pathLatest = dir_ + PATH_LATEST; + std::string pathLatestBak = dir_ + PATH_LATEST_BACKUP; + bool hasLatest = IsDir(dir_ + PATH_LATEST); + if (hasLatest) { + OHOS::ForceRemoveDirectory(pathLatestBak); + if (rename(pathLatest.c_str(), + pathLatestBak.c_str()) != 0) { + LOGE("backup the latest fail errno:%{public}d", errno); + } + LOGI("backup the latest success"); + } +} + // 针对De只通过Huks加密 bool BaseKey::EncryptDe(const UserAuth &auth, const std::string &path) { @@ -479,7 +481,7 @@ bool BaseKey::EncryptEceSece(const UserAuth &auth, const uint32_t keyType, KeyCo return true; } -bool BaseKey::RestoreKey(const UserAuth &auth) +bool BaseKey::RestoreKey(const UserAuth &auth, bool needSyncCandidate) { LOGI("enter"); auto candidate = GetCandidateDir(); @@ -490,7 +492,7 @@ bool BaseKey::RestoreKey(const UserAuth &auth) if (DoRestoreKeyEx(auth, candidate)) { // update the latest with the candidate - UpdateKey(); + UpdateKey("", needSyncCandidate); return true; } @@ -510,7 +512,7 @@ bool BaseKey::RestoreKey(const UserAuth &auth) for (const auto &it: files) { if (it != candidate) { if (DoRestoreKeyEx(auth, dir_ + "/" + it)) { - UpdateKey(it); + UpdateKey(it, needSyncCandidate); return true; } } diff --git a/services/storage_daemon/crypto/src/fscrypt_key_v1.cpp b/services/storage_daemon/crypto/src/fscrypt_key_v1.cpp index 3e29e7c3a3a3a9ac80b12a6e34052379e855caa2..da9fa822a97bbb34fcbbbfd38c2ba1e930546189 100644 --- a/services/storage_daemon/crypto/src/fscrypt_key_v1.cpp +++ b/services/storage_daemon/crypto/src/fscrypt_key_v1.cpp @@ -25,6 +25,7 @@ #include "key_backup.h" #include "libfscrypt/key_control.h" #include "storage_service_log.h" +#include "utils/file_utils.h" namespace OHOS { namespace StorageDaemon { @@ -225,13 +226,53 @@ bool FscryptKeyV1::ChangePinCodeClassE(bool &isFbeSupport, uint32_t userId) return true; } -bool FscryptKeyV1::DecryptClassE(const UserAuth &auth, bool &isSupport, - bool &eBufferStatue, uint32_t user, uint32_t status) +bool FscryptKeyV1::DoDecryptClassE(const UserAuth &auth, KeyBlob &eSecretFBE, KeyBlob &decryptedKey, + bool needSyncCandidate) +{ + LOGI("enter"); + auto candidate = GetCandidateDir(); + if (candidate.empty()) { + // no candidate dir, just restore from the latest + return KeyBackup::GetInstance().TryRestoreUeceKey(shared_from_this(), auth, eSecretFBE, decryptedKey) == 0; + } + + if (DecryptKeyBlob(auth, candidate, eSecretFBE, decryptedKey)) { + // update the latest with the candidate + UpdateKey("", needSyncCandidate); + return true; + } + + LOGE("DoRestoreKey with %{public}s failed", candidate.c_str()); + // try to restore from other versions + std::vector files; + GetSubDirs(dir_, files); + std::sort(files.begin(), files.end(), [&](const std::string &a, const std::string &b) { + if (a.length() != b.length() || + a.length() < PATH_KEY_VERSION.length() || + b.length() < PATH_KEY_VERSION.length()) { + return a.length() > b.length(); + } + // make sure a.length() >= PATH_KEY_VERSION.length() && b.length() >= PATH_KEY_VERSION.length() + return std::stoi(a.substr(PATH_KEY_VERSION.size() - 1)) > std::stoi(b.substr(PATH_KEY_VERSION.size() - 1)); + }); + for (const auto &it: files) { + if (it != candidate) { + if (DecryptKeyBlob(auth, dir_ + "/" + it, eSecretFBE, decryptedKey)) { + UpdateKey(it, needSyncCandidate); + return true; + } + } + } + return false; +} + +bool FscryptKeyV1::DecryptClassE(const UserAuth &auth, bool &isSupport, bool &eBufferStatue, + uint32_t user, bool needSyncCandidate) { LOGI("enter"); KeyBlob eSecretFBE(AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES); bool isFbeSupport = true; - if (!fscryptV1Ext.ReadClassE(status, eSecretFBE.data, eSecretFBE.size, isFbeSupport)) { + if (!fscryptV1Ext.ReadClassE(USER_UNLOCK, eSecretFBE.data, eSecretFBE.size, isFbeSupport)) { LOGE("fscryptV1Ext ReadClassE failed"); return false; } @@ -248,14 +289,14 @@ bool FscryptKeyV1::DecryptClassE(const UserAuth &auth, bool &isSupport, } LOGI("Decrypt keyPath is %{public}s", (dir_ + PATH_LATEST).c_str()); KeyBlob decryptedKey(AES_256_HASH_RANDOM_SIZE); - if (KeyBackup::GetInstance().TryRestoreUeceKey(shared_from_this(), auth, eSecretFBE, decryptedKey) != 0) { + if (!DoDecryptClassE(auth, eSecretFBE, decryptedKey, needSyncCandidate)) { LOGE("DecryptKeyBlob Decrypt failed"); eSecretFBE.Clear(); return false; } eSecretFBE.Clear(); LOGI("Decrypt end!"); - if (!fscryptV1Ext.WriteClassE(status, decryptedKey.data.get(), decryptedKey.size)) { + if (!fscryptV1Ext.WriteClassE(USER_UNLOCK, decryptedKey.data.get(), decryptedKey.size)) { LOGE("fscryptV1Ext WriteClassE failed"); return false; } diff --git a/services/storage_daemon/crypto/src/fscrypt_key_v2.cpp b/services/storage_daemon/crypto/src/fscrypt_key_v2.cpp index a1396411cc1a035f060286784d13af80a6c812af..5b98037e4251774ac31795f2b0c5b285466ee2a4 100644 --- a/services/storage_daemon/crypto/src/fscrypt_key_v2.cpp +++ b/services/storage_daemon/crypto/src/fscrypt_key_v2.cpp @@ -179,11 +179,11 @@ bool FscryptKeyV2::ChangePinCodeClassE(bool &isFbeSupport, uint32_t userId) } bool FscryptKeyV2::DecryptClassE(const UserAuth &auth, bool &isSupport, - bool &eBufferStatue, uint32_t user, uint32_t status) + bool &eBufferStatue, uint32_t user, bool needSyncCandidate) { (void)auth; (void)user; - (void)status; + (void)needSyncCandidate; isSupport = false; eBufferStatue = false; LOGI("Unsupported fscrypt v2"); diff --git a/services/storage_daemon/crypto/src/key_manager.cpp b/services/storage_daemon/crypto/src/key_manager.cpp index ec10d0df6240e952c4425c927fc001862c270bb7..bbdf5d11e789350e8644239c3efcc45a245aa62b 100644 --- a/services/storage_daemon/crypto/src/key_manager.cpp +++ b/services/storage_daemon/crypto/src/key_manager.cpp @@ -243,7 +243,7 @@ int KeyManager::GenerateAndInstallEl5Key(uint32_t userId, const std::string &dir } } else { bool eBufferStatue = false; - if (!elKey->DecryptClassE(auth, saveESecretStatus[userId], eBufferStatue, userId, USER_UNLOCK)) { + if (!elKey->DecryptClassE(auth, saveESecretStatus[userId], eBufferStatue, userId, false)) { LOGE("user %{public}u decrypt error", userId); } } @@ -1239,7 +1239,7 @@ int KeyManager::ActiveUeceUserKey(unsigned int user, userEl5Key_[user] = elKey; UserAuth auth = { .token = token, .secret = secret }; bool eBufferStatue = false; - if (!elKey->DecryptClassE(auth, saveESecretStatus[user], eBufferStatue, user, USER_UNLOCK)) { + if (!elKey->DecryptClassE(auth, saveESecretStatus[user], eBufferStatue, user, true)) { LOGE("Unlock user %{public}u E_Class failed", user); return -EFAULT; } @@ -1336,7 +1336,7 @@ int32_t KeyManager::UnlockEceSece(uint32_t user, saveLockScreenStatus[user]); return E_NON_EXIST; } - if (!el4Key->RestoreKey({token, secret}) && !el4Key->RestoreKey(NULL_KEY_AUTH)) { + if (!el4Key->RestoreKey({ token, secret }, false) && !el4Key->RestoreKey(NULL_KEY_AUTH, false)) { LOGE("Restore user %{public}u el4 key failed", user); return E_RESTORE_KEY_FAILED; } @@ -1356,7 +1356,7 @@ int32_t KeyManager::UnlockUece(uint32_t user, saveESecretStatus[user] = !auth.token.IsEmpty(); auto el5Key = GetUserElKey(user, EL5_KEY); bool eBufferStatue = false; - if (el5Key != nullptr && !el5Key->DecryptClassE(auth, saveESecretStatus[user], eBufferStatue, user, USER_UNLOCK)) { + if (el5Key != nullptr && !el5Key->DecryptClassE(auth, saveESecretStatus[user], eBufferStatue, user, false)) { LOGE("Unlock user %{public}u uece failed", user); return E_UNLOCK_APP_KEY2_FAILED; } @@ -1461,7 +1461,7 @@ int KeyManager::CreateRecoverKey(uint32_t userId, uint32_t userType, const std:: return -EOPNOTSUPP; } UserAuth auth = { token, secret }; - if ((elxKey->RestoreKey(auth) == false) && (elxKey->RestoreKey(NULL_KEY_AUTH) == false)) { + if ((elxKey->RestoreKey(auth, false) == false) && (elxKey->RestoreKey(NULL_KEY_AUTH, false) == false)) { LOGE("Restore el failed"); return -EFAULT; } diff --git a/services/storage_daemon/include/crypto/base_key.h b/services/storage_daemon/include/crypto/base_key.h index 8f5f64d2ecdfddd119d7cf3b554ddcbe2014a3dc..f9e53ce84ca32fa9e337b555430bbafc721b4413 100644 --- a/services/storage_daemon/include/crypto/base_key.h +++ b/services/storage_daemon/include/crypto/base_key.h @@ -31,6 +31,7 @@ const uint32_t USER_ADD_AUTH = 0x0; const uint32_t USER_CHANGE_AUTH = 0x1; const std::string SUFFIX_NEED_UPDATE = "/need_update"; const std::string SUFFIX_NEED_RESTORE = "/need_restore"; +const std::string PATH_KEY_VERSION = "/version_"; const std::vector NULL_SECRET = { '!' }; enum UpdateVersion { UPDATE_V2 = 2, @@ -50,8 +51,8 @@ public: #else bool StoreKey(const UserAuth &auth); #endif - bool UpdateKey(const std::string &keypath = ""); - bool RestoreKey(const UserAuth &auth); + bool UpdateKey(const std::string &keypath = "", bool needSyncCandidate = true); + bool RestoreKey(const UserAuth &auth, bool needSyncCandidate = true); virtual bool ActiveKey(uint32_t flag, const std::string &mnt = MNT_DATA) = 0; virtual bool InactiveKey(uint32_t flag, const std::string &mnt = MNT_DATA) = 0; virtual bool LockUserScreen(uint32_t flag, uint32_t sdpClass, const std::string &mnt = MNT_DATA) = 0; @@ -61,7 +62,7 @@ public: virtual bool AddClassE(bool &isNeedEncryptClassE, bool &isSupport, uint32_t status) = 0; virtual bool DeleteClassEPinCode(uint32_t userId) = 0; virtual bool DecryptClassE(const UserAuth &auth, bool &isSupport, bool &eBufferStatue, uint32_t user, - uint32_t status) = 0; + bool needSyncCandidate) = 0; 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; @@ -92,6 +93,7 @@ public: protected: static bool SaveKeyBlob(const KeyBlob &blob, const std::string &path); static bool LoadKeyBlob(KeyBlob &blob, const std::string &path, const uint32_t size = 0); + std::string GetCandidateDir() const; std::string dir_ {}; private: @@ -123,9 +125,9 @@ private: void ClearKeyContext(KeyContext &keyCtx); bool InitKeyContext(const UserAuth &auth, const std::string &keyPath, KeyContext &keyCtx); int GetCandidateVersion() const; - std::string GetCandidateDir() const; std::string GetNextCandidateDir() const; void SyncKeyDir() const; + void DoLatestBackUp() const; uint32_t GetTypeFromDir(); uint32_t GetIdFromDir(); diff --git a/services/storage_daemon/include/crypto/fscrypt_key_v1.h b/services/storage_daemon/include/crypto/fscrypt_key_v1.h index 750d446de4e0aaa9bf916e27ea396603b83f7c87..6294e3655c3ce6caecdf9da1d27bafa1eac4544b 100644 --- a/services/storage_daemon/include/crypto/fscrypt_key_v1.h +++ b/services/storage_daemon/include/crypto/fscrypt_key_v1.h @@ -43,7 +43,7 @@ public: bool DeleteClassEPinCode(uint32_t userId = 0); bool ChangePinCodeClassE(bool &isFbeSupport, uint32_t userId = 0); bool DecryptClassE(const UserAuth &auth, bool &isSupport, bool &eBufferStatue, uint32_t user = 0, - uint32_t status = 0); + bool needSyncCandidate = true); bool EncryptClassE(const UserAuth &auth, bool &isSupport, uint32_t user = 0, uint32_t status = 0); bool LockUece(bool &isFbeSupport); @@ -52,10 +52,12 @@ private: bool InstallKeyToKeyring(); bool InstallEceSeceKeyToKeyring(uint32_t sdpClass); bool UninstallKeyToKeyring(); - FscryptKeyV1Ext fscryptV1Ext; bool InstallKeyForAppKeyToKeyring(KeyBlob &appKey); bool UninstallKeyForAppKeyToKeyring(const std::string keyId); bool GenerateAppKeyDesc(KeyBlob appKey); + bool DoDecryptClassE(const UserAuth &auth, KeyBlob &eSecretFBE, KeyBlob &decryptedKey, + bool needSyncCandidate = true); + FscryptKeyV1Ext fscryptV1Ext; }; } // namespace StorageDaemon } // namespace OHOS diff --git a/services/storage_daemon/include/crypto/fscrypt_key_v2.h b/services/storage_daemon/include/crypto/fscrypt_key_v2.h index 6a13b06fe4f466c84bf333c79d33653b800e2caa..749809efa0c5ddc997dfaf268744d942db7d0dd5 100644 --- a/services/storage_daemon/include/crypto/fscrypt_key_v2.h +++ b/services/storage_daemon/include/crypto/fscrypt_key_v2.h @@ -38,7 +38,7 @@ public: bool DeleteClassEPinCode(uint32_t userId = 0); bool ChangePinCodeClassE(bool &isFbeSupport, uint32_t userId = 0); bool DecryptClassE(const UserAuth &auth, bool &isSupport, bool &eBufferStatue, uint32_t user = 0, - uint32_t status = 0); + bool needSyncCandidate = true); bool EncryptClassE(const UserAuth &auth, bool &isSupport, uint32_t user = 0, uint32_t status = 0); bool GenerateAppkey(uint32_t userId, uint32_t hashId, std::string &keyId); bool DeleteAppkey(const std::string KeyId); diff --git a/services/storage_daemon/include/mock/base_key_mock.h b/services/storage_daemon/include/mock/base_key_mock.h index 174967f356c64b20e8721370bf977e36c33aef85..cb0d76c04389526787f7050254462622c7564837 100644 --- a/services/storage_daemon/include/mock/base_key_mock.h +++ b/services/storage_daemon/include/mock/base_key_mock.h @@ -41,6 +41,7 @@ public: virtual bool LoadKeyBlob(KeyBlob &blob, const std::string &path, const uint32_t size) = 0; virtual bool KeyDescIsEmpty() = 0; virtual std::string GetKeyDir() = 0; + virtual std::string GetCandidateDir() = 0; public: static inline std::shared_ptr baseKeyMoc = nullptr; }; @@ -62,6 +63,7 @@ public: MOCK_METHOD1(GetOriginKey, bool(KeyBlob &originKey)); MOCK_METHOD2(SaveKeyBlob, bool(const KeyBlob &blob, const std::string &path)); MOCK_METHOD3(LoadKeyBlob, bool(KeyBlob &blob, const std::string &path, const uint32_t size)); + MOCK_METHOD0(GetCandidateDir, std::string()); }; } } diff --git a/services/storage_daemon/mock/base_key_mock.cpp b/services/storage_daemon/mock/base_key_mock.cpp index 12ce6d79e51d3d51b4589771b572827eb718eefd..18248aa681d3914574b2b7a2933d39e0d1494b98 100644 --- a/services/storage_daemon/mock/base_key_mock.cpp +++ b/services/storage_daemon/mock/base_key_mock.cpp @@ -60,7 +60,7 @@ bool BaseKey::ClearKey(const std::string &mnt) return IBaseKeyMoc::baseKeyMoc->ClearKey(mnt); } -bool BaseKey::UpdateKey(const std::string &keypath) +bool BaseKey::UpdateKey(const std::string &keypath, bool needSyncCandidate) { if (IBaseKeyMoc::baseKeyMoc == nullptr) { return false; @@ -68,7 +68,7 @@ bool BaseKey::UpdateKey(const std::string &keypath) return IBaseKeyMoc::baseKeyMoc->UpdateKey(keypath); } -bool BaseKey::RestoreKey(const UserAuth &auth) +bool BaseKey::RestoreKey(const UserAuth &auth, bool needSyncCandidate) { if (IBaseKeyMoc::baseKeyMoc == nullptr) { return false; @@ -167,3 +167,11 @@ void BaseKey::SetOriginKey(KeyBlob &originKey) { return; } + +std::string BaseKey::GetCandidateDir() const +{ + if (IBaseKeyMoc::baseKeyMoc == nullptr) { + return ""; + } + return IBaseKeyMoc::baseKeyMoc->GetCandidateDir(); +} diff --git a/services/storage_daemon/mock/fscrypt_key_v2_mock.cpp b/services/storage_daemon/mock/fscrypt_key_v2_mock.cpp index 5defbb0d42c1810912d96216435b8c181f4665ac..2925e972e7e91e2121d60ddfbad3eeadb711e35e 100644 --- a/services/storage_daemon/mock/fscrypt_key_v2_mock.cpp +++ b/services/storage_daemon/mock/fscrypt_key_v2_mock.cpp @@ -99,12 +99,12 @@ bool FscryptKeyV2::ChangePinCodeClassE(bool &isFbeSupport, uint32_t userId) } bool FscryptKeyV2::DecryptClassE(const UserAuth &auth, bool &isSupport, - bool &eBufferStatue, uint32_t user, uint32_t status) + bool &eBufferStatue, uint32_t user, bool needSyncCandidate) { if (IFscryptKeyV2Moc::fscryptKeyV2Moc == nullptr) { return false; } - return IFscryptKeyV2Moc::fscryptKeyV2Moc->DecryptClassE(auth, isSupport, eBufferStatue, user, status); + return IFscryptKeyV2Moc::fscryptKeyV2Moc->DecryptClassE(auth, isSupport, eBufferStatue, user, needSyncCandidate); } bool FscryptKeyV2::EncryptClassE(const UserAuth &auth, bool &isSupport, uint32_t user, uint32_t status)