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