1 /*
2 * Copyright (c) 2024-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_config_parser.h"
17
18 #include <inttypes.h>
19 #include <securec.h>
20 #include <stdint.h>
21 #include <string.h>
22 #include <unistd.h>
23
24 #include "hks_at_api_wrap.h"
25 #include "hks_log.h"
26 #include "hks_mem.h"
27 #include "hks_param.h"
28 #include "hks_template.h"
29 #include "hks_type_inner.h"
30
31 static const struct HksFileTransferSystemAbilityConfig SA_UPGRADE_CFG_LIST[] = HUKS_SA_UPGRADE_CONFIG;
32 static const struct HksFileTransferHapConfig HAP_UPGRADE_CFG_LIST[] = HUKS_HAP_UPGRADE_CONFIG;
33 static const uint32_t SA_SKIP_UPGRADE_CFG_LIST[] = HUKS_SA_SKIP_UPGRADE_CONFIG;
34 static const char * const HAP_SKIP_UPGRADE_CFG_LIST[] = HUKS_HAP_SKIP_UPGRADE_CONFIG;
35
36 static const char * const RDB_DE_PREFIX = "DistributedDataRdb";
37 static const char * const RDB_ROOT_DE = "distributeddb_client_root_key";
38
HksIsRdbDeKey(const char * alias)39 bool HksIsRdbDeKey(const char *alias)
40 {
41 uint32_t rdbDePrefixLen = strlen(RDB_DE_PREFIX);
42 uint32_t rdbRootDeLen = strlen(RDB_ROOT_DE);
43 uint32_t aliasSize = strlen(alias);
44 if (aliasSize >= rdbDePrefixLen && HksMemCmp(alias, RDB_DE_PREFIX, rdbDePrefixLen) == EOK) {
45 return true;
46 }
47 if (aliasSize == rdbRootDeLen && HksMemCmp(alias, RDB_ROOT_DE, rdbRootDeLen) == EOK) {
48 return true;
49 }
50 return false;
51 }
52
ParseOwnerIdFromParamSet(const struct HksParamSet * paramSet,uint32_t * uid,uint64_t * accessTokenId,uint32_t * userId)53 static int32_t ParseOwnerIdFromParamSet(const struct HksParamSet *paramSet, uint32_t *uid, uint64_t *accessTokenId,
54 uint32_t *userId)
55 {
56 bool getUid = false;
57 bool getAccessToken = false;
58 bool getUserId = false;
59 int32_t ret;
60 for (uint32_t i = 0; i < paramSet->paramsCnt; ++i) {
61 if (paramSet->params[i].tag == HKS_TAG_PROCESS_NAME) {
62 // the uid data should be uint32_t
63 if (paramSet->params[i].blob.size != sizeof(uint32_t)) {
64 HKS_LOG_E("process name blob data is over the size of uint32_t.");
65 ret = HKS_ERROR_INVALID_KEY_FILE;
66 break;
67 }
68 *uid = *(uint32_t *)paramSet->params[i].blob.data;
69 getUid = true;
70 continue;
71 }
72 if (paramSet->params[i].tag == HKS_TAG_ACCESS_TOKEN_ID) {
73 *accessTokenId = paramSet->params[i].uint64Param;
74 getAccessToken = true;
75 continue;
76 }
77 if (paramSet->params[i].tag == HKS_TAG_SPECIFIC_USER_ID) {
78 *userId = paramSet->params[i].uint32Param;
79 getUserId = true;
80 continue;
81 }
82 if (paramSet->params[i].tag == HKS_TAG_USER_ID && !getUserId) {
83 *userId = paramSet->params[i].uint32Param;
84 getUserId = true;
85 continue;
86 }
87 if (getUid && getAccessToken && getUserId) {
88 break;
89 }
90 }
91 ret = getUid && getAccessToken && getUserId ? HKS_SUCCESS : HKS_ERROR_INVALID_KEY_FILE;
92 return ret;
93 }
94
ParseOwnerIdFromFileContent(const struct HksBlob * fileContent,uint32_t * uid,uint64_t * accessTokenId,uint32_t * userId)95 static int32_t ParseOwnerIdFromFileContent(const struct HksBlob *fileContent, uint32_t *uid, uint64_t *accessTokenId,
96 uint32_t *userId)
97 {
98 struct HksParamSet *tmpParamSet = NULL;
99 int32_t ret = HksGetParamSet((const struct HksParamSet *)fileContent->data, fileContent->size, &tmpParamSet);
100 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "fresh paramset failed.")
101
102 ret = ParseOwnerIdFromParamSet(tmpParamSet, uid, accessTokenId, userId);
103 HKS_FREE(tmpParamSet);
104 return ret;
105 }
106
InitDefaultStrategy(const char * alias,struct HksUpgradeFileTransferInfo * info)107 static void InitDefaultStrategy(const char *alias, struct HksUpgradeFileTransferInfo *info)
108 {
109 info->skipTransfer = false;
110 info->needDe = false;
111 info->needFrontUser = false;
112 if (HksIsRdbDeKey(alias)) {
113 HKS_LOG_I("Find rdb key file, set default as DE.");
114 // Add default DE for rdb key file.
115 info->needDe = true;
116 }
117 }
118
MatchSaConfig(const char * alias,uint32_t uid,uint32_t userId,struct HksUpgradeFileTransferInfo * info)119 static int32_t MatchSaConfig(const char *alias, uint32_t uid, uint32_t userId, struct HksUpgradeFileTransferInfo *info)
120 {
121 InitDefaultStrategy(alias, info);
122 for (uint32_t i = 0; i < HKS_ARRAY_SIZE(SA_SKIP_UPGRADE_CFG_LIST); ++i) {
123 if (uid == SA_SKIP_UPGRADE_CFG_LIST[i]) {
124 HKS_LOG_E_IMPORTANT("%" LOG_PUBLIC "u needs skip transfer upgrade.", uid);
125 info->skipTransfer = true;
126 return HKS_SUCCESS;
127 }
128 }
129
130 for (uint32_t i = 0; i < HKS_ARRAY_SIZE(SA_UPGRADE_CFG_LIST); ++i) {
131 if (SA_UPGRADE_CFG_LIST[i].uid == uid) {
132 info->needDe = SA_UPGRADE_CFG_LIST[i].needDe;
133 info->needFrontUser = SA_UPGRADE_CFG_LIST[i].needFrontUser;
134 HKS_LOG_E_IMPORTANT("match sa config, need de %" LOG_PUBLIC "d, need with withUser %" LOG_PUBLIC "d,"
135 "need uid %" LOG_PUBLIC "u.", info->needDe, info->needFrontUser, uid);
136 break;
137 }
138 }
139 info->uid = uid;
140 info->userId = userId;
141 return HKS_SUCCESS;
142 }
143
MatchHapConfig(const char * alias,uint32_t uid,uint32_t userId,uint64_t accessTokenId,struct HksUpgradeFileTransferInfo * info)144 static int32_t MatchHapConfig(const char *alias, uint32_t uid, uint32_t userId, uint64_t accessTokenId,
145 struct HksUpgradeFileTransferInfo *info)
146 {
147 char hapName[HAP_NAME_LEN_MAX] = { 0 };
148 int32_t ret = HksGetHapNameFromAccessToken(accessTokenId, hapName, HAP_NAME_LEN_MAX);
149 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
150 "get hap name from accessTokenId failed, accessTokenId is %" LOG_PUBLIC PRIu64, accessTokenId)
151
152 InitDefaultStrategy(alias, info);
153 for (uint32_t i = 0; i < HKS_ARRAY_SIZE(HAP_SKIP_UPGRADE_CFG_LIST); ++i) {
154 HKS_IF_TRUE_CONTINUE(strlen(HAP_SKIP_UPGRADE_CFG_LIST[i]) != strlen(hapName));
155 if (HksMemCmp(HAP_SKIP_UPGRADE_CFG_LIST[i], hapName, strlen(hapName)) == EOK) {
156 info->skipTransfer = true;
157 HKS_LOG_E_IMPORTANT("%" LOG_PUBLIC "u, %" LOG_PUBLIC "s needs skip transfer upgrade.", uid, hapName);
158 return HKS_SUCCESS;
159 }
160 }
161 for (uint32_t i = 0; i < HKS_ARRAY_SIZE(HAP_UPGRADE_CFG_LIST); ++i) {
162 HKS_IF_TRUE_CONTINUE(strlen(HAP_UPGRADE_CFG_LIST[i].hapName) != strlen(hapName));
163 if (HksMemCmp(HAP_UPGRADE_CFG_LIST[i].hapName, hapName, strlen(hapName)) == EOK) {
164 info->needDe = HAP_UPGRADE_CFG_LIST[i].needDe;
165 info->needFrontUser = HAP_UPGRADE_CFG_LIST[i].needFrontUser;
166 HKS_LOG_E_IMPORTANT("match hap config, need de %" LOG_PUBLIC "d, need with withUser %" LOG_PUBLIC "d,"
167 "need uid %" LOG_PUBLIC "u.", info->needDe, info->needFrontUser, uid);
168 break;
169 }
170 }
171 info->uid = uid;
172 info->userId = userId;
173 return HKS_SUCCESS;
174 }
175
HksMatchConfig(const char * alias,uint32_t uid,uint32_t userId,uint64_t accessTokenId,struct HksUpgradeFileTransferInfo * info)176 int32_t HksMatchConfig(const char *alias, uint32_t uid, uint32_t userId, uint64_t accessTokenId,
177 struct HksUpgradeFileTransferInfo *info)
178 {
179 enum HksAtType type;
180 int32_t ret = HksGetAtType(accessTokenId, &type);
181 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "get access token type failed.")
182 if (type == HKS_TOKEN_HAP) {
183 return MatchHapConfig(alias, uid, userId, accessTokenId, info);
184 }
185 return MatchSaConfig(alias, uid, userId, info);
186 }
187
188 // get transfer config info of a key file, which contains the owner info
HksParseConfig(const char * alias,const struct HksBlob * fileContent,struct HksUpgradeFileTransferInfo * info)189 int32_t HksParseConfig(const char *alias, const struct HksBlob *fileContent, struct HksUpgradeFileTransferInfo *info)
190 {
191 uint32_t uid = 0;
192 uint64_t accessTokenId = 0;
193 uint32_t userId = 0;
194 int32_t ret = ParseOwnerIdFromFileContent(fileContent, &uid, &accessTokenId, &userId);
195 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "parse file failed.")
196 return HksMatchConfig(alias, uid, userId, accessTokenId, info);
197 }