• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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