• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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