• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <fstream>
17 #include <unistd.h>
18 #include <dirent.h>
19 #include <regex>
20 
21 #include "directory_ex.h"
22 #include "fbex.h"
23 #include "file_ex.h"
24 #include "huks_master.h"
25 #include "iam_client.h"
26 #include "key_backup.h"
27 #include "libfscrypt/key_control.h"
28 #include "storage_service_errno.h"
29 #include "storage_service_log.h"
30 #include "string_ex.h"
31 #include "utils/file_utils.h"
32 #include "utils/storage_radar.h"
33 #include "utils/string_utils.h"
34 #include "utils/storage_radar.h"
35 
36 namespace {
37 constexpr const char *PATH_LATEST_BACKUP = "/latest_bak";
38 constexpr const char *PATH_KEY_TEMP = "/temp";
39 constexpr const char *PATH_NEED_RESTORE_SUFFIX = "/latest/need_restore";
40 constexpr const char *PATH_USER_EL1_DIR = "/data/service/el1/public/storage_daemon/sd/el1/";
41 constexpr uint8_t USER_DESTROY = 0x1;
42 constexpr int32_t RESTORE_VERSION = 3;
43 const std::vector<uint8_t> NULL_SECRET = { '!' };
44 const std::vector<uint8_t> DEFAULT_KEY = { 'D', 'o', 'c', 's' };
45 
46 #ifndef F2FS_IOCTL_MAGIC
47 #define F2FS_IOCTL_MAGIC 0xf5
48 #endif
49 
50 #ifndef F2FS_IOC_SEC_TRIM_FILE
51     struct F2fsSectrimRange {
52         uint64_t start;
53         uint64_t len;
54         uint64_t flags;
55     };
56     using F2fsSectrim = F2fsSectrimRange;
57 #define F2FS_IOC_SEC_TRIM_FILE _IOW(F2FS_IOCTL_MAGIC, 20, F2fsSectrim)
58 #define F2FS_TRIM_FILE_DISCARD 0x1
59 #define F2FS_TRIM_FILE_ZEROOUT 0x2
60 #endif
61 #ifndef F2FS_IOC_SET_PIN_FILE
62 #define F2FS_IOC_SET_PIN_FILE _IOW(F2FS_IOCTL_MAGIC, 13, set)
63 #define F2FS_IOC_GET_PIN_FILE _IOR(F2FS_IOCTL_MAGIC, 14, set)
64 #endif
65 }
66 
67 namespace OHOS {
68 namespace StorageDaemon {
BaseKey(const std::string & dir,uint8_t keyLen)69 BaseKey::BaseKey(const std::string &dir, uint8_t keyLen) : dir_(dir), keyLen_(keyLen),
70     keyEncryptType_(KeyEncryptType::KEY_CRYPT_HUKS)
71 {
72 }
73 
DoTempStore(const KeyContext & sourceCtx,KeyContext & targetCtx)74 static void DoTempStore(const KeyContext &sourceCtx, KeyContext &targetCtx)
75 {
76     LOGI("Store huks result temporary");
77     KeyBlob tempAad(sourceCtx.aad);
78     KeyBlob tempNonce(sourceCtx.nonce);
79     KeyBlob tempRndEnc(sourceCtx.rndEnc);
80     KeyBlob tempShield(sourceCtx.shield);
81     targetCtx.aad = std::move(tempAad);
82     targetCtx.nonce = std::move(tempNonce);
83     targetCtx.rndEnc = std::move(tempRndEnc);
84     targetCtx.shield = std::move(tempShield);
85 }
86 
InitKey(bool needGenerateKey)87 bool BaseKey::InitKey(bool needGenerateKey)
88 {
89     LOGI("enter");
90     if (keyInfo_.version == FSCRYPT_INVALID || keyInfo_.version > KeyCtrlGetFscryptVersion(MNT_DATA)) {
91         LOGE("invalid version %{public}u", keyInfo_.version);
92         return false;
93     }
94     if (!keyInfo_.key.IsEmpty()) {
95         LOGE("key is not empty");
96         return false;
97     }
98     if (needGenerateKey && !GenerateKeyBlob(keyInfo_.key, keyLen_)) {
99         LOGE("GenerateKeyBlob raw key failed");
100         return false;
101     }
102     return true;
103 }
104 
GenerateKeyBlob(KeyBlob & blob,const uint32_t size)105 bool BaseKey::GenerateKeyBlob(KeyBlob &blob, const uint32_t size)
106 {
107     blob = HuksMaster::GenerateRandomKey(size);
108     return !blob.IsEmpty();
109 }
110 
SaveKeyBlob(const KeyBlob & blob,const std::string & path)111 bool BaseKey::SaveKeyBlob(const KeyBlob &blob, const std::string &path)
112 {
113     if (blob.IsEmpty()) {
114         LOGE("blob is empty");
115         return false;
116     }
117     LOGI("enter %{public}s, size=%{public}d", path.c_str(), blob.size);
118     std::string errMsg = "";
119     return WriteFileSync(path.c_str(), blob.data.get(), blob.size, errMsg);
120 }
121 
GenerateAndSaveKeyBlob(KeyBlob & blob,const std::string & path,const uint32_t size)122 bool BaseKey::GenerateAndSaveKeyBlob(KeyBlob &blob, const std::string &path, const uint32_t size)
123 {
124     if (!GenerateKeyBlob(blob, size)) {
125         return false;
126     }
127     return SaveKeyBlob(blob, path);
128 }
129 
LoadKeyBlob(KeyBlob & blob,const std::string & path,const uint32_t size)130 bool BaseKey::LoadKeyBlob(KeyBlob &blob, const std::string &path, const uint32_t size)
131 {
132     LOGW("enter %{public}s, size=%{public}d", path.c_str(), size);
133     std::ifstream file(path, std::ios::binary);
134     if (file.fail()) {
135         LOGE("open %{public}s failed, errno %{public}d", path.c_str(), errno);
136         return false;
137     }
138 
139     file.seekg(0, std::ios::end);
140     uint32_t length = static_cast<uint32_t>(file.tellg());
141     // zero size means use the file length.
142     if ((size != 0) && (length != size)) {
143         LOGE("file:%{public}s size error, real len %{public}d not expected %{public}d", path.c_str(), length, size);
144         return false;
145     }
146     if (!blob.Alloc(length)) {
147         return false;
148     }
149 
150     file.seekg(0, std::ios::beg);
151     if (file.read(reinterpret_cast<char *>(blob.data.get()), length).fail()) {
152         LOGE("read %{public}s failed, errno %{public}d", path.c_str(), errno);
153         return false;
154     }
155     return true;
156 }
157 
ClearKeyInfo()158 void BaseKey::ClearKeyInfo()
159 {
160     LOGI("begin clear key info.");
161     keyInfo_.key.Clear();
162 }
163 
GetCandidateVersion() const164 int BaseKey::GetCandidateVersion() const
165 {
166     std::string prefix(PATH_KEY_VERSION + 1); // skip the first slash
167     std::vector<std::string> files;
168     GetSubDirs(dir_, files);
169     int candidate = -1;
170     for (const auto &it: files) {
171         if (it.rfind(prefix) == 0) {
172             std::string str = it.substr(prefix.length());
173             int ver;
174             if (IsNumericStr(str) && StrToInt(str, ver) && ver >= candidate) {
175                 candidate = ver;
176             }
177         }
178     }
179     if (candidate != -1) {
180         LOGW("candidate key version is %{public}d", candidate);
181     }
182     return candidate;
183 }
184 
185 // Get last version_xx dir to load key files.
GetCandidateDir() const186 std::string BaseKey::GetCandidateDir() const
187 {
188     auto candidate = GetCandidateVersion();
189     // candidate is -1 means no version_xx dir.
190     if (candidate == -1) {
191         return "";
192     }
193 
194     return dir_ + PATH_KEY_VERSION + std::to_string(candidate);
195 }
196 
197 // Get next available version_xx dir to save key files.
GetNextCandidateDir() const198 std::string BaseKey::GetNextCandidateDir() const
199 {
200     auto candidate = GetCandidateVersion();
201     return dir_ + PATH_KEY_VERSION + std::to_string(candidate + 1);
202 }
203 
204 #ifdef USER_CRYPTO_MIGRATE_KEY
StoreKey(const UserAuth & auth,bool needGenerateShield)205 int32_t BaseKey::StoreKey(const UserAuth &auth, bool needGenerateShield)
206 #else
207 int32_t BaseKey::StoreKey(const UserAuth &auth)
208 #endif
209 {
210     LOGI("enter");
211     auto pathTemp = dir_ + PATH_KEY_TEMP;
212     int32_t ret = E_PERMISSION_DENIED;
213 #ifdef USER_CRYPTO_MIGRATE_KEY
214     ret = DoStoreKey(auth, needGenerateShield);
215 #else
216     ret = DoStoreKey(auth);
217 #endif
218     if (ret == E_OK) {
219         // rename keypath/temp/ to keypath/version_xx/
220         auto candidate = GetNextCandidateDir();
221         LOGI("rename %{public}s to %{public}s", pathTemp.c_str(), candidate.c_str());
222         if (rename(pathTemp.c_str(), candidate.c_str()) == 0) {
223             LOGI("start sync");
224             SyncKeyDir();
225             LOGI("sync end");
226             return E_OK;
227         }
228         LOGE("rename fail return %{public}d, cleanup the temp dir", errno);
229         ret = errno;
230     } else {
231         StorageService::StorageRadar::ReportUserKeyResult("StoreKey", 0, ret, "", "dir_=" + dir_);
232         LOGE("DoStoreKey fail, cleanup the temp dir");
233     }
234     OHOS::ForceRemoveDirectory(pathTemp);
235     LOGI("start sync");
236     SyncKeyDir();
237     LOGI("sync end");
238     return ret;
239 }
240 
241 // All key files are saved under keypath/temp/ in this function.
242 #ifdef USER_CRYPTO_MIGRATE_KEY
DoStoreKey(const UserAuth & auth,bool needGenerateShield)243 int32_t  BaseKey::DoStoreKey(const UserAuth &auth, bool needGenerateShield)
244 #else
245 int32_t  BaseKey::DoStoreKey(const UserAuth &auth)
246 #endif
247 {
248     LOGI("enter");
249     auto pathTemp = dir_ + PATH_KEY_TEMP;
250     if (!MkDirRecurse(pathTemp, S_IRWXU)) {
251         LOGE("MkDirRecurse failed!");
252     }
253     if (!CheckAndUpdateVersion()) {
254         return E_VERSION_ERROR;
255     }
256     uint32_t keyType = GetTypeFromDir();
257     if (keyType == TYPE_EL1 || keyType == TYPE_GLOBAL_EL1) {
258         return EncryptDe(auth, pathTemp);
259     }
260     if ((auth.token.IsEmpty() && auth.secret.IsEmpty()) || // Create user/Delete pincode(EL2-4)
261         !auth.token.IsEmpty()) {  // add/change pin code (EL2-4)
262         LOGE("Encrypt huks openssl.");
263         KeyContext keyCtx = {};
264         auto ret = InitKeyContext(auth, pathTemp, keyCtx);
265         if (ret != E_OK) {
266             LOGE("init key context failed !");
267             return ret;
268         }
269 
270         ret = EncryptEceSece(auth, keyType, keyCtx);
271         if (ret != E_OK) {
272             LOGE("Encrypt key failed !");
273             ClearKeyContext(keyCtx);
274             return ret;
275         }
276         // save key buff nonce+rndEnc+aad
277         if (!SaveAndCleanKeyBuff(pathTemp, keyCtx)) {
278             LOGE("save key buff failed !");
279             return E_SAVE_KEY_BUFFER_ERROR;
280         }
281     }
282     LOGI("finish");
283     return E_OK;
284 }
285 
CheckAndUpdateVersion()286 bool BaseKey::CheckAndUpdateVersion()
287 {
288     auto pathVersion = dir_ + PATH_FSCRYPT_VER;
289     std::string version;
290     std::string errMsg = "";
291     if (OHOS::LoadStringFromFile(pathVersion, version)) {
292         if (version != std::to_string(keyInfo_.version)) {
293             LOGE("version already exist %{public}s, not expected %{public}d", version.c_str(), keyInfo_.version);
294             return false;
295         }
296     } else if (SaveStringToFileSync(pathVersion, std::to_string(keyInfo_.version), errMsg) == false) {
297         StorageService::StorageRadar::ReportUserKeyResult("CheckAndUpdateVersion", 0, 0, "", "dir_=" + dir_);
298         LOGE("save version failed, errno:%{public}d", errno);
299         return false;
300     }
301     ChMod(pathVersion, S_IREAD | S_IWRITE);
302     return true;
303 }
304 
InitKeyContext(const UserAuth & auth,const std::string & keyPath,KeyContext & keyCtx)305 int32_t BaseKey::InitKeyContext(const UserAuth &auth, const std::string &keyPath, KeyContext &keyCtx)
306 {
307     LOGI("enter");
308     auto ret = LoadAndSaveShield(auth, keyPath + PATH_SHIELD, true, keyCtx);
309     if (ret != E_OK) {
310         LOGE("Load or save shield failed !");
311         return ret;
312     }
313 
314     if (!GenerateAndSaveKeyBlob(keyCtx.secDiscard, keyPath + PATH_SECDISC, CRYPTO_KEY_SECDISC_SIZE)) {
315         LOGE("Generate sec_discard failed");
316         return E_GENERATE_DISCARD_ERROR;
317     }
318 
319     if (!GenerateKeyBlob(keyCtx.nonce, GCM_NONCE_BYTES) ||
320         !GenerateKeyBlob(keyCtx.aad, GCM_MAC_BYTES)) {
321         LOGE("Generate nonce and aad failed !");
322         return E_KEY_BLOB_ERROR;
323     }
324     return E_OK;
325 }
326 
SaveAndCleanKeyBuff(const std::string & keyPath,KeyContext & keyCtx)327 bool BaseKey::SaveAndCleanKeyBuff(const std::string &keyPath, KeyContext &keyCtx)
328 {
329     KeyBlob storeKey(keyCtx.nonce.size + keyCtx.rndEnc.size + keyCtx.aad.size);
330     if (!CombKeyCtx(keyCtx.nonce, keyCtx.rndEnc, keyCtx.aad, storeKey)) {
331         LOGE("CombKeyCtx failed");
332         return false;
333     }
334 
335     if (!SaveKeyBlob(storeKey, keyPath + PATH_ENCRYPTED)) {
336         return false;
337     }
338 
339     storeKey.Clear();
340     ClearKeyContext(keyCtx);
341     const std::string NEED_UPDATE_PATH = keyPath + SUFFIX_NEED_UPDATE;
342     if (!SaveStringToFile(NEED_UPDATE_PATH, KeyEncryptTypeToString(keyEncryptType_))) {
343         LOGE("Save key type file failed");
344         return false;
345     }
346 
347     return true;
348 }
349 
LoadAndSaveShield(const UserAuth & auth,const std::string & pathShield,bool needGenerateShield,KeyContext & keyCtx)350 int32_t BaseKey::LoadAndSaveShield(const UserAuth &auth, const std::string &pathShield,
351                                    bool needGenerateShield, KeyContext &keyCtx)
352 {
353 #ifdef USER_CRYPTO_MIGRATE_KEY
354     if (needGenerateShield) {
355         auto ret = HuksMaster::GetInstance().GenerateKey(auth, keyCtx.shield);
356         if (ret != HKS_SUCCESS) {
357             LOGE("GenerateKey of shield failed");
358             return ret;
359         }
360     } else {
361         if (!LoadKeyBlob(keyCtx.shield, dir_ + PATH_LATEST + PATH_SHIELD)) {  // needcheck is update
362             keyCtx.rndEnc.Clear();
363             return E_LOAD_KEY_BLOB_ERROR;
364         }
365     }
366 #else
367     auto ret = HuksMaster::GetInstance().GenerateKey(auth, keyCtx.shield);
368     if (ret != HKS_SUCCESS) {
369         LOGE("GenerateKey of shield failed");
370         return ret;
371     }
372 #endif
373     if (!SaveKeyBlob(keyCtx.shield,  pathShield)) {
374         return E_SAVE_KEY_BLOB_ERROR;
375     }
376     return E_OK;
377 }
378 
379 // update the latest and do cleanups.
UpdateKey(const std::string & keypath,bool needSyncCandidate)380 int32_t BaseKey::UpdateKey(const std::string &keypath, bool needSyncCandidate)
381 {
382     LOGI("enter");
383     if (!needSyncCandidate) {
384         LOGE("Do not update candidate file !");
385         return E_OK;
386     }
387     auto candidate = keypath.empty() ? GetCandidateDir() : keypath;
388     LOGI("ready to update, candiate = %{public}s", candidate.c_str());
389     if (candidate.empty() && GetTypeFromDir() == TYPE_EL5) {
390         LOGI("no uece candidate dir, do not need updateKey.");
391         return E_OK;
392     }
393     if (candidate.empty()) {
394         LOGE("no candidate dir");
395         return E_EMPTY_CANDIDATE_ERROR;
396     }
397 
398     if (strcmp(candidate.c_str(), (dir_ + PATH_LATEST).c_str()) != 0) {
399         int32_t ret = UpdateOrRollbackKey(candidate);
400         if (ret != E_OK) {
401             LOGE("backup or rename failed, errno=%{public}d", errno);
402             return ret;
403         }
404     }
405 
406     std::vector<std::string> files;
407     GetSubDirs(dir_, files);
408     for (const auto &it: files) { // cleanup backup and other versions
409         if (it != PATH_LATEST + 1) {
410             OHOS::ForceRemoveDirectory(dir_ + "/" + it);
411         }
412     }
413 
414     std::string backupDir;
415     KeyBackup::GetInstance().GetBackupDir(dir_, backupDir);
416     KeyBackup::GetInstance().CreateBackup(dir_, backupDir, true);
417     SyncKeyDir();
418     return E_OK;
419 }
420 
UpdateOrRollbackKey(const std::string & candidate)421 int32_t BaseKey::UpdateOrRollbackKey(const std::string &candidate)
422 {
423     DoLatestBackUp();
424     bool hasLatest = IsDir(dir_ + PATH_LATEST);
425     OHOS::ForceRemoveDirectory(dir_ + PATH_LATEST);
426     if (rename(candidate.c_str(), (dir_ + PATH_LATEST).c_str()) != 0) { // rename {candidate} to latest
427         LOGE("rename candidate to latest fail return %{public}d", errno);
428         if (hasLatest) { // revert from the backup
429             if (rename((dir_ + PATH_LATEST_BACKUP).c_str(), (dir_ + PATH_LATEST).c_str()) != 0) {
430                 LOGE("restore the latest_backup fail errno:%{public}d", errno);
431             } else {
432                 LOGI("restore the latest_backup success");
433             }
434         }
435         SyncKeyDir();
436         return errno;
437     }
438     LOGI("rename candidate %{public}s to latest success", candidate.c_str());
439     return E_OK;
440 }
441 
DoLatestBackUp() const442 void BaseKey::DoLatestBackUp() const
443 {
444     // backup the latest
445     std::string pathLatest = dir_ + PATH_LATEST;
446     std::string pathLatestBak = dir_ + PATH_LATEST_BACKUP;
447     bool hasLatest = IsDir(dir_ + PATH_LATEST);
448     if (hasLatest) {
449         OHOS::ForceRemoveDirectory(pathLatestBak);
450         if (rename(pathLatest.c_str(),
451                    pathLatestBak.c_str()) != 0) {
452             LOGE("backup the latest fail errno:%{public}d", errno);
453         }
454         LOGI("backup the latest success");
455     }
456 }
457 
EncryptDe(const UserAuth & auth,const std::string & path)458 int32_t BaseKey::EncryptDe(const UserAuth &auth, const std::string &path)
459 {
460     LOGI("enter");
461     KeyContext ctxDe;
462     auto ret = InitKeyContext(auth, path, ctxDe);
463     if (ret != E_OK) {
464         LOGE("init key context failed !");
465         return ret;
466     }
467     keyEncryptType_ = KeyEncryptType::KEY_CRYPT_HUKS;
468     ret = HuksMaster::GetInstance().EncryptKey(ctxDe, auth, keyInfo_, true);
469     if (ret != E_OK) {
470         LOGE("Encrypt by hks failed.");
471         ClearKeyContext(ctxDe);
472         return ret;
473     }
474     if (!SaveKeyBlob(ctxDe.rndEnc, path + PATH_ENCRYPTED)) {
475         LOGE("SaveKeyBlob rndEnc failed.");
476         ClearKeyContext(ctxDe);
477         return E_SAVE_KEY_BLOB_ERROR;
478     }
479     const std::string NEED_UPDATE_PATH = path + SUFFIX_NEED_UPDATE;
480     if (!SaveStringToFile(NEED_UPDATE_PATH, KeyEncryptTypeToString(keyEncryptType_))) {
481         LOGE("Save key type file failed");
482         return E_SAVE_KEY_TYPE_ERROR;
483     }
484     LOGI("finish");
485     return E_OK;
486 }
487 
EncryptEceSece(const UserAuth & auth,const uint32_t keyType,KeyContext & keyCtx)488 int32_t BaseKey::EncryptEceSece(const UserAuth &auth, const uint32_t keyType, KeyContext &keyCtx)
489 {
490     LOGI("enter");
491     // rnd 64 -> rndEnc 80
492     auto ret = HuksMaster::GetInstance().EncryptKeyEx(auth, keyInfo_.key, keyCtx);
493     if (ret != E_OK) {
494         LOGE("Encrypt by hks failed.");
495         return ret;
496     }
497     LOGE("Huks encrypt end.");
498 
499     UserAuth mUserAuth = auth;
500     if (auth.secret.IsEmpty()) {
501         mUserAuth.secret = KeyBlob(NULL_SECRET);
502     }
503 
504     if (keyType == TYPE_EL3 || keyType == TYPE_EL4) {
505         DoTempStore(keyCtx, keyContext_);
506     }
507 
508     KeyBlob rndEnc(keyCtx.rndEnc);
509     LOGI("Encrypt by openssl start"); // rndEnc 80 -> rndEncEnc 108
510     ret = OpensslCrypto::AESEncrypt(mUserAuth.secret, rndEnc, keyCtx);
511     if (ret != E_OK) {
512         LOGE("Encrypt by openssl failed.");
513         return ret;
514     }
515     LOGE("Encrypt by openssl end");
516     rndEnc.Clear();
517     keyEncryptType_ = KeyEncryptType::KEY_CRYPT_HUKS_OPENSSL;
518     LOGI("finish");
519     return E_OK;
520 }
521 
RestoreKey(const UserAuth & auth,bool needSyncCandidate)522 int32_t BaseKey::RestoreKey(const UserAuth &auth, bool needSyncCandidate)
523 {
524     LOGD("BaseKey::RestoreKey enter, auth token %{public}d, auth secret %{public}d",
525         auth.token.IsEmpty(), auth.secret.IsEmpty());
526     auto candidate = GetCandidateDir();
527     if (candidate.empty()) {
528         // no candidate dir, just restore from the latest
529         auto ret = KeyBackup::GetInstance().TryRestoreKey(shared_from_this(), auth);
530         if (ret == 0) {
531             return E_OK;
532         }
533         return ret;
534     }
535 
536     auto ret = DoRestoreKey(auth, candidate);
537     if (ret == E_OK) {
538         // update the latest with the candidate
539         UpdateKey("", needSyncCandidate);
540         return E_OK;
541     }
542 
543     LOGE("DoRestoreKey with %{public}s failed", candidate.c_str());
544     // try to restore from other versions
545     std::vector<std::string> files;
546     GetSubDirs(dir_, files);
547     std::sort(files.begin(), files.end(), [&](const std::string &a, const std::string &b) {
548         if (a.length() != b.length() ||
549             a.length() < strlen(PATH_KEY_VERSION) ||
550             b.length() < strlen(PATH_KEY_VERSION)) {
551             return a.length() > b.length();
552         }
553         std::regex pattern("^version_\\d+$");
554         if (!std::regex_search(a, pattern)) return false;
555         if (!std::regex_search(b, pattern)) return true;
556 
557         // make sure a and b is version_\d+
558         auto a_len = std::atoi(a.substr(strlen(PATH_KEY_VERSION) - 1).c_str());
559         auto b_len = std::atoi(b.substr(strlen(PATH_KEY_VERSION) - 1).c_str());
560         return a_len > b_len;
561     });
562     for (const auto &it: files) {
563         if (it != candidate) {
564             ret = DoRestoreKey(auth, dir_ + "/" + it);
565             if (ret == E_OK) {
566                 UpdateKey((dir_ + "/" + it), needSyncCandidate);
567                 return E_OK;
568             }
569         }
570     }
571     return ret;
572 }
573 
RestoreKey4Nato(const std::string & keyDir,KeyType type)574 int32_t BaseKey::RestoreKey4Nato(const std::string &keyDir, KeyType type)
575 {
576     LOGI("Restore key for nato for type %{public}u keyDir=%{public}s enter.", type, keyDir.c_str());
577     static const std::map<KeyType, uint32_t> keyTypeMap = {
578         {KeyType::EL2_KEY, TYPE_EL2},
579         {KeyType::EL3_KEY, TYPE_EL3},
580         {KeyType::EL4_KEY, TYPE_EL4},
581     };
582 
583     auto iter = keyTypeMap.find(type);
584     if (iter == keyTypeMap.end()) {
585         return E_PARAMS_INVALID;
586     }
587     UserAuth auth = { {}, {} };
588     auto ret = DoRestoreKeyCeEceSece(auth, keyDir + PATH_LATEST, iter->second);
589     if (ret != E_OK) {
590         LOGE("Restore ce ece sece for nato secen failed !");
591         return ret;
592     }
593     ret = StoreKey({ {}, {}, 0 });
594     if (ret != E_OK) {
595         LOGE("Store key for nato secen failed !");
596         return ret;
597     }
598     ret = UpdateKey();
599     if (ret != E_OK) {
600         LOGE("Update key for nato secen failed !");
601         return ret;
602     }
603     LOGI("Restore key for nato for type %{public}u success.", type);
604     return E_OK;
605 }
606 
DoRestoreKeyOld(const UserAuth & auth,const std::string & path)607 int32_t BaseKey::DoRestoreKeyOld(const UserAuth &auth, const std::string &path)
608 {
609     LOGW("enter, path = %{public}s", path.c_str());
610     const std::string NEED_UPDATE_PATH = dir_ + PATH_LATEST + SUFFIX_NEED_UPDATE;
611     if (!auth.secret.IsEmpty() && FileExists(NEED_UPDATE_PATH)) {
612         keyEncryptType_ = KeyEncryptType::KEY_CRYPT_OPENSSL;
613         LOGI("set keyEncryptType_ as KEY_CRYPT_OPENSSL success");
614     } else {
615         keyEncryptType_ = KeyEncryptType::KEY_CRYPT_HUKS;
616         LOGI("set keyEncryptType_ as KEY_CRYPT_HUKS success");
617     }
618     auto ver = KeyCtrlLoadVersion(dir_.c_str());
619     if (ver == FSCRYPT_INVALID || ver != keyInfo_.version) {
620         LOGE("RestoreKey fail. bad version loaded %{public}u not expected %{public}u", ver, keyInfo_.version);
621         return E_PARAMS_INVALID;
622     }
623     if (!LoadKeyBlob(keyContext_.rndEnc, path + PATH_ENCRYPTED)) {
624         return E_LOAD_KEY_BLOB_ERROR;
625     }
626     if (keyEncryptType_ == KeyEncryptType::KEY_CRYPT_HUKS) {
627         if (!LoadKeyBlob(keyContext_.shield, path + PATH_SHIELD)) {
628             keyContext_.rndEnc.Clear();
629             return E_LOAD_KEY_BLOB_ERROR;
630         }
631     }
632     if (!LoadKeyBlob(keyContext_.secDiscard, path + PATH_SECDISC, CRYPTO_KEY_SECDISC_SIZE)) {
633         keyContext_.rndEnc.Clear();
634         keyContext_.shield.Clear();
635         return E_LOAD_KEY_BLOB_ERROR;
636     }
637     return Decrypt(auth);
638 }
639 
DoRestoreKeyDe(const UserAuth & auth,const std::string & path)640 int32_t BaseKey::DoRestoreKeyDe(const UserAuth &auth, const std::string &path)
641 {
642     LOGI("enter");
643     KeyContext ctxNone;
644     if (!LoadKeyBlob(ctxNone.rndEnc, path + PATH_ENCRYPTED)) {
645         LOGE("Load rndEnc failed !");
646         return E_LOAD_KEY_BLOB_ERROR;
647     }
648 
649     if (!LoadKeyBlob(ctxNone.secDiscard, path + PATH_SECDISC) ||
650         !LoadKeyBlob(ctxNone.shield, path + PATH_SHIELD)) {
651         ctxNone.rndEnc.Clear();
652         LOGE("Load shield failed !");
653         return E_LOAD_KEY_BLOB_ERROR;
654     }
655 
656     LOGW("Decrypt by hks start.");  // keyCtx.rndEnc 80 -> 64
657     auto ret = HuksMaster::GetInstance().DecryptKey(ctxNone, auth, keyInfo_, true);
658     if (ret != E_OK) {
659         LOGE("Decrypt by hks failed.");
660         ClearKeyContext(ctxNone);
661         return ret;
662     }
663     ClearKeyContext(ctxNone);
664     LOGI("finish");
665     return E_OK;
666 }
667 
DoRestoreKeyCeEceSece(const UserAuth & auth,const std::string & path,const uint32_t keyType)668 int32_t BaseKey::DoRestoreKeyCeEceSece(const UserAuth &auth, const std::string &path, const uint32_t keyType)
669 {
670     LOGI("enter");
671     auto startTime = StorageService::StorageRadar::RecordCurrentTime();
672     if ((auth.secret.IsEmpty() && auth.token.IsEmpty()) ||
673         (!auth.secret.IsEmpty() && !auth.token.IsEmpty())) {
674         KeyContext ctxNone;
675         if (!LoadKeyBlob(ctxNone.rndEnc, path + PATH_ENCRYPTED)) {
676             LOGE("Load rndEnc failed !");
677             return E_LOAD_KEY_BLOB_ERROR;
678         }
679 
680         ctxNone.aad.Alloc(GCM_MAC_BYTES);
681         ctxNone.nonce.Alloc(GCM_NONCE_BYTES);
682         if (!SplitKeyCtx(ctxNone.rndEnc, ctxNone.nonce, ctxNone.rndEnc, ctxNone.aad)) {
683             ctxNone.rndEnc.Clear();
684             LOGE("Split key context failed !");
685             return E_SPILT_KEY_CTX_ERROR;
686         }
687         if (!LoadKeyBlob(ctxNone.secDiscard, path + PATH_SECDISC) ||
688             !LoadKeyBlob(ctxNone.shield, path + PATH_SHIELD)) {
689             ctxNone.rndEnc.Clear();
690             LOGE("Load shield failed !");
691             return E_SHIELD_OPERATION_ERROR;
692         }
693         auto delay = StorageService::StorageRadar::ReportDuration("READ KEY FILE: FILE OPS", startTime);
694         LOGI("SD_DURATION: READ KEY FILE: delay time = %{public}s", delay.c_str());
695         return DecryptReal(auth, keyType, ctxNone);
696     }
697 
698     // face/finger (EL3 EL4)
699     if (auth.secret.IsEmpty() && !auth.token.IsEmpty()) {
700         if (!keyContext_.shield.IsEmpty() || !keyContext_.rndEnc.IsEmpty()) {
701             LOGI("Restore key by face/finger");
702             UserAuth mUserAuth = auth;
703             mUserAuth.secret = KeyBlob(NULL_SECRET);
704             KeyContext tempCtx = {};
705             DoTempStore(keyContext_, tempCtx);
706             auto ret = HuksMaster::GetInstance().DecryptKeyEx(tempCtx, mUserAuth, keyInfo_.key);
707             if (ret != E_OK) {
708                 LOGE("Decrypt by hks failed.");
709                 ClearKeyContext(tempCtx);
710                 return ret;
711             }
712             ClearKeyContext(tempCtx);
713         }
714         return E_OK;
715     }
716     LOGE("Decrypt failed, invalid param !");
717     return E_PARAMS_INVALID;
718 }
719 
DoRestoreKey(const UserAuth & auth,const std::string & path)720 int32_t BaseKey::DoRestoreKey(const UserAuth &auth, const std::string &path)
721 {
722     auto ver = KeyCtrlLoadVersion(dir_.c_str());
723     if (ver == FSCRYPT_INVALID || ver != keyInfo_.version) {
724         LOGE("RestoreKey fail. bad version loaded %{public}u not expected %{public}u", ver, keyInfo_.version);
725         return E_VERSION_ERROR;
726     }
727 
728     std::string encryptType;
729     LoadStringFromFile(path + SUFFIX_NEED_UPDATE, encryptType);
730     LOGI("encrypt type : %{public}s, keyInfo empty: %{public}u", encryptType.c_str(), keyInfo_.key.IsEmpty());
731 
732     uint32_t keyType = GetTypeFromDir();
733     if (keyType == TYPE_EL1 || keyType == TYPE_GLOBAL_EL1) {
734         LOGI("Restore device key.");
735         return DoRestoreKeyDe(auth, path);
736     }
737     int ret = -1;
738     if (encryptType == KeyEncryptTypeToString(KeyEncryptType::KEY_CRYPT_HUKS_OPENSSL)) {
739         LOGD("Restore ce ece sece key.");
740         ret = DoRestoreKeyCeEceSece(auth, path, keyType);
741     }
742     std::error_code errCode;
743     std::string need_restore;
744     LoadStringFromFile(path + SUFFIX_NEED_RESTORE, need_restore);
745     uint32_t restore_version = static_cast<uint32_t>(std::atoi(need_restore.c_str()));
746     UpdateVersion update_version = static_cast<UpdateVersion>(std::atoi(need_restore.c_str()));
747     LOGI("NeedRestore Path is: %{public}s, restore_version: %{public}u", path.c_str(), restore_version);
748     if (std::filesystem::exists(path + SUFFIX_NEED_RESTORE, errCode)) {
749         if (restore_version < RESTORE_VERSION) {
750             LOGW("Old DOUBLE_2_SINGLE.");
751             ret = DoUpdateRestore(auth, path);
752         } else {
753             LOGW("New DOUBLE_2_SINGLE.");
754             ret = DoUpdateRestoreVx(auth, path, update_version);
755         }
756     }
757     LOGI("end ret %{public}u, filepath isExist: %{public}u", ret, errCode.value());
758     return ret;
759 }
760 
DoUpdateRestore(const UserAuth & auth,const std::string & keyPath)761 int32_t BaseKey::DoUpdateRestore(const UserAuth &auth, const std::string &keyPath)
762 {
763     LOGI("enter");
764     auto ret = DoRestoreKeyOld(auth, keyPath);
765     if (ret != E_OK) {
766         LOGE("Restore old failed !");
767         return ret;
768     }
769     std::error_code errCode;
770     if (std::filesystem::exists(dir_ + PATH_NEED_RESTORE_SUFFIX, errCode) && !auth.token.IsEmpty()) {
771         LOGE("Double 2 single, skip huks -> huks-openssl !");
772         return E_OK;
773     }
774     uint64_t secureUid = { 0 };
775     uint32_t userId = GetIdFromDir();
776     if ((userId < StorageService::START_APP_CLONE_USER_ID || userId >= StorageService::MAX_APP_CLONE_USER_ID) &&
777         !IamClient::GetInstance().GetSecureUid(userId, secureUid)) {
778         LOGE("Get secure uid form iam failed, use default value.");
779     }
780     ret = StoreKey({ auth.token, auth.secret, secureUid });
781     if (ret != E_OK) {
782         LOGE("Store old failed !");
783         return ret;
784     }
785     ret = UpdateKey();
786     if (ret != E_OK) {
787         LOGE("Update old failed !");
788         return ret;
789     }
790     LOGI("finish");
791     return E_OK;
792 }
DoUpdateRestoreVx(const UserAuth & auth,const std::string & keyPath,UpdateVersion update_version)793 int32_t BaseKey::DoUpdateRestoreVx(const UserAuth &auth, const std::string &keyPath, UpdateVersion update_version)
794 {
795     LOGI("enter");
796     LOGI("Restore version %{public}u", update_version);
797     auto ret = DoRestoreKeyCeEceSece(auth, keyPath, GetTypeFromDir());
798     if (ret != E_OK) {
799         LOGE("Restore ce ece sece failed !");
800         return ret;
801     }
802     uint64_t secureUid = { 0 };
803 
804     uint32_t userId = GetIdFromDir();
805     if ((userId < StorageService::START_APP_CLONE_USER_ID || userId >= StorageService::MAX_APP_CLONE_USER_ID) &&
806         IamClient::GetInstance().HasPinProtect(userId)) {
807         if (!IamClient::GetInstance().GetSecureUid(GetIdFromDir(), secureUid)) {
808             LOGE("Get secure uid form iam failed, use default value.");
809         }
810         LOGI("PIN protect exist.");
811     }
812     ret = StoreKey({auth.token, auth.secret, secureUid});
813     if (ret != E_OK) {
814         LOGE("Store old failed !");
815         return ret;
816     }
817     ret = UpdateKey();
818     if (ret != E_OK) {
819         LOGE("Update old failed !");
820         return ret;
821     }
822     LOGI("finish");
823     return E_OK;
824 }
825 
DecryptReal(const UserAuth & auth,const uint32_t keyType,KeyContext & keyCtx)826 int32_t BaseKey::DecryptReal(const UserAuth &auth, const uint32_t keyType, KeyContext &keyCtx)
827 {
828     LOGI("enter");
829     UserAuth mUserAuth = auth;
830     if (auth.secret.IsEmpty()) {
831         mUserAuth.secret = KeyBlob(NULL_SECRET);
832     }
833     KeyBlob rndEnc(keyCtx.rndEnc);
834     auto ret = OpensslCrypto::AESDecrypt(mUserAuth.secret, keyCtx, rndEnc);
835     if (ret != E_OK) { // rndEncEnc -> rndEnc
836         LOGE("Decrypt by openssl failed.");
837         return ret;
838     }
839 
840     auto startTime = StorageService::StorageRadar::RecordCurrentTime();
841     keyCtx.rndEnc = std::move(rndEnc);
842     if (keyType == TYPE_EL3 || keyType == TYPE_EL4) {
843         DoTempStore(keyCtx, keyContext_);
844     }
845     ret = HuksMaster::GetInstance().DecryptKeyEx(keyCtx, auth, keyInfo_.key);
846     if (ret != E_OK) { // rndEnc -> rnd
847         LOGE("Decrypt by hks failed.");
848         return ret;
849     }
850     auto delay = StorageService::StorageRadar::ReportDuration("HUKS: DECRYPT KEY EX", startTime);
851     LOGI("SD_DURATION: HUKS: DECRYPT KEY EX: delay time = %{public}s", delay.c_str());
852 
853     rndEnc.Clear();
854     LOGI("finish");
855     return E_OK;
856 }
857 
Decrypt(const UserAuth & auth)858 int32_t BaseKey::Decrypt(const UserAuth &auth)
859 {
860     int32_t ret = E_PARAMS_INVALID;
861     switch (keyEncryptType_) {
862         case KeyEncryptType::KEY_CRYPT_OPENSSL:
863             LOGI("Enhanced decrypt key start");
864             ret = OpensslCrypto::AESDecrypt(auth.secret, keyContext_, keyInfo_.key);
865             break;
866         case KeyEncryptType::KEY_CRYPT_HUKS:
867             LOGI("Huks decrypt key start");
868             ret = HuksMaster::GetInstance().DecryptKey(keyContext_, auth, keyInfo_, true);
869             break;
870         case KeyEncryptType::KEY_CRYPT_HUKS_OPENSSL:
871             LOGI("Huks openssl decrypt key, skip");
872             break;
873     }
874     ClearKeyContext(keyContext_);
875     return ret;
876 }
877 
ClearKey(const std::string & mnt)878 bool BaseKey::ClearKey(const std::string &mnt)
879 {
880     LOGI("enter, dir_ = %{public}s", dir_.c_str());
881     auto ret = InactiveKey(USER_DESTROY, mnt);
882     if (ret != E_OK) {
883         LOGE("InactiveKey failed.");
884     }
885     keyInfo_.key.Clear();
886     keyInfo_.keyHash.Clear();
887     bool needClearFlag = true;
888 #ifdef USER_CRYPTO_MIGRATE_KEY
889     std::error_code errCode;
890     std::string elNeedRestorePath(PATH_USER_EL1_DIR);
891     elNeedRestorePath += std::to_string(GetIdFromDir());
892     elNeedRestorePath += PATH_NEED_RESTORE_SUFFIX;
893     if (std::filesystem::exists(elNeedRestorePath, errCode)) {
894         needClearFlag = false;
895         LOGI("needRestore flag exist, do not remove secret.");
896     }
897 #endif
898     if (needClearFlag) {
899         LOGI("do clear key.");
900         if (!IsDir(dir_)) {
901             LOGE("dir not exist, do not need to remove dir");
902             return (ret == E_OK);
903         }
904         WipingActionDir(dir_);
905         std::string backupDir;
906         KeyBackup::GetInstance().GetBackupDir(dir_, backupDir);
907         WipingActionDir(backupDir);
908         KeyBackup::GetInstance().RemoveNode(backupDir);
909         LOGI("force remove backupDir, %{public}s.", backupDir.c_str());
910         OHOS::ForceRemoveDirectory(backupDir);
911         LOGI("force remove dir_, %{public}s.", dir_.c_str());
912         bool removeRet = OHOS::ForceRemoveDirectory(dir_);
913         if (!removeRet) {
914             LOGE("ForceRemoveDirectory failed.");
915             return removeRet;
916         }
917         // use F2FS_IOC_SEC_TRIM_FILE
918     }
919     return (ret == E_OK);
920 }
921 
WipingActionDir(std::string & path)922 void BaseKey::WipingActionDir(std::string &path)
923 {
924     std::vector<std::string> fileList;
925     LOGI("WipingActionDir path.c_str() is %{public}s", path.c_str());
926     OpenSubFile(path.c_str(), fileList);
927     for (const auto &it: fileList) {
928         FILE *f = fopen(it.c_str(), "w");
929         if (f == nullptr) {
930             LOGE("open %{public}s failed, errno %{public}u", it.c_str(), errno);
931             return;
932         }
933         int fd = fileno(f);
934         if (fd < 0) {
935             LOGE("open %{public}s failed, errno %{public}u", it.c_str(), errno);
936             (void)fclose(f);
937             return;
938         }
939         uint32_t  set = 1;
940         int ret = ioctl(fd, F2FS_IOC_SET_PIN_FILE, &set);
941         if (ret != 0) {
942             LOGE("F2FS_IOC_SET_PIN_FILE ioctl is %{public}u, errno = %{public}u", ret, errno);
943         }
944         struct F2fsSectrimRange trimRange;
945         trimRange.start = 0;
946         trimRange.len = -1;
947         trimRange.flags = F2FS_TRIM_FILE_DISCARD | F2FS_TRIM_FILE_ZEROOUT;
948         ret = ioctl(fd, F2FS_IOC_SEC_TRIM_FILE, &trimRange);
949         if (ret != 0 && errno == EOPNOTSUPP) {
950             trimRange.flags = F2FS_TRIM_FILE_ZEROOUT;
951             ret = ioctl(fd, F2FS_IOC_SEC_TRIM_FILE, &trimRange);
952             if (ret != 0) {
953                 LOGE("F2FS_IOC_SEC_TRIM_FILE ioctl is %{public}u, errno = %{public}u", ret, errno);
954             }
955         }
956         set = 0;
957         ret = ioctl(fd, F2FS_IOC_SET_PIN_FILE, &set);
958         if (ret != 0) {
959             LOGE("F2FS_IOC_SET_PIN_FILE ioctl is %{public}u", ret);
960         }
961         LOGI("WipingActionDir success");
962         (void)fclose(f);
963     }
964 }
965 
SyncKeyDir() const966 void BaseKey::SyncKeyDir() const
967 {
968     DIR *dir = opendir(dir_.c_str());
969     if (dir == nullptr) {
970         LOGE("open %{public}s failed, errno %{public}u", dir_.c_str(), errno);
971         return;
972     }
973     int fd = dirfd(dir);
974     if (fd < 0) {
975         LOGE("open %{public}s failed, errno %{public}d", dir_.c_str(), errno);
976         sync();
977         (void)closedir(dir);
978         return;
979     }
980     LOGW("start fsync, dir_ is %{public}s", dir_.c_str());
981     auto startTime = StorageService::StorageRadar::RecordCurrentTime();
982     if (fsync(fd) != 0) {
983         LOGE("fsync %{public}s failed, errno %{public}d", dir_.c_str(), errno);
984         syncfs(fd);
985     }
986     auto delay = StorageService::StorageRadar::ReportDuration("FSYNC",
987         startTime, StorageService::DELAY_TIME_THRESH_HIGH, StorageService::DEFAULT_USERID);
988     LOGW("fsync end. SD_DURATION: FSYNC: delay time = %{public}s", delay.c_str());
989     (void)closedir(dir);
990 }
991 
UpgradeKeys()992 bool BaseKey::UpgradeKeys()
993 {
994     std::vector<std::string> versions;
995     GetSubDirs(dir_, versions);
996 
997     for (const auto &it : versions) {
998         std::string shieldPath = dir_ + "/" + it + PATH_SHIELD;
999         LOGI("Upgrade of %{public}s", shieldPath.c_str());
1000         LoadKeyBlob(keyContext_.shield, shieldPath);
1001         if (HuksMaster::GetInstance().UpgradeKey(keyContext_)) {
1002             LOGI("success upgrade of %{public}s", shieldPath.c_str());
1003             SaveKeyBlob(keyContext_.shield, shieldPath);
1004             SyncKeyDir();
1005         }
1006     }
1007     return true;
1008 }
1009 
GetOriginKey(KeyBlob & originKey)1010 bool BaseKey::GetOriginKey(KeyBlob &originKey)
1011 {
1012     LOGI("enter");
1013     if (keyInfo_.key.IsEmpty()) {
1014         LOGE("origin key is empty, need restore !");
1015         return false;
1016     }
1017     KeyBlob key(keyInfo_.key);
1018     originKey = std::move(key);
1019     return true;
1020 }
1021 
SetOriginKey(KeyBlob & originKey)1022 void BaseKey::SetOriginKey(KeyBlob &originKey)
1023 {
1024     LOGI("enter");
1025     keyInfo_.key = std::move(originKey);
1026     return;
1027 }
1028 
GetHashKey(KeyBlob & hashKey)1029 bool BaseKey::GetHashKey(KeyBlob &hashKey)
1030 {
1031     LOGI("enter");
1032     if (keyInfo_.keyHash.IsEmpty()) {
1033         LOGE("hash key is empty.");
1034         return false;
1035     }
1036     KeyBlob key(keyInfo_.keyHash);
1037     hashKey = std::move(key);
1038     return true;
1039 }
1040 
GenerateHashKey()1041 bool BaseKey::GenerateHashKey()
1042 {
1043     LOGI("enter");
1044     if (keyInfo_.key.IsEmpty()) {
1045         LOGE("origin key is empty, Generate error");
1046         return false;
1047     }
1048 
1049     if (!keyInfo_.keyHash.IsEmpty()) {
1050         LOGW("clear hash key when is not empty");
1051         keyInfo_.keyHash.Clear();
1052     }
1053 
1054     KeyBlob preKey(DEFAULT_KEY);
1055     KeyBlob hashKey = OpensslCrypto::HashWithPrefix(preKey, keyInfo_.key, AES_256_HASH_RANDOM_SIZE);
1056     keyInfo_.keyHash = std::move(hashKey);
1057     return true;
1058 }
1059 
EncryptKeyBlob(const UserAuth & auth,const std::string & keyPath,KeyBlob & planKey,KeyBlob & encryptedKey)1060 int32_t BaseKey::EncryptKeyBlob(const UserAuth &auth, const std::string &keyPath, KeyBlob &planKey,
1061                                 KeyBlob &encryptedKey)
1062 {
1063     LOGI("enter");
1064     KeyContext keyCtx;
1065     if (!MkDirRecurse(keyPath, S_IRWXU)) {
1066         LOGE("MkDirRecurse failed!");
1067     }
1068 
1069     LOGW("key path is exist : %{public}d", FileExists(keyPath));
1070     if (HuksMaster::GetInstance().GenerateKey(auth, keyCtx.shield) != HKS_SUCCESS ||
1071         !SaveKeyBlob(keyCtx.shield, keyPath + PATH_SHIELD)) {
1072         LOGE("GenerateKey and save shield failed!");
1073         return E_SHIELD_OPERATION_ERROR;
1074     }
1075     if (!GenerateAndSaveKeyBlob(keyCtx.secDiscard, keyPath + PATH_SECDISC, CRYPTO_KEY_SECDISC_SIZE)) {
1076         keyCtx.shield.Clear();
1077         LOGE("GenerateAndSaveKeyBlob sec_discard failed!");
1078         return E_SAVE_KEY_BLOB_ERROR;
1079     }
1080     auto ret = HuksMaster::GetInstance().EncryptKey(keyCtx, auth, {.key = planKey}, false);
1081     if (ret != E_OK) {
1082         keyCtx.shield.Clear();
1083         keyCtx.secDiscard.Clear();
1084         LOGE("HUKS encrypt key failed!");
1085         return ret;
1086     }
1087     CombKeyBlob(keyCtx.rndEnc, keyCtx.nonce, encryptedKey);
1088 
1089     ClearKeyContext(keyCtx);
1090     LOGI("finish");
1091     return E_OK;
1092 }
1093 
DecryptKeyBlob(const UserAuth & auth,const std::string & keyPath,KeyBlob & planKey,KeyBlob & decryptedKey)1094 int32_t BaseKey::DecryptKeyBlob(const UserAuth &auth, const std::string &keyPath, KeyBlob &planKey,
1095                                 KeyBlob &decryptedKey)
1096 {
1097     LOGI("enter");
1098     KeyContext keyCtx;
1099     auto candidate = GetCandidateDir();
1100     std::string path = candidate.empty() ? keyPath : candidate;
1101     LOGI("Key path is exist : %{public}d", FileExists(path));
1102 
1103     if (!LoadKeyBlob(keyCtx.shield, path + PATH_SHIELD)) {
1104         LOGE("Load KeyBlob shield failed!");
1105         return E_LOAD_KEY_BLOB_ERROR;
1106     }
1107     if (!LoadKeyBlob(keyCtx.secDiscard, path + PATH_SECDISC, CRYPTO_KEY_SECDISC_SIZE)) {
1108         LOGE("Load key secDiscard failed!");
1109         keyCtx.shield.Clear();
1110         return E_LOAD_KEY_BLOB_ERROR;
1111     }
1112 
1113     KeyInfo planKeyInfo = {.key = planKey};
1114     SplitKeyBlob(planKey, keyCtx.rndEnc, keyCtx.nonce, AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES);
1115     LOGE("decrypted size : %{public}d, nonce size : %{public}d", keyCtx.rndEnc.size, keyCtx.nonce.size);
1116 
1117     auto ret = HuksMaster::GetInstance().DecryptKey(keyCtx, auth, planKeyInfo, false);
1118     if (ret != E_OK) {
1119         keyCtx.shield.Clear();
1120         keyCtx.rndEnc.Clear();
1121         LOGE("HUKS decrypt key failed!");
1122         return ret;
1123     }
1124 
1125     decryptedKey = std::move(planKeyInfo.key);
1126     planKeyInfo.key.Clear();
1127     ClearKeyContext(keyCtx);
1128     LOGI("finish");
1129     return E_OK;
1130 }
1131 
RenameKeyPath(const std::string & keyPath)1132 bool BaseKey::RenameKeyPath(const std::string &keyPath)
1133 {
1134     // rename keypath/temp/ to keypath/version_xx/
1135     auto candidate = GetNextCandidateDir();
1136     LOGI("rename %{public}s to %{public}s", keyPath.c_str(), candidate.c_str());
1137     if (rename(keyPath.c_str(), candidate.c_str()) != 0) {
1138         LOGE("rename %{public}s to %{public}s failed!", keyPath.c_str(), candidate.c_str());
1139         return false;
1140     }
1141     SyncKeyDir();
1142     return true;
1143 }
1144 
CombKeyBlob(const KeyBlob & encAad,const KeyBlob & end,KeyBlob & keyOut)1145 void BaseKey::CombKeyBlob(const KeyBlob &encAad, const KeyBlob &end, KeyBlob &keyOut)
1146 {
1147     std::vector<uint8_t> startVct(encAad.data.get(), encAad.data.get() + encAad.size);
1148     std::vector<uint8_t> endVct(end.data.get(), end.data.get() + end.size);
1149     startVct.insert(startVct.end(), endVct.begin(), endVct.end());
1150     std::copy(startVct.begin(), startVct.end(), keyOut.data.get());
1151     startVct.clear();
1152     endVct.clear();
1153 }
1154 
SplitKeyBlob(const KeyBlob & keyIn,KeyBlob & encAad,KeyBlob & nonce,uint32_t start)1155 void BaseKey::SplitKeyBlob(const KeyBlob &keyIn, KeyBlob &encAad, KeyBlob &nonce, uint32_t start)
1156 {
1157     std::vector<uint8_t> inVct(keyIn.data.get(), keyIn.data.get() + keyIn.size);
1158     encAad.Alloc(start);
1159     nonce.Alloc(keyIn.size - start);
1160     std::copy(inVct.begin(), inVct.begin() + start, encAad.data.get());
1161     std::copy(inVct.begin() + start, inVct.end(), nonce.data.get());
1162     inVct.clear();
1163 }
1164 
ClearKeyContext(KeyContext & keyCtx)1165 void BaseKey::ClearKeyContext(KeyContext &keyCtx)
1166 {
1167     LOGD("BaseKey::ClearKeyContext enter");
1168     keyCtx.aad.Clear();
1169     keyCtx.nonce.Clear();
1170     keyCtx.shield.Clear();
1171     keyCtx.rndEnc.Clear();
1172     keyCtx.secDiscard.Clear();
1173 }
1174 
KeyEncryptTypeToString(KeyEncryptType keyEncryptType_) const1175 std::string BaseKey::KeyEncryptTypeToString(KeyEncryptType keyEncryptType_) const
1176 {
1177     switch (keyEncryptType_) {
1178         case KeyEncryptType::KEY_CRYPT_OPENSSL:
1179             return "KEY_CRYPT_OPENSSL";
1180         case KeyEncryptType::KEY_CRYPT_HUKS:
1181             return "KEY_CRYPT_HUKS";
1182         case KeyEncryptType::KEY_CRYPT_HUKS_OPENSSL:
1183             return "KEY_CRYPT_HUKS_OPENSSL";
1184     }
1185 }
1186 
CombKeyCtx(const KeyBlob & nonce,const KeyBlob & rndEnc,const KeyBlob & aad,KeyBlob & keyOut)1187 bool BaseKey::CombKeyCtx(const KeyBlob &nonce, const KeyBlob &rndEnc, const KeyBlob &aad, KeyBlob &keyOut)
1188 {
1189     LOGI("enter");
1190     if (nonce.IsEmpty() || aad.IsEmpty() || rndEnc.IsEmpty()) {
1191         LOGE("Invalid param, can not combine !");
1192         return false;
1193     }
1194     LOGE("rndEncEnc: %{public}u", rndEnc.size);
1195     std::vector<uint8_t> nonceVct(nonce.data.get(), nonce.data.get() + nonce.size);
1196     std::vector<uint8_t> rndVct(rndEnc.data.get(), rndEnc.data.get() + rndEnc.size);
1197     std::vector<uint8_t> aadVct(aad.data.get(), aad.data.get() + aad.size);
1198 
1199     nonceVct.insert(nonceVct.end(), rndVct.begin(), rndVct.end());
1200     nonceVct.insert(nonceVct.end(), aadVct.begin(), aadVct.end());
1201     std::copy(nonceVct.begin(), nonceVct.end(), keyOut.data.get());
1202     nonceVct.clear();
1203     rndVct.clear();
1204     aadVct.clear();
1205     return true;
1206 }
1207 
SplitKeyCtx(const KeyBlob & keyIn,KeyBlob & nonce,KeyBlob & rndEnc,KeyBlob & aad)1208 bool BaseKey::SplitKeyCtx(const KeyBlob &keyIn, KeyBlob &nonce, KeyBlob &rndEnc, KeyBlob &aad)
1209 {
1210     LOGI("enter");
1211     if (keyIn.size < (nonce.size + aad.size)) {
1212         LOGE("Invalid keyIn size is too small");
1213         return false;
1214     }
1215     std::vector<uint8_t> keyInVct(keyIn.data.get(), keyIn.data.get() + keyIn.size);
1216     rndEnc.Alloc(keyIn.size - nonce.size - aad.size);
1217 
1218     std::copy(keyInVct.begin(), keyInVct.begin() + nonce.size, nonce.data.get());
1219     std::copy(keyInVct.begin() + nonce.size, keyInVct.begin() + nonce.size + rndEnc.size, rndEnc.data.get());
1220     std::copy(keyInVct.begin() + nonce.size + rndEnc.size, keyInVct.end(), aad.data.get());
1221     LOGI("rndEncEnc: %{public}u", rndEnc.size);
1222     keyInVct.clear();
1223     return true;
1224 }
1225 
GetTypeFromDir()1226 uint32_t BaseKey::GetTypeFromDir()
1227 {
1228     static const std::vector<std::pair<std::string, uint32_t>> typeStrs = {
1229         {"el1", TYPE_EL1},
1230         {"el2", TYPE_EL2},
1231         {"el3", TYPE_EL3},
1232         {"el4", TYPE_EL4},
1233         {"el5", TYPE_EL5},
1234     };
1235     uint32_t type = TYPE_GLOBAL_EL1; // default to global el1
1236 
1237     // fscrypt key dir is like `/data/foo/bar/el1/100`
1238     auto slashIndex = dir_.rfind('/');
1239     if (slashIndex == std::string::npos) {
1240         LOGE("bad dir %{public}s", dir_.c_str());
1241         return type;
1242     }
1243 
1244     if (slashIndex == 0) {
1245         LOGE("bad dir %{public}s", dir_.c_str());
1246         return type;
1247     }
1248 
1249     slashIndex = dir_.rfind('/', slashIndex - 1);
1250     if (slashIndex == std::string::npos) {
1251         LOGE("bad dir %{public}s", dir_.c_str());
1252         return type;
1253     }
1254 
1255     std::string el = dir_.substr(slashIndex + 1); // el string is like `el1/100`
1256     for (const auto &it : typeStrs) {
1257         if (el.find(it.first) != std::string::npos) {
1258             type = it.second;
1259             break;
1260         }
1261     }
1262     LOGI("el string is %{public}s, parse type %{public}d", el.c_str(), type);
1263     return type;
1264 }
1265 
GetKeyDir()1266 std::string BaseKey::GetKeyDir()
1267 {
1268     uint32_t type = GetTypeFromDir();
1269     switch (type) {
1270         case TYPE_EL1:
1271             return "el1";
1272         case TYPE_EL2:
1273             return "el2";
1274         case TYPE_EL3:
1275             return "el3";
1276         case TYPE_EL4:
1277             return "el4";
1278         case TYPE_EL5:
1279             return "el5";
1280         default:
1281             StorageService::StorageRadar::ReportUserKeyResult("GetKeyDir", 0, 0, "", "dir_=" + dir_);
1282             LOGE("type is error");
1283             return "";
1284     }
1285 }
1286 
GetIdFromDir()1287 uint32_t BaseKey::GetIdFromDir()
1288 {
1289     int userId = USERID_GLOBAL_EL1; // default to global el1
1290 
1291     // fscrypt key dir is like `/data/foo/bar/el1/100`
1292     auto slashIndex = dir_.rfind('/');
1293     if (slashIndex != std::string::npos) {
1294         std::string last = dir_.substr(slashIndex + 1);
1295         (void)OHOS::StrToInt(last, userId);
1296     }
1297 
1298     LOGI("dir_: %{public}s, get userId is %{public}d", dir_.c_str(), userId);
1299     return static_cast<uint32_t>(userId);
1300 }
1301 
KeyDescIsEmpty()1302 bool BaseKey::KeyDescIsEmpty()
1303 {
1304     LOGI("The keyBlob is null? %{public}d", keyInfo_.keyDesc.IsEmpty());
1305     return keyInfo_.keyDesc.IsEmpty();
1306 }
1307 } // namespace StorageDaemon
1308 } // namespace OHOS
1309