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