• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-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 "recover_manager.h"
17 
18 #include <bitset>
19 #include <openssl/sha.h>
20 #include <unistd.h>
21 #include "key_manager_ext.h"
22 #include "storage_service_errno.h"
23 #include "storage_service_log.h"
24 #include "utils/storage_radar.h"
25 
26 using namespace OHOS::StorageService;
27 namespace OHOS {
28 namespace StorageDaemon {
29 static const std::string CRYPTO_NAME_PREFIXES[] = {"ext4", "f2fs", "fscrypt"};
30 #ifdef RECOVER_KEY_TEE_ENVIRONMENT
31 constexpr uint32_t ELX_TYPE_ARR[] = { TYPE_GLOBAL_EL1, USERID_GLOBAL_EL1, TYPE_EL1, TYPE_EL2, TYPE_EL3, TYPE_EL4 };
32 constexpr static uint32_t TEE_PARAM_INDEX_0 = 0;
33 constexpr static uint32_t TEE_PARAM_INDEX_1 = 1;
34 constexpr static uint32_t TEE_PARAM_INDEX_2 = 2;
35 constexpr static int SESSION_START_DEFAULT = 1;
36 constexpr int MAX_RETRY_COUNT = 3;
37 constexpr int RETRY_INTERVAL = 100 * 1000; // 100ms
38 constexpr static uint32_t RECOVERY_USER_ID = 300;
39 #endif
40 
RecoveryManager()41 RecoveryManager::RecoveryManager()
42 {
43     LOGI("enter");
44     isSessionOpened = false;
45 }
46 
~RecoveryManager()47 RecoveryManager::~RecoveryManager()
48 {
49     LOGI("enter");
50 }
51 
IsEncryptionEnabled()52 bool RecoveryManager::IsEncryptionEnabled()
53 {
54     LOGI("enter");
55 #ifdef RECOVER_KEY_TEE_ENVIRONMENT
56     TEEC_Context createKeyContext = {};
57     TEEC_Session createKeySession = {};
58     if (!OpenSession(createKeyContext, createKeySession)) {
59         LOGE("Open session failed !");
60         return true;
61     }
62 
63     TEEC_Operation operation = { 0 };
64     operation.started = SESSION_START_DEFAULT;
65     operation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
66     operation.params[TEE_PARAM_INDEX_0].value.a = 1;
67 
68     uint32_t origin = 0;
69     TEEC_Result result = TEEC_InvokeCommand(&createKeySession, TaCmdId::RK_CMD_ID_GET_FULL_DISK_ENCRYPTION_POLICY,
70                                             &operation, &origin);
71     LOGI("InvokeCmd ret: %{public}d, origin: %{public}d", result, origin);
72     if (result != TEEC_SUCCESS) {
73         LOGE("InvokeCmd failed, ret: %{public}d, origin: %{public}d", result, origin);
74         CloseSession(createKeyContext, createKeySession);
75         std::string extraData = "cmd=RK_CMD_ID_GET_FULL_DISK_ENCRYPTION_POLICY,ret=" + std::to_string(result) +
76             ",origin=" + std::to_string(origin);
77         StorageRadar::ReportTEEClientResult("TEEC_InvokeCommand", E_TEEC_GEN_RECOVERY_KEY_ERR, 0, extraData);
78         return true;
79     }
80     CloseSession(createKeyContext, createKeySession);
81 
82     auto policy = std::bitset<sizeof(uint32_t)>(operation.params[TEE_PARAM_INDEX_0].value.a);
83     return policy.test(0);
84 #endif
85     LOGI("success");
86     return true;
87 }
88 
CreateRecoverKey(uint32_t userId,uint32_t userType,const std::vector<uint8_t> & token,const std::vector<uint8_t> & secret,const std::vector<KeyBlob> & originIv)89 int RecoveryManager::CreateRecoverKey(uint32_t userId,
90                                       uint32_t userType,
91                                       const std::vector<uint8_t> &token,
92                                       const std::vector<uint8_t> &secret,
93                                       const std::vector<KeyBlob> &originIv)
94 {
95     LOGI("enter");
96 #ifdef RECOVER_KEY_TEE_ENVIRONMENT
97     TEEC_Context createKeyContext = {};
98     TEEC_Session createKeySession = {};
99     if (!OpenSession(createKeyContext, createKeySession)) {
100         LOGE("Open session failed !");
101         return E_RECOVERY_KEY_OPEN_SESSION_ERR;
102     }
103     uint32_t createKeyOrigin = 0;
104     TEEC_Operation operation = { 0 };
105     operation.started = SESSION_START_DEFAULT;
106     operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
107     CreateRecoverKeyStr recoverKeyStr = { .userType = userType, .userId = userId,
108                                           .authTokenLen = static_cast<uint32_t>(token.size()) };
109     if (!token.empty()) {
110         auto err = memcpy_s(recoverKeyStr.authToken, AUTH_TOKEN_LEN, token.data(), token.size());
111         if (err != EOK) {
112             CloseSession(createKeyContext, createKeySession);
113             return E_MEMORY_OPERATION_ERR;
114         }
115     }
116     for (size_t i = 0; i < originIv.size(); ++i) {
117         auto err = memcpy_s(recoverKeyStr.rndToTee[i], RND_AND_KEY2_LEN, originIv[i].data.get(), originIv[i].size);
118         if (err != EOK) {
119             CloseSession(createKeyContext, createKeySession);
120             return E_MEMORY_OPERATION_ERR;
121         }
122     }
123     auto startTime = StorageService::StorageRadar::RecordCurrentTime();
124     operation.params[TEE_PARAM_INDEX_0].tmpref.buffer = static_cast<void *>(&recoverKeyStr);
125     operation.params[TEE_PARAM_INDEX_0].tmpref.size = sizeof(recoverKeyStr);
126     TEEC_Result ret = TEEC_InvokeCommand(&createKeySession, TaCmdId::RK_CMD_ID_GEN_RECOVERY_KEY,
127                                          &operation, &createKeyOrigin);
128     LOGW("SD_DURATION: InvokeCmd ret: %{public}d, origin: %{public}d, token size: %{public}zu, delay = %{public}s",
129         ret, createKeyOrigin, token.size(), StorageService::StorageRadar::ReportDuration("CREATE RECOVERY KEY",
130         startTime, StorageService::DELAY_TIME_THRESH_HIGH, userId).c_str());
131     if (ret != TEEC_SUCCESS) {
132         LOGE("InvokeCmd failed, ret: %{public}d, origin: %{public}d", ret, createKeyOrigin);
133         CloseSession(createKeyContext, createKeySession);
134         std::string extraData = "cmd=RK_CMD_ID_GEN_RECOVERY_KEY,ret=" + std::to_string(ret) +
135             ",origin=" + std::to_string(createKeyOrigin);
136         StorageRadar::ReportTEEClientResult("TEEC_InvokeCommand", E_TEEC_GEN_RECOVERY_KEY_ERR, userId, extraData);
137         return E_TEEC_GEN_RECOVERY_KEY_ERR;
138     }
139     CloseSession(createKeyContext, createKeySession);
140 #endif
141     LOGI("success");
142     return 0;
143 }
144 
SetRecoverKey(const std::vector<uint8_t> & key)145 int RecoveryManager::SetRecoverKey(const std::vector<uint8_t> &key)
146 {
147 #ifdef RECOVER_KEY_TEE_ENVIRONMENT
148     SetRecoverKeyStr setRecoverKeyStr;
149     int ret = SetRecoverKeyToTee(key, setRecoverKeyStr);
150     if (ret != 0) {
151         LOGE("Set recover key to tee failed !");
152         return ret;
153     }
154     if (sizeof(setRecoverKeyStr.key2FromTee) != sizeof(setRecoverKeyStr.rndFromTee)) {
155         LOGE("key2 size dose not match iv size !");
156         return E_PARAMS_INVALID;
157     }
158     int rndNum = sizeof(setRecoverKeyStr.rndFromTee) / RND_AND_KEY2_LEN;
159     int key2Num = sizeof(setRecoverKeyStr.key2FromTee) / RND_AND_KEY2_LEN;
160     if (rndNum != RND_AND_KEY2_NUMS || key2Num != RND_AND_KEY2_NUMS) {
161         LOGE("rnd and key2 num is not match ! rndNum: %{public}d, key2Num: %{public}d", rndNum, key2Num);
162         return E_PARAMS_INVALID;
163     }
164 
165     for (int i = 0; i < rndNum; ++i) {
166         uint8_t *key2 = setRecoverKeyStr.key2FromTee[i];
167         uint8_t *originIv = setRecoverKeyStr.rndFromTee[i];
168         std::vector<uint8_t> key2Data(key2, key2 + RND_AND_KEY2_LEN);
169         std::vector<uint8_t> ivData(originIv, originIv + RND_AND_KEY2_LEN);
170         KeyBlob ivBlob(ivData);
171         KeyBlob key2Blob(key2Data);
172         KeyBlob keyDesc;
173         auto errNo = GenerateKeyDesc(ivBlob, keyDesc);
174         if (errNo != E_OK) {
175             LOGE("Generate key desc failed !");
176             return errNo;
177         }
178         auto startTime = StorageService::StorageRadar::RecordCurrentTime();
179         ret = InstallKeyDescToKeyring(ELX_TYPE_ARR[i], key2Blob, keyDesc);
180         if (ret != E_OK) {
181             ivBlob.Clear();
182             keyDesc.Clear();
183             key2Blob.Clear();
184             LOGE("install type %{public}d to keyring failed !", ELX_TYPE_ARR[i]);
185             return ret;
186         }
187         (void)KeyManagerExt::GetInstance().SetRecoverKey(RECOVERY_USER_ID, ELX_TYPE_ARR[i], ivBlob);
188         auto delay = StorageService::StorageRadar::ReportDuration("INSTALL KEY DESC TO KEYRING", startTime);
189         LOGI("SD_DURATION: INSTALL KEY DESC TO KEYRING, delayTime = %{public}s", delay.c_str());
190         ivBlob.Clear();
191         keyDesc.Clear();
192         key2Blob.Clear();
193     }
194 #endif
195     return 0;
196 }
197 
SetRecoverKeyToTee(const std::vector<uint8_t> & key,SetRecoverKeyStr & setRecoverKeyStr)198 int RecoveryManager::SetRecoverKeyToTee(const std::vector<uint8_t> &key, SetRecoverKeyStr &setRecoverKeyStr)
199 {
200     LOGI("enter");
201 #ifdef RECOVER_KEY_TEE_ENVIRONMENT
202     TEEC_Context setKeyContext = {};
203     TEEC_Session setKeySession = {};
204     if (!OpenSession(setKeyContext, setKeySession)) {
205         LOGE("Open session failed !");
206         return E_RECOVERY_KEY_OPEN_SESSION_ERR;
207     }
208     auto startTime = StorageService::StorageRadar::RecordCurrentTime();
209     TEEC_Operation operation = { 0 };
210     operation.started = SESSION_START_DEFAULT;
211     operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE);
212     uint32_t setKeyOrigin;
213     operation.params[TEE_PARAM_INDEX_0].tmpref.buffer = static_cast<void *>(const_cast<unsigned char *>(key.data()));
214     operation.params[TEE_PARAM_INDEX_0].tmpref.size = key.size();
215     operation.params[TEE_PARAM_INDEX_1].tmpref.buffer = static_cast<void *>(&setRecoverKeyStr);
216     operation.params[TEE_PARAM_INDEX_1].tmpref.size = sizeof(setRecoverKeyStr);
217     TEEC_Result ret = TEEC_InvokeCommand(&setKeySession, TaCmdId::RK_CMD_ID_DECRYPT_CLASS_KEY, &operation,
218                                          &setKeyOrigin);
219     LOGI("InvokeCmd ret: %{public}d, origin: %{public}d", ret, setKeyOrigin);
220     if (ret != TEEC_SUCCESS) {
221         LOGE("InvokeCmd failed, ret: %{public}d, origin: %{public}d", ret, setKeyOrigin);
222         CloseSession(setKeyContext, setKeySession);
223         std::string extraData = "cmd=RK_CMD_ID_DECRYPT_CLASS_KEY,ret=" + std::to_string(ret) +
224             ",origin=" + std::to_string(setKeyOrigin);
225         StorageRadar::ReportTEEClientResult("SetRecoverKeyToTee::TEEC_InvokeCommand", E_TEEC_DECRYPT_CLASS_KEY_ERR,
226             DEFAULT_USERID, extraData);
227         return E_TEEC_DECRYPT_CLASS_KEY_ERR;
228     }
229     auto delay = StorageService::StorageRadar::ReportDuration("SET RECOVERY KEY",
230         startTime, StorageService::DELAY_TIME_THRESH_HIGH, StorageService::DEFAULT_USERID);
231     LOGI("SD_DURATION: SET RECOVERY KEY, delayTime = %{public}s", delay.c_str());
232     CloseSession(setKeyContext, setKeySession);
233 #endif
234     return 0;
235 }
236 
ResetSecretWithRecoveryKey(uint32_t userId,uint32_t rkType,const std::vector<uint8_t> & key,std::vector<KeyBlob> & originIvs)237 int32_t RecoveryManager::ResetSecretWithRecoveryKey(uint32_t userId, uint32_t rkType,
238     const std::vector<uint8_t> &key, std::vector<KeyBlob> &originIvs)
239 {
240     LOGI("reset secret userId: %{public}d", userId);
241 #ifdef RECOVER_KEY_TEE_ENVIRONMENT
242     SetRecoverKeyStr setRecoverKeyStr;
243     int ret = ResetSecretWithRecoveryKeyToTee(userId, rkType, key, setRecoverKeyStr);
244     if (ret != 0) {
245         LOGE("Set recover key to tee failed !");
246         return ret;
247     }
248 
249     if (sizeof(setRecoverKeyStr.key2FromTee) != sizeof(setRecoverKeyStr.rndFromTee)) {
250         LOGE("key2 size dose not match iv size !");
251         return E_PARAMS_INVALID;
252     }
253     int rndNum = sizeof(setRecoverKeyStr.rndFromTee) / RND_AND_KEY2_LEN;
254     int key2Num = sizeof(setRecoverKeyStr.key2FromTee) / RND_AND_KEY2_LEN;
255     if (rndNum != RND_AND_KEY2_NUMS || key2Num != RND_AND_KEY2_NUMS) {
256         LOGE("rnd and key2 num is not match ! rndNum: %{public}d, key2Num: %{public}d", rndNum, key2Num);
257         return E_PARAMS_INVALID;
258     }
259 
260     for (int i = 0; i < rndNum; ++i) {
261         uint8_t *key2 = setRecoverKeyStr.key2FromTee[i];
262         uint8_t *originIv = setRecoverKeyStr.rndFromTee[i];
263         std::vector<uint8_t> key2Data(key2, key2 + RND_AND_KEY2_LEN);
264         std::vector<uint8_t> ivData(originIv, originIv + RND_AND_KEY2_LEN);
265         KeyBlob ivBlob(ivData);
266         KeyBlob key2Blob(key2Data);
267         KeyBlob keyDesc;
268         auto errNo = GenerateKeyDesc(ivBlob, keyDesc);
269         if (errNo != E_OK) {
270             LOGE("Generate key desc failed !");
271             return errNo;
272         }
273         auto startTime = StorageService::StorageRadar::RecordCurrentTime();
274         ret = InstallKeyDescToKeyring(ELX_TYPE_ARR[i], key2Blob, keyDesc);
275         if (ret != E_OK) {
276             LOGE("install type %{public}d to keyring failed !", ELX_TYPE_ARR[i]);
277             return ret;
278         }
279         (void)KeyManagerExt::GetInstance().SetRecoverKey(userId, ELX_TYPE_ARR[i], ivBlob);
280         auto delay = StorageService::StorageRadar::ReportDuration("INSTALL KEY DESC TO KEYRING",
281             startTime, StorageService::DEFAULT_DELAY_TIME_THRESH, userId);
282         LOGI("SD_DURATION: INSTALL KEY DESC TO KEYRING, delayTime = %{public}s", delay.c_str());
283         originIvs.emplace_back(ivBlob);
284     }
285 #endif
286     return E_OK;
287 }
288 
ResetSecretWithRecoveryKeyToTee(uint32_t userId,uint32_t rkType,const std::vector<uint8_t> & key,SetRecoverKeyStr & setRecoverKeyStr)289 int32_t RecoveryManager::ResetSecretWithRecoveryKeyToTee(uint32_t userId, uint32_t rkType,
290     const std::vector<uint8_t> &key, SetRecoverKeyStr &setRecoverKeyStr)
291 {
292     LOGI("reset secret with recovery key");
293 #ifdef RECOVER_KEY_TEE_ENVIRONMENT
294     TEEC_Context setKeyContext = {};
295     TEEC_Session setKeySession = {};
296     if (!OpenSession(setKeyContext, setKeySession)) {
297         LOGE("Open session failed !");
298         return E_RECOVERY_KEY_OPEN_SESSION_ERR;
299     }
300 
301     auto startTime = StorageService::StorageRadar::RecordCurrentTime();
302     TEEC_Operation operation = { 0 };
303     operation.started = SESSION_START_DEFAULT;
304     operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
305         TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE);
306     uint32_t setKeyOrigin;
307     operation.params[TEE_PARAM_INDEX_0].tmpref.buffer = static_cast<void *>(const_cast<unsigned char *>(key.data()));
308     operation.params[TEE_PARAM_INDEX_0].tmpref.size = key.size();
309     operation.params[TEE_PARAM_INDEX_1].value.a = userId;
310     operation.params[TEE_PARAM_INDEX_1].value.b = rkType;
311     operation.params[TEE_PARAM_INDEX_2].tmpref.buffer = static_cast<void *>(&setRecoverKeyStr);
312     operation.params[TEE_PARAM_INDEX_2].tmpref.size = sizeof(setRecoverKeyStr);
313     TEEC_Result ret = TEEC_InvokeCommand(&setKeySession, TaCmdId::RK_CMD_ID_SET_RK_FOR_PLUGGED_IN_SSD, &operation,
314                                          &setKeyOrigin);
315     LOGI("InvokeCmd ret: %{public}d, origin: %{public}d", ret, setKeyOrigin);
316     if (ret != TEEC_SUCCESS) {
317         LOGE("InvokeCmd failed, ret: %{public}d, origin: %{public}d", ret, setKeyOrigin);
318         CloseSession(setKeyContext, setKeySession);
319         std::string extraData = "cmd=RK_CMD_ID_SET_RK_FOR_PLUGGED_IN_SSD,ret=" + std::to_string(ret) +
320             ",origin=" + std::to_string(setKeyOrigin);
321         StorageRadar::ReportTEEClientResult("ResetSecretWithRecoveryKeyToTee::TEEC_InvokeCommand",
322             E_TEEC_SET_RK_FOR_PLUGGED_IN_SSD_ERR, userId, extraData);
323         return E_TEEC_SET_RK_FOR_PLUGGED_IN_SSD_ERR;
324     }
325     auto delay = StorageService::StorageRadar::ReportDuration("RESET SECRET WITH RECOVERY KEY",
326         startTime, StorageService::DELAY_TIME_THRESH_HIGH, userId);
327     LOGI("SD_DURATION: RESET SECRET WITH RECOVERY KEY, delayTime = %{public}s", delay.c_str());
328     CloseSession(setKeyContext, setKeySession);
329 #endif
330     return E_OK;
331 }
332 
333 #ifdef RECOVER_KEY_TEE_ENVIRONMENT
OpenSession(TEEC_Context & context,TEEC_Session & session)334 bool RecoveryManager::OpenSession(TEEC_Context &context, TEEC_Session &session)
335 {
336     LOGI("enter");
337     if (isSessionOpened) {
338         LOGE("Tee session has Opened !");
339         return true;
340     }
341     TEEC_Result ret = TEEC_InitializeContext(NULL, &context);
342     if (ret != TEEC_SUCCESS) {
343         LOGE("recovery tee ctx init failed !");
344         TEEC_FinalizeContext(&context);
345         isSessionOpened = false;
346         StorageRadar::ReportTEEClientResult("OpenSession::TEEC_InitializeContext", ret, DEFAULT_USERID, "");
347         return false;
348     }
349     TEEC_Operation operation;
350     LOGI("Prepare session operation.");
351     operation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
352     if (memset_s(&operation, sizeof(TEEC_Operation), 0, sizeof(TEEC_Operation)) != EOK) {
353         LOGE("[OpenSession] memset_s failed !");
354         TEEC_FinalizeContext(&context);
355         isSessionOpened = false;
356         return false;
357     }
358     LOGI("Prepare open session.");
359     operation.started = SESSION_START_DEFAULT;
360     operation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
361     uint32_t retErr = 0;
362     uint32_t retryCount = 0;
363     while (retryCount < MAX_RETRY_COUNT) {
364         ret = TEEC_OpenSession(&context, &session, recoverUuid_, TEEC_LOGIN_IDENTIFY, nullptr, &operation, &retErr);
365         if (ret == TEEC_SUCCESS) {
366             LOGI("Open session success, has try %{public}u times.", retryCount);
367             break;
368         }
369         retryCount++;
370         LOGE("has retry %{public}d times, ret: %{public}d", retryCount, ret);
371         usleep(RETRY_INTERVAL);
372     }
373 
374     if (ret != TEEC_SUCCESS) {
375         LOGE("open session failed !");
376         CloseSession(context, session);
377         StorageRadar::ReportTEEClientResult("OpenSession::TEEC_OpenSession", ret, DEFAULT_USERID, "");
378         return false;
379     }
380     isSessionOpened = true;
381     LOGI("open session success");
382     return true;
383 }
384 
CloseSession(TEEC_Context & context,TEEC_Session & session)385 void RecoveryManager::CloseSession(TEEC_Context &context, TEEC_Session &session)
386 {
387     TEEC_CloseSession(&session);
388     TEEC_FinalizeContext(&context);
389     isSessionOpened = false;
390     LOGI("close session success");
391 }
392 #endif
393 
GenerateKeyDesc(const KeyBlob & ivBlob,KeyBlob & keyDesc)394 int32_t RecoveryManager::GenerateKeyDesc(const KeyBlob &ivBlob, KeyBlob &keyDesc)
395 {
396     LOGI("enter");
397     if (ivBlob.IsEmpty()) {
398         LOGE("key is empty");
399         return E_KEY_BLOB_ERROR;
400     }
401     SHA512_CTX c;
402 
403     SHA512_Init(&c);
404     SHA512_Update(&c, ivBlob.data.get(), ivBlob.size);
405     uint8_t keyRef1[SHA512_DIGEST_LENGTH] = { 0 };
406     SHA512_Final(keyRef1, &c);
407 
408     SHA512_Init(&c);
409     SHA512_Update(&c, keyRef1, SHA512_DIGEST_LENGTH);
410     uint8_t keyRef2[SHA512_DIGEST_LENGTH] = { 0 };
411     SHA512_Final(keyRef2, &c);
412 
413     static_assert(SHA512_DIGEST_LENGTH >= CRYPTO_KEY_DESC_SIZE, "Hash too short for descriptor");
414     keyDesc.Alloc(CRYPTO_KEY_DESC_SIZE);
415     auto err = memcpy_s(keyDesc.data.get(), keyDesc.size, keyRef2, CRYPTO_KEY_DESC_SIZE);
416     if (err != EOK) {
417         LOGE("memcpy failed ret %{public}d", err);
418         return err;
419     }
420     LOGI("succeed");
421     return E_OK;
422 }
423 
InstallKeyDescToKeyring(size_t keyType,const KeyBlob & key2Blob,const KeyBlob & keyDesc)424 int32_t RecoveryManager::InstallKeyDescToKeyring(size_t keyType, const KeyBlob &key2Blob, const KeyBlob &keyDesc)
425 {
426     int ret = E_OK;
427     if (keyType == TYPE_EL3 || keyType == TYPE_EL4) {
428         uint32_t sdpClass;
429         if (keyType == TYPE_EL3) {
430             sdpClass = FSCRYPT_SDP_SECE_CLASS;
431         } else {
432             sdpClass = FSCRYPT_SDP_ECE_CLASS;
433         }
434         ret = InstallEceSece(sdpClass, key2Blob, keyDesc);
435         if (ret != E_OK) {
436             LOGE("InstallKeyDescToKeyring failed");
437             return ret;
438         }
439     } else {
440         ret = InstallDeCe(key2Blob, keyDesc);
441         if (ret != E_OK) {
442             LOGE("InstallKeyToKeyring failed");
443             return ret;
444         }
445     }
446     return E_OK;
447 }
448 
449 
InstallDeCe(const KeyBlob & key2Blob,const KeyBlob & keyDesc)450 int32_t RecoveryManager::InstallDeCe(const KeyBlob &key2Blob, const KeyBlob &keyDesc)
451 {
452     fscrypt_key fskey;
453     fskey.mode = FS_ENCRYPTION_MODE_AES_256_XTS;
454     fskey.size = key2Blob.size;
455     auto err = memcpy_s(fskey.raw, FS_MAX_KEY_SIZE, key2Blob.data.get(), key2Blob.size);
456     if (err != EOK) {
457         LOGE("memcpy failed ret %{public}d", err);
458         return err;
459     }
460 
461     key_serial_t krid = KeyCtrlSearch(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
462     if (krid == -1) {
463         LOGI("no session keyring for fscrypt");
464         krid = KeyCtrlAddKey("keyring", "fscrypt", KEY_SPEC_SESSION_KEYRING);
465         if (krid == -1) {
466             LOGE("failed to add session keyring");
467             return E_ADD_SESSION_KEYRING_ERROR;
468         }
469     }
470     for (auto prefix : CRYPTO_NAME_PREFIXES) {
471         std::string keyref = prefix + ":" + keyDesc.ToString();
472         LOGI("InstallDeCe: prefix: %{public}s", prefix.c_str());
473         key_serial_t ks = KeyCtrlAddKeyEx("logon", keyref.c_str(), &fskey, krid);
474         if (ks == -1) {
475             // Addkey failed, need to process the error
476             LOGE("Failed to AddKey %{public}s to keyring, errno %{public}d", prefix.c_str(), errno);
477         }
478     }
479     LOGI("success");
480     return E_OK;
481 }
482 
InstallEceSece(uint32_t sdpClass,const KeyBlob & key2Blob,const KeyBlob & keyDesc)483 int32_t RecoveryManager::InstallEceSece(uint32_t sdpClass, const KeyBlob &key2Blob, const KeyBlob &keyDesc)
484 {
485     EncryptionKeySdp fskey;
486     if (key2Blob.size != sizeof(fskey.raw)) {
487         LOGE("Wrong key size is %{public}d", key2Blob.size);
488         return E_KEY_BLOB_ERROR;
489     }
490     fskey.mode = EXT4_ENCRYPTION_MODE_AES_256_XTS;
491     auto err = memcpy_s(fskey.raw, sizeof(fskey.raw), key2Blob.data.get(), key2Blob.size);
492     if (err != EOK) {
493         LOGE("memcpy failed ret %{public}d", err);
494         return err;
495     }
496     fskey.size = EXT4_AES_256_XTS_KEY_SIZE_TO_KEYRING;
497     fskey.sdpClass = sdpClass;
498     fskey.version = 0;
499     key_serial_t krid = KeyCtrlSearch(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
500     if (krid == -1) {
501         LOGI("no session keyring for fscrypt");
502         krid = KeyCtrlAddKey("keyring", "fscrypt", KEY_SPEC_SESSION_KEYRING);
503         if (krid == -1) {
504             LOGE("failed to add session keyring");
505             return E_ADD_SESSION_KEYRING_ERROR;
506         }
507     }
508     for (auto prefix : CRYPTO_NAME_PREFIXES) {
509         std::string keyref = prefix + ":" + keyDesc.ToString();
510         key_serial_t ks = KeyCtrlAddKeySdp("logon", keyref.c_str(), &fskey, krid);
511         if (ks == -1) {
512             // Addkey failed, need to process the error
513             LOGE("Failed to AddKey %{public}s into keyring, errno %{public}d", prefix.c_str(), errno);
514         }
515     }
516     LOGI("success");
517     return E_OK;
518 }
519 } // namespace StorageDaemon
520 } // namespace HOHS