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], &param);
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