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