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 }