1 /*
2 * Copyright (c) 2023-2023 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_key.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_keyblob.h"
25 #include "hks_log.h"
26 #include "hks_tags_type_manager.h"
27 #include "hks_mem.h"
28 #include "hks_secure_access.h"
29 #include "hks_template.h"
30 #include "hks_type.h"
31
32 #ifdef HKS_ENABLE_SMALL_TO_SERVICE
33 #include "hks_check_trust_list.h"
34 #endif
35
36 #include "securec.h"
37
38 #ifdef HKS_ENABLE_UPGRADE_KEY
IsTagInAlgTagsList(uint32_t tag)39 static bool IsTagInAlgTagsList(uint32_t tag)
40 {
41 uint32_t *tagList = NULL;
42 uint32_t listSize = 0;
43 HksGetAlgTagsList(&tagList, &listSize);
44 for (uint32_t i = 0; i < listSize; ++i) {
45 if (tag == tagList[i]) {
46 return true;
47 }
48 }
49 return false;
50 }
51
AddAlgParamsTags(const struct HksParamSet * srcParamSet,struct HksParamSet * targetParamSet)52 static int32_t AddAlgParamsTags(const struct HksParamSet *srcParamSet, struct HksParamSet *targetParamSet)
53 {
54 int32_t ret = HKS_SUCCESS;
55
56 for (uint32_t i = 0; i < srcParamSet->paramsCnt; ++i) {
57 if (IsTagInAlgTagsList(srcParamSet->params[i].tag)) {
58 ret = HksAddParams(targetParamSet, &(srcParamSet->params[i]), 1);
59 if (ret != HKS_SUCCESS) {
60 HKS_LOG_E("append param %" LOG_PUBLIC "u failed", srcParamSet->params[i].tag);
61 break;
62 }
63 }
64 }
65 return ret;
66 }
67
AddMandatoryParams(const struct HksParamSet * paramSet,struct HksParamSet * targetParamSet)68 static int32_t AddMandatoryParams(const struct HksParamSet *paramSet, struct HksParamSet *targetParamSet)
69 {
70 uint32_t *tagList = NULL;
71 uint32_t listSize = 0;
72 HksGetKeyFileTagsList(&tagList, &listSize);
73 int32_t ret = HKS_SUCCESS;
74 for (uint32_t i = 0; i < listSize; ++i) {
75 struct HksParam *param = NULL;
76 ret = HksGetParam(paramSet, tagList[i], ¶m);
77 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "get param %" LOG_PUBLIC "u from paramSet failed!", tagList[i])
78 ret = HksAddParams(targetParamSet, param, 1);
79 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "add param %" LOG_PUBLIC "u into targetParamSet failed!", tagList[i])
80 }
81 return ret;
82 }
83
84 typedef int32_t (*HksAddUpgradeParam)(const struct HksParamSet *srcParamSet, struct HksParamSet *targetParamSet);
85
86 struct HksAddUpgradeParamFuncMap {
87 uint32_t paramTag;
88 HksAddUpgradeParam func;
89 };
90
HksAddKeyVersionToParamSet(const struct HksParamSet * srcParamSet,struct HksParamSet * targetParamSet)91 static int32_t HksAddKeyVersionToParamSet(const struct HksParamSet *srcParamSet, struct HksParamSet *targetParamSet)
92 {
93 (void)srcParamSet;
94 struct HksParam HksParamKeyVerison = { .tag = HKS_TAG_KEY_VERSION, .uint32Param = HKS_KEY_VERSION };
95 return HksAddParams(targetParamSet, &HksParamKeyVerison, 1);
96 }
97
HksAddOsVersionToParamSet(const struct HksParamSet * srcParamSet,struct HksParamSet * targetParamSet)98 static int32_t HksAddOsVersionToParamSet(const struct HksParamSet *srcParamSet, struct HksParamSet *targetParamSet)
99 {
100 (void)srcParamSet;
101 struct HksParam HksParamOsVersion = { .tag = HKS_TAG_OS_VERSION, .uint32Param = HKS_KEY_BLOB_DUMMY_OS_VERSION };
102 return HksAddParams(targetParamSet, &HksParamOsVersion, 1);
103 }
104
HksAddOsPatchToParamSet(const struct HksParamSet * srcParamSet,struct HksParamSet * targetParamSet)105 static int32_t HksAddOsPatchToParamSet(const struct HksParamSet *srcParamSet, struct HksParamSet *targetParamSet)
106 {
107 (void)srcParamSet;
108 struct HksParam HksOsPatchLevel = { .tag = HKS_TAG_OS_PATCHLEVEL,
109 .uint32Param = HKS_KEY_BLOB_DUMMY_OS_PATCHLEVEL };
110 return HksAddParams(targetParamSet, &HksOsPatchLevel, 1);
111 }
112
HksAddkeyToParamSet(const struct HksParamSet * srcParamSet,struct HksParamSet * targetParamSet)113 static int32_t HksAddkeyToParamSet(const struct HksParamSet *srcParamSet, struct HksParamSet *targetParamSet)
114 {
115 struct HksParam *keyParam = NULL;
116 int32_t ret = HksGetParam(srcParamSet, HKS_TAG_KEY, &keyParam);
117 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "get param key failed!")
118 return HksAddParams(targetParamSet, keyParam, 1);
119 }
120
121 static const struct HksAddUpgradeParamFuncMap HKS_ADD_MANDATORY_FUNC_LIST[] = {
122 {
123 .paramTag = HKS_TAG_KEY_VERSION,
124 .func = HksAddKeyVersionToParamSet
125 }, {
126 .paramTag = HKS_TAG_OS_VERSION,
127 .func = HksAddOsVersionToParamSet
128 }, {
129 .paramTag = HKS_TAG_OS_PATCHLEVEL,
130 .func = HksAddOsPatchToParamSet
131 }, {
132 .paramTag = HKS_TAG_KEY,
133 .func = HksAddkeyToParamSet
134 },
135 };
136
AddMandatoryParamsInCore(const struct HksParamSet * oldKeyBlobParamSet,const struct HksParamSet * srcParamSet,struct HksParamSet ** targetParamSet)137 static int32_t AddMandatoryParamsInCore(const struct HksParamSet *oldKeyBlobParamSet,
138 const struct HksParamSet *srcParamSet, struct HksParamSet **targetParamSet)
139 {
140 struct HksParamSet *outParamSet = NULL;
141 int32_t ret;
142 do {
143 ret = HksInitParamSet(&outParamSet);
144 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "init paramset failed!")
145
146 ret = HksAddParams(outParamSet, srcParamSet->params, srcParamSet->paramsCnt);
147 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "add params from srcParamSet to targetParamSet failed!")
148
149 uint32_t funcArraySize = HKS_ARRAY_SIZE(HKS_ADD_MANDATORY_FUNC_LIST);
150 for (uint32_t i = 0; i < funcArraySize; ++i) {
151 ret = HKS_ADD_MANDATORY_FUNC_LIST[i].func(oldKeyBlobParamSet, outParamSet);
152 if (ret != HKS_SUCCESS) {
153 HksFreeParamSet(&outParamSet);
154 HKS_LOG_E("add upgrade param %" LOG_PUBLIC "u failed!", i);
155 return ret;
156 }
157 }
158
159 *targetParamSet = outParamSet;
160 return ret;
161 } while (0);
162 HksFreeParamSet(&outParamSet);
163 return ret;
164 }
165
166 #ifdef HKS_ENABLE_SMALL_TO_SERVICE
167 // only enable to skip process info verify when the file-owner-change is needed and the target uid is in the white list
HksIsToSkipProcessVerify(const struct HksParamSet * paramSet)168 static int32_t HksIsToSkipProcessVerify(const struct HksParamSet *paramSet)
169 {
170 struct HksParam *processName;
171 int32_t ret = HksGetParam(paramSet, HKS_TAG_PROCESS_NAME, &processName);
172 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "get process name from paramset failed!")
173 uint32_t uid = 0;
174 if (processName->blob.size == sizeof(uid)) {
175 (void)memcpy_s(&uid, sizeof(uid), processName->blob.data, processName->blob.size);
176 } else {
177 return HKS_ERROR_NO_PERMISSION;
178 }
179
180 return HksCheckIsInTrustList(uid);
181 }
182 #endif
183
AuthChangeProcessName(const struct HksParamSet * oldKeyBlobParamSet,const struct HksParamSet * paramSet)184 static int32_t AuthChangeProcessName(const struct HksParamSet *oldKeyBlobParamSet, const struct HksParamSet *paramSet)
185 {
186 struct HksParam *oldProcessName;
187 int32_t ret = HksGetParam(oldKeyBlobParamSet, HKS_TAG_PROCESS_NAME, &oldProcessName);
188 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "get process name from old key paramset failed!")
189
190 struct HksParam *newProcessName;
191 ret = HksGetParam(paramSet, HKS_TAG_PROCESS_NAME, &newProcessName);
192 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, HKS_SUCCESS, "not to change process name, skip the process name auth")
193
194 if (oldProcessName->blob.size != newProcessName->blob.size ||
195 HksMemCmp(oldProcessName->blob.data, newProcessName->blob.data, oldProcessName->blob.size) != HKS_SUCCESS) {
196 #ifdef HKS_ENABLE_SMALL_TO_SERVICE
197 uint32_t uid = 0;
198 ret = memcpy_s(&uid, sizeof(uid), newProcessName->blob.data, newProcessName->blob.size);
199 if (ret != EOK) {
200 return HKS_ERROR_NO_PERMISSION;
201 }
202 ret = HksCheckIsInTrustList(uid);
203 #else
204 return HKS_FAILURE;
205 #endif
206 }
207 return ret;
208 }
209
AuthUpgradeKey(const struct HksParamSet * oldKeyBlobParamSet,const struct HksParamSet * paramSet)210 static int32_t AuthUpgradeKey(const struct HksParamSet *oldKeyBlobParamSet, const struct HksParamSet *paramSet)
211 {
212 int32_t ret;
213 #ifdef HKS_ENABLE_SMALL_TO_SERVICE
214 ret = HksIsToSkipProcessVerify(paramSet);
215 if (ret != HKS_SUCCESS) {
216 #endif
217 ret = HksProcessIdentityVerify(oldKeyBlobParamSet, paramSet);
218 if (ret != HKS_SUCCESS) {
219 return ret;
220 }
221 #ifdef HKS_ENABLE_SMALL_TO_SERVICE
222 }
223 #endif
224
225 return AuthChangeProcessName(oldKeyBlobParamSet, paramSet);
226 }
227
CleanParamSetKey(const struct HksParamSet * paramSet)228 static void CleanParamSetKey(const struct HksParamSet *paramSet)
229 {
230 struct HksParam *keyParam = NULL;
231 int32_t ret = HksGetParam(paramSet, HKS_TAG_KEY, &keyParam);
232 if (ret != HKS_SUCCESS) {
233 HKS_LOG_E("get key param failed!");
234 return;
235 }
236 (void)memset_s(keyParam->blob.data, keyParam->blob.size, 0, keyParam->blob.size);
237 }
238
CheckIsNeedToUpgradeKey(const struct HksParamSet * oldKeyBlobParamSet,const struct HksParamSet * paramSet)239 static int32_t CheckIsNeedToUpgradeKey(const struct HksParamSet *oldKeyBlobParamSet, const struct HksParamSet *paramSet)
240 {
241 int32_t ret = AuthUpgradeKey(oldKeyBlobParamSet, paramSet);
242 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "auth upgrade key param failed!")
243
244 struct HksParam *keyVersion = NULL;
245 ret = HksGetParam(oldKeyBlobParamSet, HKS_TAG_KEY_VERSION, &keyVersion);
246 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "get key version failed!")
247
248 if (keyVersion->uint32Param >= HKS_KEY_VERSION) {
249 HKS_LOG_E("key version is already up to date!");
250 return HKS_FAILURE;
251 }
252 return HKS_SUCCESS;
253 }
254
ConstructNewKeyParamSet(const struct HksParamSet * oldKeyBlobParamSet,const struct HksParamSet * paramSet,struct HksParamSet ** outKeyBlobParamSet)255 static int32_t ConstructNewKeyParamSet(const struct HksParamSet *oldKeyBlobParamSet, const struct HksParamSet *paramSet,
256 struct HksParamSet **outKeyBlobParamSet)
257 {
258 int32_t ret;
259 struct HksParamSet *newMandatoryParamSet = NULL;
260 struct HksParamSet *newKeyBlobParamSet = NULL;
261 do {
262 ret = AddMandatoryParamsInCore(oldKeyBlobParamSet, paramSet, &newMandatoryParamSet);
263 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "AddMandatoryParamsInCore failed!")
264
265 ret = HksInitParamSet(&newKeyBlobParamSet);
266 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "HksInitParamSet failed!")
267
268 ret = AddAlgParamsTags(oldKeyBlobParamSet, newKeyBlobParamSet);
269 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "AddAlgParamsTags failed!")
270
271 // the key param must be the last one added
272 ret = AddMandatoryParams(newMandatoryParamSet, newKeyBlobParamSet);
273 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "AddMandatoryParams failed!")
274
275 ret = HksBuildParamSet(&newKeyBlobParamSet);
276 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "build newKeyBlobParamSet failed!")
277
278 ret = HksCheckParamSetTag(newKeyBlobParamSet);
279 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "HksCheckParamSetTag failed!")
280
281 *outKeyBlobParamSet = newKeyBlobParamSet;
282 HksFreeParamSet(&newMandatoryParamSet);
283 return HKS_SUCCESS;
284 } while (0);
285 HksFreeParamSet(&newMandatoryParamSet);
286
287 CleanParamSetKey(newKeyBlobParamSet);
288 HksFreeParamSet(&newKeyBlobParamSet);
289 return ret;
290 }
291
HksUpgradeKey(const struct HksBlob * oldKey,const struct HksParamSet * paramSet,struct HksBlob * newKey)292 int32_t HksUpgradeKey(const struct HksBlob *oldKey, const struct HksParamSet *paramSet, struct HksBlob *newKey)
293 {
294 HKS_LOG_I("enter HksUpgradeKey");
295 int32_t ret;
296 struct HksParamSet *oldKeyBlobParamSet = NULL;
297 struct HksParamSet *newKeyBlobParamSet = NULL;
298 struct HksKeyNode *keyNode = NULL;
299 do {
300 keyNode = HksGenerateKeyNode(oldKey);
301 if (keyNode == NULL) {
302 ret = HKS_ERROR_BAD_STATE;
303 HKS_LOG_E("generate key node failed!");
304 break;
305 }
306
307 ret = HksGetParamSet(keyNode->paramSet, keyNode->paramSet->paramSetSize, &oldKeyBlobParamSet);
308 if (ret != HKS_SUCCESS) {
309 break;
310 }
311
312 ret = CheckIsNeedToUpgradeKey(oldKeyBlobParamSet, paramSet);
313 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "CheckIsNeedToUpgradeKey failed!")
314
315 ret = ConstructNewKeyParamSet(oldKeyBlobParamSet, paramSet, &newKeyBlobParamSet);
316 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "ConstructNewKeyParamSet failed!")
317
318 ret = HksBuildKeyBlobWithOutAddKeyParam(newKeyBlobParamSet, newKey);
319 } while (0);
320 CleanParamSetKey(newKeyBlobParamSet);
321 HksFreeParamSet(&newKeyBlobParamSet);
322
323 CleanParamSetKey(oldKeyBlobParamSet);
324 HksFreeParamSet(&oldKeyBlobParamSet);
325
326 HksFreeKeyNode(&keyNode);
327
328 return ret;
329 }
330
331 #else /* HKS_ENABLE_UPGRADE_KEY */
HksUpgradeKey(const struct HksBlob * oldKey,const struct HksParamSet * paramSet,struct HksBlob * newKey)332 int32_t HksUpgradeKey(const struct HksBlob *oldKey, const struct HksParamSet *paramSet, struct HksBlob *newKey)
333 {
334 (void)oldKey;
335 (void)paramSet;
336 (void)newKey;
337 return HKS_SUCCESS;
338 }
339 #endif