1 /*
2 * Copyright (c) 2023-2024 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 #define HUKS_DISABLE_LOG_AT_FILE_TO_REDUCE_ROM_SIZE
16
17 #include "hks_upgrade_helper.h"
18
19 #ifdef HKS_CONFIG_FILE
20 #include HKS_CONFIG_FILE
21 #else
22 #include "hks_config.h"
23 #endif
24
25 #include "hks_check_trust_list.h"
26 #include "hks_client_service_util.h"
27 #include "hks_get_process_info.h"
28 #include "hks_log.h"
29 #include "hks_mem.h"
30 #include "hks_storage.h"
31 #include "hks_template.h"
32 #include "hks_type_inner.h"
33
34 #include "hks_upgrade_key_accesser.h"
35
36 #include "securec.h"
37
38 #ifdef HKS_ENABLE_SMALL_TO_SERVICE
39 #define HKS_OLD_KEY_VERSION_FOR_SDK_HUKS 1
40
HksIsProcessInfoInTrustList(const struct HksProcessInfo * processInfo)41 static int32_t HksIsProcessInfoInTrustList(const struct HksProcessInfo *processInfo)
42 {
43 uint32_t uid = 0;
44 if (processInfo->processName.size == sizeof(uid)) {
45 (void)memcpy_s(&uid, sizeof(uid), processInfo->processName.data, processInfo->processName.size);
46 } else {
47 return HKS_ERROR_NO_PERMISSION;
48 }
49
50 return HksCheckIsInTrustList(uid);
51 }
52
53 #ifdef HKS_ENABLE_MARK_CLEARED_FOR_SMALL_TO_SERVICE
54 // it is ok for no mutex lock, because the hugest problem it can lead to is checking key directory for nothing once
55 static volatile bool g_isOldKeyCleared = false;
56
HksMarkOldKeyClearedIfEmpty(void)57 void HksMarkOldKeyClearedIfEmpty(void)
58 {
59 uint32_t keyCount = 0;
60 int32_t ret = HksIsOldKeyPathCleared(&keyCount);
61 if (ret == HKS_SUCCESS && keyCount == 0) {
62 // record mark
63 g_isOldKeyCleared = true;
64 }
65 }
66
HksIsOldKeyCleared(void)67 static bool HksIsOldKeyCleared(void)
68 {
69 return g_isOldKeyCleared ? true : false;
70 }
71 #endif /** HKS_ENABLE_MARK_CLEARED_FOR_SMALL_TO_SERVICE */
72
HksIsKeyExpectedVersion(const struct HksBlob * key,uint32_t expectedVersion)73 static int32_t HksIsKeyExpectedVersion(const struct HksBlob *key, uint32_t expectedVersion)
74 {
75 struct HksParam *keyVersion = NULL;
76 int32_t ret = HksGetParam((const struct HksParamSet *)key->data, HKS_TAG_KEY_VERSION, &keyVersion);
77 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "get param key version failed!")
78 return (keyVersion->uint32Param == expectedVersion) ? HKS_SUCCESS : HKS_FAILURE;
79 }
80
HksCheckNeedUpgradeForSmallToService(const struct HksProcessInfo * processInfo)81 int32_t HksCheckNeedUpgradeForSmallToService(const struct HksProcessInfo *processInfo)
82 {
83 #ifdef HKS_ENABLE_MARK_CLEARED_FOR_SMALL_TO_SERVICE
84 if (HksIsOldKeyCleared()) {
85 return HKS_FAILURE;
86 }
87 #endif
88 return HksIsProcessInfoInTrustList(processInfo);
89 }
90
HksConstructRootProcessInfo(struct HksProcessInfo * processInfo)91 static int32_t HksConstructRootProcessInfo(struct HksProcessInfo *processInfo)
92 {
93 char *processName = NULL;
94 char *userId = NULL;
95 int32_t ret = HksGetProcessName(&processName);
96 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "get old process name failed");
97 ret = HksGetUserId(&userId);
98 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "get old user if failed");
99
100 processInfo->processName.data = (uint8_t *)processName;
101 processInfo->processName.size = strlen(processName);
102 processInfo->userId.data = (uint8_t *)userId;
103 processInfo->userId.size = strlen(userId);
104 processInfo->userIdInt = 0;
105 processInfo->accessTokenId = 0;
106 return HKS_SUCCESS;
107 }
108
HksDeleteOldKeyForSmallToService(const struct HksBlob * keyAlias)109 int32_t HksDeleteOldKeyForSmallToService(const struct HksBlob *keyAlias)
110 {
111 struct HksProcessInfo rootProcessInfo;
112 int32_t ret = HksConstructRootProcessInfo(&rootProcessInfo);
113 HKS_IF_NOT_SUCC_RETURN(ret, ret)
114 uint32_t keySize = 0;
115 ret = HksManageStoreGetKeyBlobSize(&rootProcessInfo, NULL, keyAlias, &keySize, HKS_STORAGE_TYPE_KEY);
116 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "get keyblob size from storage failed, ret = %" LOG_PUBLIC "d.", ret)
117
118 if (keySize > MAX_KEY_SIZE) {
119 HKS_LOG_E("invalid storage size, size = %" LOG_PUBLIC "u", keySize);
120 return HKS_ERROR_INVALID_KEY_FILE;
121 }
122 struct HksBlob oldKey = { .size = keySize, .data = NULL };
123 do {
124 oldKey.data = (uint8_t *)HksMalloc(keySize);
125 if (oldKey.data == NULL) {
126 ret = HKS_ERROR_MALLOC_FAIL;
127 break;
128 }
129 ret = HksManageStoreGetKeyBlob(&rootProcessInfo, NULL, keyAlias, &oldKey, HKS_STORAGE_TYPE_KEY);
130 HKS_IF_NOT_SUCC_BREAK(ret)
131 ret = HksIsKeyExpectedVersion(&oldKey, HKS_OLD_KEY_VERSION_FOR_SDK_HUKS);
132 if (ret != HKS_SUCCESS) {
133 ret = HKS_ERROR_NOT_EXIST;
134 break;
135 }
136
137 ret = HksManageStoreDeleteKeyBlob(&rootProcessInfo, NULL, keyAlias, HKS_STORAGE_TYPE_KEY);
138 if ((ret != HKS_SUCCESS) && (ret != HKS_ERROR_NOT_EXIST)) {
139 HKS_LOG_E("service delete main key failed, ret = %" LOG_PUBLIC "d", ret);
140 }
141
142 #ifdef HKS_ENABLE_MARK_CLEARED_FOR_SMALL_TO_SERVICE
143 HksMarkOldKeyClearedIfEmpty();
144 #endif
145 } while (0);
146 HKS_FREE_BLOB(oldKey);
147
148 return ret;
149 }
150
HksChangeKeyOwner(const struct HksProcessInfo * processInfo,const struct HksParamSet * paramSet,const struct HksBlob * keyAlias,enum HksStorageType mode)151 static int32_t HksChangeKeyOwner(const struct HksProcessInfo *processInfo, const struct HksParamSet *paramSet,
152 const struct HksBlob *keyAlias, enum HksStorageType mode)
153 {
154 HKS_LOG_I("enter HksChangeKeyOwner");
155 struct HksProcessInfo rootProcessInfo;
156 int32_t ret = HksConstructRootProcessInfo(&rootProcessInfo);
157 HKS_IF_NOT_SUCC_RETURN(ret, ret)
158
159 struct HksBlob oldKey = { .size = 0, .data = NULL };
160 struct HksBlob newKey = { .size = 0, .data = NULL };
161
162 struct HksParamSet *upgradeParamSet = NULL;
163
164 do {
165 // get old key
166 ret = GetKeyFileData(&rootProcessInfo, NULL, keyAlias, &oldKey, mode);
167 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "not have old key")
168
169 ret = ConstructUpgradeKeyParamSet(processInfo, paramSet, &upgradeParamSet);
170 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "construct param set failed!")
171 ret = HksIsKeyExpectedVersion(&oldKey, HKS_OLD_KEY_VERSION_FOR_SDK_HUKS);
172 if (ret != HKS_SUCCESS) {
173 ret = HKS_ERROR_NOT_EXIST;
174 break;
175 }
176
177 newKey.data = (uint8_t *)HksMalloc(MAX_KEY_SIZE);
178 if (newKey.data == NULL) {
179 ret = HKS_ERROR_MALLOC_FAIL;
180 break;
181 }
182 newKey.size = MAX_KEY_SIZE;
183 ret = HksDoUpgradeKeyAccess(&oldKey, upgradeParamSet, &newKey);
184 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "access change key owner failed!")
185
186 ret = HksManageStoreKeyBlob(processInfo, NULL, keyAlias, &newKey, HKS_STORAGE_TYPE_KEY);
187 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "store new key failed!")
188
189 // delete old key only after new key stored successfully
190 (void)HksDeleteOldKeyForSmallToService(keyAlias);
191
192 #ifdef HKS_ENABLE_MARK_CLEARED_FOR_SMALL_TO_SERVICE
193 HksMarkOldKeyClearedIfEmpty();
194 #endif
195 } while (0);
196 HksFreeParamSet(&upgradeParamSet);
197 HKS_FREE_BLOB(oldKey);
198 HKS_FREE_BLOB(newKey);
199
200 return ret;
201 }
202
HksChangeKeyOwnerForSmallToService(const struct HksProcessInfo * processInfo,const struct HksParamSet * paramSet,const struct HksBlob * keyAlias,enum HksStorageType mode)203 int32_t HksChangeKeyOwnerForSmallToService(const struct HksProcessInfo *processInfo, const struct HksParamSet *paramSet,
204 const struct HksBlob *keyAlias, enum HksStorageType mode)
205 {
206 HKS_LOG_I("enter get new key");
207 return HksChangeKeyOwner(processInfo, paramSet, keyAlias, mode);
208 }
209
HksGetkeyInfoListByProcessName(const struct HksProcessInfo * processInfo,struct HksKeyInfo * keyInfoList,uint32_t * listCount)210 static int32_t HksGetkeyInfoListByProcessName(const struct HksProcessInfo *processInfo,
211 struct HksKeyInfo *keyInfoList, uint32_t *listCount)
212 {
213 int32_t ret;
214
215 // the number for infos really added in keyInfoList
216 uint32_t realCnt = 0;
217 do {
218 ret = HksManageGetKeyAliasByProcessName(processInfo, NULL, keyInfoList, listCount);
219 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "get old key alias list from storage failed, ret = %" LOG_PUBLIC "d", ret)
220 for (uint32_t i = 0; i < *listCount; ++i) {
221 struct HksBlob keyFromFile = { 0, NULL };
222 ret = GetKeyFileData(processInfo, NULL, &(keyInfoList[i].alias), &keyFromFile, HKS_STORAGE_TYPE_KEY);
223 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "get old key data failed, ret = %" LOG_PUBLIC "d", ret)
224 if (HksIsKeyExpectedVersion(&keyFromFile, HKS_OLD_KEY_VERSION_FOR_SDK_HUKS) != HKS_SUCCESS) {
225 HKS_FREE_BLOB(keyFromFile);
226 continue;
227 }
228 ret = GetKeyParamSet(&keyFromFile, keyInfoList[realCnt].paramSet);
229 HKS_FREE_BLOB(keyFromFile);
230 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "get old key paramSet failed, ret = %" LOG_PUBLIC "d", ret)
231 ++realCnt;
232 }
233 *listCount = realCnt;
234 return HKS_SUCCESS;
235 } while (0);
236
237 *listCount = realCnt;
238
239 return ret;
240 }
241
HksGetOldKeyInfoListForSmallToService(const struct HksProcessInfo * processInfo,struct HksKeyInfo * keyInfoList,uint32_t listMaxCnt,uint32_t * listCount)242 int32_t HksGetOldKeyInfoListForSmallToService(const struct HksProcessInfo *processInfo, struct HksKeyInfo *keyInfoList,
243 uint32_t listMaxCnt, uint32_t *listCount)
244 {
245 int32_t ret;
246
247 // remain buffer count for old key info
248 uint32_t listCountOld = listMaxCnt - *listCount;
249 do {
250 struct HksProcessInfo rootProcessInfo;
251 ret = HksConstructRootProcessInfo(&rootProcessInfo);
252 HKS_IF_NOT_SUCC_BREAK(ret, "construct root process info failed!")
253 ret = HksGetkeyInfoListByProcessName(&rootProcessInfo, NULL, keyInfoList + *listCount, &listCountOld);
254 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "get key info list in old path failed!")
255
256 *listCount = *listCount + listCountOld;
257 } while (0);
258 return ret;
259 }
260 #endif
261