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