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