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