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