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