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