1 /*
2 * Copyright (c) 2022-2025 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 "fscrypt_key_v1.h"
17
18 #include <openssl/sha.h>
19 #include <unistd.h>
20 #include <dirent.h>
21 #include <regex>
22
23 #include "file_ex.h"
24 #include "key_backup.h"
25 #include "storage_service_log.h"
26 #include "storage_service_errno.h"
27 #include "utils/file_utils.h"
28 #include "utils/storage_radar.h"
29
30 using namespace OHOS::StorageService;
31 namespace OHOS {
32 namespace StorageDaemon {
33 static const std::string CRYPTO_NAME_PREFIXES[] = {"ext4", "f2fs", "fscrypt"};
34 constexpr uint32_t USER_UNLOCK = 0x2;
35
ActiveKey(const KeyBlob & authToken,uint32_t flag,const std::string & mnt)36 int32_t FscryptKeyV1::ActiveKey(const KeyBlob &authToken, uint32_t flag, const std::string &mnt)
37 {
38 uint32_t elType;
39 (void)mnt;
40 LOGI("enter");
41 int32_t ret = GenerateKeyDesc();
42 if (ret != E_OK) {
43 keyInfo_.key.Clear();
44 LOGE("GenerateKeyDesc failed");
45 return ret;
46 }
47 LOGE("ActiveKey key is empty: %{public}u", keyInfo_.key.IsEmpty());
48 auto startTime = StorageService::StorageRadar::RecordCurrentTime();
49 int errNo = fscryptV1Ext.ActiveKeyExt(flag, keyInfo_.key, elType, authToken);
50 if (errNo != E_OK) {
51 keyInfo_.key.Clear();
52 LOGE("fscryptV1Ext ActiveKeyExtfailed");
53 return errNo;
54 }
55 auto delay = StorageService::StorageRadar::ReportDuration("HUKS: ACTIVE KEY EXT", startTime);
56 LOGI("SD_DURATION: HUKS: ACTIVE KEY EXT: delay time = %{public}s", delay.c_str());
57 startTime = StorageService::StorageRadar::RecordCurrentTime();
58 if (elType == TYPE_EL3 || elType == TYPE_EL4) {
59 uint32_t sdpClass;
60 if (elType == TYPE_EL3) {
61 sdpClass = FSCRYPT_SDP_SECE_CLASS;
62 } else {
63 sdpClass = FSCRYPT_SDP_ECE_CLASS;
64 }
65 int errNo = InstallEceSeceKeyToKeyring(sdpClass);
66 if (errNo != E_OK) {
67 keyInfo_.key.Clear();
68 LOGE("InstallEceSeceKeyToKeyring failed");
69 return errNo;
70 }
71 } else {
72 int errNo = InstallKeyToKeyring();
73 if (errNo != E_OK) {
74 keyInfo_.key.Clear();
75 LOGE("InstallKeyToKeyring failed");
76 return errNo;
77 }
78 }
79 delay = StorageService::StorageRadar::ReportDuration("INSTALL KEY TO KEYRING", startTime);
80 LOGI("SD_DURATION: INSTALL KEY TO KEYRING: delay time = %{public}s", delay.c_str());
81 keyInfo_.key.Clear();
82 LOGI("success");
83 return E_OK;
84 }
85
GenerateAppkey(uint32_t userId,uint32_t hashId,std::string & keyDesc)86 int32_t FscryptKeyV1::GenerateAppkey(uint32_t userId, uint32_t hashId, std::string &keyDesc)
87 {
88 KeyBlob appKey(FBEX_KEYID_SIZE);
89 auto ret = fscryptV1Ext.GenerateAppkey(userId, hashId, appKey.data, appKey.size);
90 if (ret != E_OK) {
91 LOGE("fscryptV1Ext GenerateAppkey failed");
92 return ret;
93 }
94 // The ioctl does not support EL5, return empty character string
95 if (appKey.data.get() == nullptr) {
96 LOGE("appKey.data.get() is nullptr");
97 keyDesc = "";
98 return E_OK;
99 }
100 ret = GenerateAppKeyDesc(appKey);
101 if (ret != E_OK) {
102 LOGE("GenerateAppKeyDesc failed");
103 return ret;
104 }
105 ret = InstallKeyForAppKeyToKeyring(appKey);
106 if (ret != E_OK) {
107 LOGE("InstallKeyForAppKeyToKeyring failed");
108 return ret;
109 }
110 appKey.Clear();
111 keyDesc = keyInfo_.keyDesc.ToString();
112 LOGI("success");
113 return E_OK;
114 }
115
InstallKeyForAppKeyToKeyring(KeyBlob & appKey)116 int32_t FscryptKeyV1::InstallKeyForAppKeyToKeyring(KeyBlob &appKey)
117 {
118 LOGI("InstallKeyForAppKeyToKeyring enter");
119 EncryptAsdpKey fskey;
120 fskey.size = appKey.size;
121 fskey.version = 0;
122 auto err = memcpy_s(fskey.raw, FSCRYPT_MAX_KEY_SIZE, appKey.data.get(), appKey.size);
123 if (err != EOK) {
124 LOGE("memcpy failed ret %{public}d", err);
125 return err;
126 }
127 key_serial_t krid = KeyCtrlSearch(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
128 if (krid < 0) {
129 LOGI("no session keyring for fscrypt");
130 krid = KeyCtrlAddKey("keyring", "fscrypt", KEY_SPEC_SESSION_KEYRING);
131 if (krid < 0) {
132 LOGE("failed to add session keyring");
133 std::string extraData = "keyring cmd=KEY_SPEC_SESSION_KEYRING,errno=" + std::to_string(errno) +
134 ",appKey=" + appKey.ToString();
135 StorageRadar::ReportKeyRingResult("InstallKeyForAppKeyToKeyring::KeyCtrlAddKey", krid, extraData);
136 return E_ADD_SESSION_KEYRING_ERROR;
137 }
138 }
139 for (auto prefix : CRYPTO_NAME_PREFIXES) {
140 std::string keyref = prefix + ":" + keyInfo_.keyDesc.ToString();
141 key_serial_t ks = KeyCtrlAddAppAsdpKey("logon", keyref.c_str(), &fskey, krid);
142 if (ks < 0) {
143 // Addkey failed, need to process the error
144 LOGE("Failed to AddKey, errno %{public}d", errno);
145 }
146 }
147 LOGI("success");
148 return E_OK;
149 }
150
DeleteAppkey(const std::string keyId)151 int32_t FscryptKeyV1::DeleteAppkey(const std::string keyId)
152 {
153 LOGI("DeleteAppkey enter");
154 auto ret = UninstallKeyForAppKeyToKeyring(keyId);
155 if (ret != E_OK) {
156 LOGE("FscryptKeyV1 Delete Appkey2 failed");
157 return ret;
158 }
159 LOGI("success");
160 return E_OK;
161 }
162
UninstallKeyForAppKeyToKeyring(const std::string keyId)163 int32_t FscryptKeyV1::UninstallKeyForAppKeyToKeyring(const std::string keyId)
164 {
165 LOGI("UninstallKeyForAppKeyToKeyring enter");
166 if (keyId.length() == 0) {
167 LOGE("keyId is null, does not need to be installed?");
168 return E_KEY_TYPE_INVALID;
169 }
170 key_serial_t krid = KeyCtrlSearch(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
171 if (krid == -1) {
172 LOGE("Error searching session keyring for fscrypt-provisioning key for fscrypt");
173 std::string extraData = "cmd=KEY_SPEC_SESSION_KEYRING,errno=" + std::to_string(errno) + ",keyId=" + keyId;
174 StorageRadar::ReportKeyRingResult("UninstallKeyForAppKeyToKeyring::KeyCtrlSearch", krid, extraData);
175 return E_SEARCH_SESSION_KEYING_ERROR;
176 }
177 for (auto prefix : CRYPTO_NAME_PREFIXES) {
178 std::string keyref = prefix + ":" + keyId;
179 key_serial_t ks = KeyCtrlSearch(krid, "logon", keyref.c_str(), 0);
180 if (KeyCtrlUnlink(ks, krid) != 0) {
181 LOGE("Failed to unlink key !");
182 }
183 }
184 LOGI("success");
185 return E_OK;
186 }
187
UnlockUserScreen(const KeyBlob & authToken,uint32_t flag,uint32_t sdpClass,const std::string & mnt)188 int32_t FscryptKeyV1::UnlockUserScreen(const KeyBlob &authToken, uint32_t flag,
189 uint32_t sdpClass, const std::string &mnt)
190 {
191 (void)mnt;
192 LOGI("enter");
193 int32_t ret = GenerateKeyDesc();
194 if (ret != E_OK) {
195 keyInfo_.key.Clear();
196 LOGE("GenerateKeyDesc failed");
197 return ret;
198 }
199 LOGI("keyInfo empty: %{public}u:", keyInfo_.key.IsEmpty());
200 ret = fscryptV1Ext.UnlockUserScreenExt(flag, keyInfo_.key.data.get(), keyInfo_.key.size, authToken);
201 if (ret != E_OK) {
202 keyInfo_.key.Clear();
203 LOGE("fscryptV1Ext UnlockUserScreenExtfailed");
204 return ret;
205 }
206 if (sdpClass == FSCRYPT_SDP_ECE_CLASS) {
207 int errNo = InstallEceSeceKeyToKeyring(sdpClass);
208 if (errNo != E_OK) {
209 keyInfo_.key.Clear();
210 LOGE("UnlockUserScreen InstallKeyToKeyring failed");
211 return errNo;
212 }
213 }
214 keyInfo_.key.Clear();
215 LOGI("success");
216 return E_OK;
217 }
218
AddClassE(bool & isNeedEncryptClassE,bool & isSupport,uint32_t status)219 int32_t FscryptKeyV1::AddClassE(bool &isNeedEncryptClassE, bool &isSupport, uint32_t status)
220 {
221 LOGI("AddClassE enter");
222 auto ret = fscryptV1Ext.AddClassE(isNeedEncryptClassE, isSupport, status);
223 if (ret != E_OK) {
224 LOGE("fscryptV1Ext AddClassE failed");
225 return ret;
226 }
227 keyInfo_.keyDesc.Alloc(CRYPTO_KEY_DESC_SIZE);
228 auto err = memset_s(keyInfo_.keyDesc.data.get(), keyInfo_.keyDesc.size, status, CRYPTO_KEY_DESC_SIZE);
229 if (err != 0) {
230 LOGE("memset_s failed ret: %{public}d", err);
231 }
232 LOGW("AddClassE finish");
233 return E_OK;
234 }
235
DeleteClassEPinCode(uint32_t userId)236 int32_t FscryptKeyV1::DeleteClassEPinCode(uint32_t userId)
237 {
238 LOGI("DeleteClassE enter");
239 auto ret = fscryptV1Ext.DeleteClassEPinCode(userId);
240 if (ret != E_OK) {
241 LOGE("fscryptV1Ext DeleteClassE failed");
242 return ret;
243 }
244 LOGW("DeleteClassE finish");
245 return E_OK;
246 }
247
ChangePinCodeClassE(bool & isFbeSupport,uint32_t userId)248 int32_t FscryptKeyV1::ChangePinCodeClassE(bool &isFbeSupport, uint32_t userId)
249 {
250 LOGI("ChangePinCodeClassE enter, userId: %{public}d", userId);
251 auto ret = fscryptV1Ext.ChangePinCodeClassE(userId, isFbeSupport);
252 if (ret != E_OK) {
253 LOGE("fscryptV1Ext ChangePinCodeClassE failed");
254 return ret;
255 }
256 LOGW("ChangePinCodeClassE finish");
257 return E_OK;
258 }
259
UpdateClassEBackUp(uint32_t userId)260 int32_t FscryptKeyV1::UpdateClassEBackUp(uint32_t userId)
261 {
262 LOGI("UpdateClassEBackUp enter, userId: %{public}d", userId);
263 auto ret = fscryptV1Ext.UpdateClassEBackUp(userId);
264 if (ret != E_OK) {
265 LOGE("fscryptV1Ext UpdateClassEBackUp failed, ret=%{public}d", ret);
266 return ret;
267 }
268 LOGW("UpdateClassEBackUp finish");
269 return E_OK;
270 }
271
DoDecryptClassE(const UserAuth & auth,KeyBlob & eSecretFBE,KeyBlob & decryptedKey,bool needSyncCandidate)272 int32_t FscryptKeyV1::DoDecryptClassE(const UserAuth &auth, KeyBlob &eSecretFBE, KeyBlob &decryptedKey,
273 bool needSyncCandidate)
274 {
275 LOGI("enter");
276 auto candidate = GetCandidateDir();
277 if (candidate.empty()) {
278 // no candidate dir, just restore from the latest
279 return KeyBackup::GetInstance().TryRestoreUeceKey(shared_from_this(), auth, eSecretFBE, decryptedKey);
280 }
281 auto ret = DecryptKeyBlob(auth, candidate, eSecretFBE, decryptedKey);
282 if (ret == E_OK) {
283 // update the latest with the candidate
284 UpdateKey("", needSyncCandidate);
285 return E_OK;
286 }
287
288 LOGE("DoRestoreKey with %{public}s failed", candidate.c_str());
289 // try to restore from other versions
290 std::vector<std::string> files;
291 GetSubDirs(dir_, files);
292 std::sort(files.begin(), files.end(), [&](const std::string &a, const std::string &b) {
293 if (a.length() != b.length() ||
294 a.length() < strlen(PATH_KEY_VERSION) ||
295 b.length() < strlen(PATH_KEY_VERSION)) {
296 return a.length() > b.length();
297 }
298 std::regex pattern("^version_\\d+$");
299 if (!std::regex_search(a, pattern)) return false;
300 if (!std::regex_search(b, pattern)) return true;
301
302 // make sure a and b is version_\d+
303 auto a_len = std::atoi(a.substr(strlen(PATH_KEY_VERSION) - 1).c_str());
304 auto b_len = std::atoi(b.substr(strlen(PATH_KEY_VERSION) - 1).c_str());
305 return a_len > b_len;
306 });
307 for (const auto &it: files) {
308 if (it != candidate) {
309 auto ret = DecryptKeyBlob(auth, dir_ + "/" + it, eSecretFBE, decryptedKey);
310 if (ret == E_OK) {
311 UpdateKey((dir_ + "/" + it), needSyncCandidate);
312 return E_OK;
313 }
314 }
315 }
316 return ret;
317 }
318
DecryptClassE(const UserAuth & auth,bool & isSupport,bool & eBufferStatue,uint32_t user,bool needSyncCandidate)319 int32_t FscryptKeyV1::DecryptClassE(const UserAuth &auth, bool &isSupport, bool &eBufferStatue,
320 uint32_t user, bool needSyncCandidate)
321 {
322 LOGI("enter");
323 KeyBlob eSecretFBE(AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES);
324 bool isFbeSupport = true;
325 auto authToken = auth.token;
326 auto ret = fscryptV1Ext.ReadClassE(USER_UNLOCK, eSecretFBE, authToken, isFbeSupport);
327 if (ret != E_OK) {
328 LOGE("fscryptV1Ext ReadClassE failed");
329 return ret;
330 }
331 if ((auth.token.IsEmpty() && auth.secret.IsEmpty()) || eSecretFBE.IsEmpty()) {
332 LOGE("Token and secret is invalid, do not deal.");
333 eBufferStatue = eSecretFBE.IsEmpty();
334 eSecretFBE.Clear();
335 return E_OK;
336 }
337 if (!isFbeSupport) {
338 LOGE("fbe not support uece, skip!");
339 isSupport = false;
340 return E_OK;
341 }
342 LOGI("Decrypt keyPath is %{public}s", (dir_ + PATH_LATEST).c_str());
343 KeyBlob decryptedKey(AES_256_HASH_RANDOM_SIZE);
344 ret = DoDecryptClassE(auth, eSecretFBE, decryptedKey, needSyncCandidate);
345 if (ret != E_OK) {
346 LOGE("DecryptKeyBlob Decrypt failed");
347 eSecretFBE.Clear();
348 return ret;
349 }
350 keyInfo_.key.Alloc(eSecretFBE.size);
351 auto err = memcpy_s(keyInfo_.key.data.get(), keyInfo_.key.size, eSecretFBE.data.get(), eSecretFBE.size);
352 if (err != 0) {
353 LOGE("memcpy_s failed ret: %{public}d", err);
354 }
355 eSecretFBE.Clear();
356 LOGI("Decrypt end!");
357 ret = fscryptV1Ext.WriteClassE(USER_UNLOCK, decryptedKey.data.get(), decryptedKey.size);
358 if (ret != E_OK) {
359 LOGE("fscryptV1Ext WriteClassE failed");
360 return ret;
361 }
362 GenerateKeyDesc();
363 keyInfo_.key.Clear();
364 decryptedKey.Clear();
365 LOGI("finish");
366 return E_OK;
367 }
368
EncryptClassE(const UserAuth & auth,bool & isSupport,uint32_t user,uint32_t status)369 int32_t FscryptKeyV1::EncryptClassE(const UserAuth &auth, bool &isSupport, uint32_t user, uint32_t status)
370 {
371 LOGI("enter");
372 KeyBlob eSecretFBE(AES_256_HASH_RANDOM_SIZE);
373 bool isFbeSupport = true;
374 auto authToken = auth.token;
375 auto ret = fscryptV1Ext.ReadClassE(status, eSecretFBE, authToken, isFbeSupport);
376 if (ret != E_OK) {
377 LOGE("fscryptV1Ext ReadClassE failed");
378 return ret;
379 }
380 if (!isFbeSupport) {
381 LOGE("fbe not support E type, skip!");
382 isSupport = false;
383 return E_OK;
384 }
385 KeyBlob encryptedKey(AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES);
386 ret = EncryptKeyBlob(auth, dir_ + PATH_LATEST, eSecretFBE, encryptedKey);
387 if (ret != E_OK) {
388 LOGE("EncryptKeyBlob Decrypt failed");
389 eSecretFBE.Clear();
390 return ret;
391 }
392 eSecretFBE.Clear();
393 if (!RenameKeyPath(dir_ + PATH_LATEST)) {
394 LOGE("RenameKeyPath failed");
395 return E_RENAME_KEY_PATH;
396 }
397 LOGI("encrypt end");
398 ret = fscryptV1Ext.WriteClassE(status, encryptedKey.data.get(), encryptedKey.size);
399 if (ret != E_OK) {
400 LOGE("fscryptV1Ext WriteClassE failed");
401 return ret;
402 }
403 encryptedKey.Clear();
404 LOGI("finish");
405 return E_OK;
406 }
407
InstallKeyToKeyring()408 int32_t FscryptKeyV1::InstallKeyToKeyring()
409 {
410 fscrypt_key fskey;
411 fskey.mode = FS_ENCRYPTION_MODE_AES_256_XTS;
412 fskey.size = keyInfo_.key.size;
413 auto err = memcpy_s(fskey.raw, FS_MAX_KEY_SIZE, keyInfo_.key.data.get(), keyInfo_.key.size);
414 if (err != EOK) {
415 LOGE("memcpy failed ret %{public}d", err);
416 return err;
417 }
418
419 key_serial_t krid = KeyCtrlSearch(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
420 if (krid == -1) {
421 LOGI("no session keyring for fscrypt");
422 krid = KeyCtrlAddKey("keyring", "fscrypt", KEY_SPEC_SESSION_KEYRING);
423 if (krid == -1) {
424 LOGE("failed to add session keyring");
425 std::string extraData = "cmd=KEY_SPEC_SESSION_KEYRING,errno=" + std::to_string(errno);
426 StorageRadar::ReportKeyRingResult("InstallKeyToKeyring::KeyCtrlAddKey", krid, extraData);
427 return E_ADD_SESSION_KEYRING_ERROR;
428 }
429 }
430 for (auto prefix : CRYPTO_NAME_PREFIXES) {
431 std::string keyref = prefix + ":" + keyInfo_.keyDesc.ToString();
432 key_serial_t ks =
433 KeyCtrlAddKeyEx("logon", keyref.c_str(), &fskey, krid);
434 if (ks == -1) {
435 // Addkey failed, need to process the error
436 LOGE("Failed to AddKey into keyring, errno %{public}d", errno);
437 }
438 }
439 if (!SaveKeyBlob(keyInfo_.keyDesc, dir_ + PATH_KEYDESC)) {
440 return E_SAVE_KEY_BLOB_ERROR;
441 }
442 keyInfo_.key.Clear();
443 LOGW("success");
444 return E_OK;
445 }
446
InstallEceSeceKeyToKeyring(uint32_t sdpClass)447 int32_t FscryptKeyV1::InstallEceSeceKeyToKeyring(uint32_t sdpClass)
448 {
449 EncryptionKeySdp fskey;
450 if (keyInfo_.key.size != sizeof(fskey.raw)) {
451 LOGE("Wrong key size is %{public}d", keyInfo_.key.size);
452 return E_KEY_SIZE_ERROR;
453 }
454 fskey.mode = EXT4_ENCRYPTION_MODE_AES_256_XTS;
455 auto err = memcpy_s(fskey.raw, sizeof(fskey.raw), keyInfo_.key.data.get(), keyInfo_.key.size);
456 if (err != EOK) {
457 LOGE("memcpy failed ret %{public}d", err);
458 return err;
459 }
460 fskey.size = EXT4_AES_256_XTS_KEY_SIZE_TO_KEYRING;
461 fskey.sdpClass = sdpClass;
462 fskey.version = 0;
463 key_serial_t krid = KeyCtrlSearch(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
464 if (krid == -1) {
465 LOGI("no session keyring for fscrypt");
466 krid = KeyCtrlAddKey("keyring", "fscrypt", KEY_SPEC_SESSION_KEYRING);
467 if (krid == -1) {
468 LOGE("failed to add session keyring");
469 std::string extraData = "cmd=KEY_SPEC_SESSION_KEYRING,errno=" + std::to_string(errno) +
470 ",sdpClass=" + std::to_string(sdpClass);
471 StorageRadar::ReportKeyRingResult("InstallEceSeceKeyToKeyring::KeyCtrlAddKey", krid, extraData);
472 return E_ADD_SESSION_KEYRING_ERROR;
473 }
474 }
475 for (auto prefix : CRYPTO_NAME_PREFIXES) {
476 std::string keyref = prefix + ":" + keyInfo_.keyDesc.ToString();
477 key_serial_t ks =
478 KeyCtrlAddKeySdp("logon", keyref.c_str(), &fskey, krid);
479 if (ks == -1) {
480 // Addkey failed, need to process the error
481 LOGE("Failed to AddKey into keyring, errno %{public}d", errno);
482 }
483 }
484 if (!SaveKeyBlob(keyInfo_.keyDesc, dir_ + PATH_KEYDESC)) {
485 return E_SAVE_KEY_BLOB_ERROR;
486 }
487 LOGW("success");
488 return E_OK;
489 }
490
InactiveKey(uint32_t flag,const std::string & mnt)491 int32_t FscryptKeyV1::InactiveKey(uint32_t flag, const std::string &mnt)
492 {
493 (void)mnt;
494 LOGI("enter");
495 auto startTime = StorageService::StorageRadar::RecordCurrentTime();
496 DropCachesIfNeed();
497 auto delay = StorageService::StorageRadar::ReportDuration("DROP CACHE", startTime,
498 StorageService::DELAY_TIME_THRESH_HIGH, StorageService::DEFAULT_USERID);
499 LOGI("SD_DURATION: DROP CACHE: delay time = %{public}s", delay.c_str());
500
501 int32_t ret = E_OK;
502 if (!keyInfo_.keyDesc.IsEmpty()) {
503 int errNo = UninstallKeyToKeyring();
504 if (errNo != E_OK) {
505 LOGE("UninstallKeyToKeyring failed");
506 ret = errNo;
507 }
508 }
509 ret = fscryptV1Ext.InactiveKeyExt(flag);
510 if (ret != E_OK) {
511 LOGE("fscryptV1Ext InactiveKeyExt failed");
512 return ret;
513 }
514 startTime = StorageService::StorageRadar::RecordCurrentTime();
515 DropCachesIfNeed();
516 delay = StorageService::StorageRadar::ReportDuration("DROP CACHE", startTime,
517 StorageService::DELAY_TIME_THRESH_HIGH, StorageService::DEFAULT_USERID);
518 LOGI("finish. SD_DURATION: DROP CACHE: delay time = %{public}s", delay.c_str());
519 return ret;
520 }
521
DropCachesIfNeed()522 void FscryptKeyV1::DropCachesIfNeed()
523 {
524 LOGE("drop cache if need enter");
525 DIR *dir = opendir(MNT_DATA);
526 if (dir == nullptr) {
527 sync();
528 }
529 int fd = dirfd(dir);
530 LOGE("open /data dir fd success, syncfs start");
531 if (fd < 0 || syncfs(fd)) {
532 LOGE("fd < 0 or syncfs failed, sync start");
533 sync();
534 LOGE("sync success with syncfs failed.");
535 }
536 LOGE("syncfs success, drop cache start.");
537 if (!SaveStringToFile("/proc/sys/vm/drop_caches", "2")) {
538 LOGE("Failed to drop cache during key eviction");
539 }
540 (void)closedir(dir);
541 LOGE("drop cache success");
542 }
543
LockUserScreen(uint32_t flag,uint32_t sdpClass,const std::string & mnt)544 int32_t FscryptKeyV1::LockUserScreen(uint32_t flag, uint32_t sdpClass, const std::string &mnt)
545 {
546 LOGI("enter FscryptKeyV1::LockUserScreen");
547 // uninstall KeyRing
548 int errNo = UninstallKeyToKeyring();
549 if (errNo != E_OK) {
550 LOGE("UninstallKeyToKeyring failed");
551 return errNo;
552 }
553
554 // uninstall FBE
555 uint32_t elType;
556 int32_t ret = fscryptV1Ext.LockUserScreenExt(flag, elType);
557 if (ret != E_OK) {
558 LOGE("fscryptV1Ext InactiveKeyExt failed");
559 return ret;
560 }
561 LOGI("finish FscryptKeyV1::LockUserScreen");
562 return E_OK;
563 }
564
LockUece(bool & isFbeSupport)565 int32_t FscryptKeyV1::LockUece(bool &isFbeSupport)
566 {
567 LOGD("FscryptKeyV1::LockUece enter");
568 int32_t ret = fscryptV1Ext.LockUeceExt(isFbeSupport);
569 if (ret != E_OK) {
570 LOGE("fscryptV1Ext InactiveKeyExt failed");
571 return ret;
572 }
573 LOGI("FscryptKeyV1::LockUece finish");
574 return ret;
575 }
576
UninstallKeyToKeyring()577 int32_t FscryptKeyV1::UninstallKeyToKeyring()
578 {
579 if (keyInfo_.keyDesc.IsEmpty() && !LoadKeyBlob(keyInfo_.keyDesc, dir_ + PATH_KEYDESC)) {
580 LOGE("Load keyDesc failed !");
581 return E_KEY_LOAD_ERROR;
582 }
583 if (keyInfo_.keyDesc.IsEmpty()) {
584 DropCachesIfNeed();
585 LOGE("keyDesc is null, key not installed?");
586 return E_KEY_EMPTY_ERROR;
587 }
588
589 key_serial_t krid = KeyCtrlSearch(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
590 if (krid == -1) {
591 LOGE("Error searching session keyring for fscrypt-provisioning key for fscrypt");
592 std::string extraData = "cmd=KEY_SPEC_SESSION_KEYRING,errno=" + std::to_string(errno);
593 StorageRadar::ReportKeyRingResult("UninstallKeyToKeyring::KeyCtrlSearch", krid, extraData);
594 return E_SEARCH_SESSION_KEYING_ERROR;
595 }
596 for (auto prefix : CRYPTO_NAME_PREFIXES) {
597 std::string keyref = prefix + ":" + keyInfo_.keyDesc.ToString();
598 key_serial_t ks = KeyCtrlSearch(krid, "logon", keyref.c_str(), 0);
599 if (KeyCtrlUnlink(ks, krid) != 0) {
600 LOGE("Failed to unlink key !");
601 }
602 }
603
604 LOGW("success");
605 return E_OK;
606 }
607
GenerateKeyDesc()608 int32_t FscryptKeyV1::GenerateKeyDesc()
609 {
610 if (keyInfo_.key.IsEmpty()) {
611 LOGE("key is empty");
612 return E_KEY_EMPTY_ERROR;
613 }
614 SHA512_CTX c;
615
616 SHA512_Init(&c);
617 SHA512_Update(&c, keyInfo_.key.data.get(), keyInfo_.key.size);
618 uint8_t keyRef1[SHA512_DIGEST_LENGTH] = { 0 };
619 SHA512_Final(keyRef1, &c);
620
621 SHA512_Init(&c);
622 SHA512_Update(&c, keyRef1, SHA512_DIGEST_LENGTH);
623 uint8_t keyRef2[SHA512_DIGEST_LENGTH] = { 0 };
624 SHA512_Final(keyRef2, &c);
625
626 static_assert(SHA512_DIGEST_LENGTH >= CRYPTO_KEY_DESC_SIZE, "Hash too short for descriptor");
627 keyInfo_.keyDesc.Alloc(CRYPTO_KEY_DESC_SIZE);
628 auto err = memcpy_s(keyInfo_.keyDesc.data.get(), keyInfo_.keyDesc.size, keyRef2, CRYPTO_KEY_DESC_SIZE);
629 if (err != EOK) {
630 LOGE("memcpy failed ret %{public}d", err);
631 return err;
632 }
633 return E_OK;
634 }
635
GenerateAppKeyDesc(KeyBlob appKey)636 int32_t FscryptKeyV1::GenerateAppKeyDesc(KeyBlob appKey)
637 {
638 if (appKey.IsEmpty()) {
639 LOGE("key is empty");
640 return E_KEY_EMPTY_ERROR;
641 }
642 SHA512_CTX c;
643 SHA512_Init(&c);
644 SHA512_Update(&c, appKey.data.get(), appKey.size - 1);
645 uint8_t keyRef1[SHA512_DIGEST_LENGTH] = { 0 };
646 SHA512_Final(keyRef1, &c);
647
648 SHA512_Init(&c);
649 SHA512_Update(&c, keyRef1, SHA512_DIGEST_LENGTH);
650 uint8_t keyRef2[SHA512_DIGEST_LENGTH] = { 0 };
651 SHA512_Final(keyRef2, &c);
652
653 static_assert(SHA512_DIGEST_LENGTH >= CRYPTO_KEY_DESC_SIZE, "Hash too short for descriptor");
654 keyInfo_.keyDesc.Alloc(CRYPTO_KEY_DESC_SIZE);
655 auto err = memcpy_s(keyInfo_.keyDesc.data.get(), keyInfo_.keyDesc.size, keyRef2, CRYPTO_KEY_DESC_SIZE);
656 if (err != EOK) {
657 LOGE("memcpy failed ret %{public}d", err);
658 return err;
659 }
660 LOGE("GenerateAppKeyDesc keyDesc : %{private}s", keyInfo_.keyDesc.ToString().c_str());
661 return E_OK;
662 }
663 } // namespace StorageDaemon
664 } // namespace OHOS
665