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 
16 #include "hichain_adapter.h"
17 
18 #include "cJSON.h"
19 #include "device_auth.h"
20 #include "device_auth_defines.h"
21 #include "device_manager_impl_lite_m.h"
22 #include "los_compiler.h"
23 #include "los_config.h"
24 #include "los_sem.h"
25 #include "parameter.h"
26 #include "securec.h"
27 
28 #define HICHAIN_DELAY_TICK_COUNT (10 * LOSCFG_BASE_CORE_TICK_PER_SECOND)  // delay 10s
29 
30 static const UINT32 HICHAIN_SEM_INIT_COUNT = 0;
31 
32 static const char * const HICHAIN_PKG_NAME = "com.ohos.devicemanager";
33 static const char * const FILED_GROUP_TYPE = "groupType";
34 
35 static const int GROUP_TYPE_INVALID_GROUP = -1;
36 static const int GROUP_TYPE_IDENTICAL_ACCOUNT_GROUP = 1;
37 static const int GROUP_TYPE_PEER_TO_PEER_GROUP = 256;
38 static const int GROUP_TYPE_ACROSS_ACCOUNT_GROUP = 1282;
39 static const int AUTH_FORM_IDENTICAL_ACCOUNT_GROUP = 1;
40 static const int AUTH_FORM_PEER_TO_PEER_GROUP = 0;
41 static const int AUTH_FORM_ACROSS_ACCOUNT_GROUP = 2;
42 
43 static const DeviceGroupManager *g_deviceGroupManager = NULL;
44 static const GroupAuthManager *g_groupAuthManager = NULL;
45 
46 static UINT32 g_createGroupSem = LOSCFG_BASE_IPC_SEM_LIMIT;
47 
48 static void OnFinish(int64_t requestId, int operationCode, const char *returnData);
49 static void OnError(int64_t requestId, int operationCode, int errorCode, const char *errorReturn);
50 
51 static int ParseReturnJson(const char *returnJsonStr, int authForm);
52 
53 static DeviceAuthCallback g_deviceAuthCallback = {
54     .onTransmit = NULL,
55     .onSessionKeyReturned = NULL,
56     .onFinish = OnFinish,
57     .onError = OnError,
58     .onRequest = NULL,
59 };
60 
InitHichainModle(void)61 int InitHichainModle(void)
62 {
63     int retValue = DM_OK;
64     int ret = InitDeviceAuthService();
65     if (ret != HC_SUCCESS) {
66         DMLOGE("failed to init device auth service with ret: %d.", ret);
67         return ERR_DM_HICHAIN_INIT_DEVICE_AUTH_SERVICE;
68     }
69     g_deviceGroupManager = GetGmInstance();
70     g_groupAuthManager = GetGaInstance();
71     if (g_deviceGroupManager == NULL || g_groupAuthManager == NULL) {
72         DMLOGE("failed to get Gm or Ga instance from hichain.");
73         DestroyDeviceAuthService();
74         return ERR_DM_HICHAIN_GET_GM_INSTANCE;
75     }
76 
77     ret = g_deviceGroupManager->regCallback(HICHAIN_PKG_NAME, &g_deviceAuthCallback);
78     if (ret != HC_SUCCESS) {
79         DMLOGE("failed to register callback function to hichain with ret: %d.", ret);
80         retValue = ERR_DM_HICHAIN_REGISTER_CALLBACK;
81     }
82     UINT32 osRet = LOS_BinarySemCreate(HICHAIN_SEM_INIT_COUNT, &g_createGroupSem);
83     if (osRet != LOS_OK) {
84         DMLOGE("failed to create group semaphore with ret: %d.", ret);
85         retValue = ERR_DM_LITEOS_CREATE_MUTEX_OR_SEM;
86     }
87     if (retValue != DM_OK) {
88         DMLOGE("failed to init hichain modle with retValue: %d.", retValue);
89         UnInitHichainModle();
90         return retValue;
91     }
92     DMLOGI("init hichain modle successfully.");
93     return DM_OK;
94 }
95 
UnInitHichainModle(void)96 int UnInitHichainModle(void)
97 {
98     if (g_deviceGroupManager == NULL) {
99         DMLOGE("g_deviceGroupManager is NULL.");
100         return ERR_DM_POINT_NULL;
101     }
102     int retValue = g_deviceGroupManager->unRegCallback(HICHAIN_PKG_NAME);
103     if (retValue != HC_SUCCESS) {
104         DMLOGE("failed to unregister callback function to hichain with ret: %d.", retValue);
105         retValue = ERR_DM_HICHAIN_UNREGISTER_CALLBACK;
106     } else {
107         retValue = DM_OK;
108     }
109     DestroyDeviceAuthService();
110     g_deviceGroupManager = NULL;
111 
112     UINT32 osRet = LOS_SemDelete(g_createGroupSem);
113     if (osRet != LOS_OK && osRet != LOS_ERRNO_SEM_INVALID) {
114         DMLOGE("failed to delete group semaphore with ret: %d.", osRet);
115         retValue = ERR_DM_LITEOS_DELETE_MUTEX_OR_SEM;
116     } else {
117         g_createGroupSem = LOSCFG_BASE_IPC_SEM_LIMIT;
118     }
119     if (retValue != DM_OK) {
120         DMLOGE("failed to uninit hichain modle with retValue: %d.", retValue);
121         return retValue;
122     }
123     DMLOGI("uninit hichain modle successfully.");
124     return DM_OK;
125 }
126 
ParseReturnJson(const char * returnJsonStr,int authForm)127 int ParseReturnJson(const char *returnJsonStr, int authForm) // hichain groupType convert dm authForm
128 {
129     if (returnJsonStr == NULL) {
130         DMLOGE("return json str is null.");
131         return ERR_DM_HICHAIN_FAILED;
132     }
133     cJSON *groupInfos = cJSON_Parse(returnJsonStr);
134     if (groupInfos == NULL) {
135         DMLOGE("parse return json str failed.");
136         cJSON_Delete(groupInfos);
137         return ERR_DM_CJSON_PARSE_STRING;
138     }
139     cJSON *groupInfo = NULL;
140     int groupType = -1;
141     cJSON_ArrayForEach(groupInfo, groupInfos) {
142         cJSON *object = cJSON_GetObjectItem(groupInfo, FILED_GROUP_TYPE);
143         if (object != NULL && cJSON_IsNumber(object)) {
144             groupType = object->valueint;
145             DMLOGI("parse group type is: %d.", authForm);
146             break;
147         }
148     }
149     cJSON_Delete(groupInfos);
150 
151     if (groupType == GROUP_TYPE_INVALID_GROUP) {
152         authForm = GROUP_TYPE_INVALID_GROUP;
153     }
154     if (groupType == GROUP_TYPE_PEER_TO_PEER_GROUP) {
155         authForm = AUTH_FORM_PEER_TO_PEER_GROUP;
156     }
157     if (groupType == GROUP_TYPE_IDENTICAL_ACCOUNT_GROUP) {
158         authForm = AUTH_FORM_IDENTICAL_ACCOUNT_GROUP;
159     }
160     if (groupType == GROUP_TYPE_ACROSS_ACCOUNT_GROUP) {
161         authForm = AUTH_FORM_ACROSS_ACCOUNT_GROUP;
162     }
163     return DM_OK;
164 }
165 
GetAuthFormByDeviceId(const char * deviceId,int authForm)166 int GetAuthFormByDeviceId(const char *deviceId, int authForm)
167 {
168     int resultFlag = ERR_DM_FAILED;
169     char *returnJsonStr = NULL;
170     uint32_t groupNumber = 0;
171     int userId = 0;
172     authForm = -1;
173 
174     if (g_deviceGroupManager == NULL) {
175         DMLOGE("g_deviceGroupManager is NULL.");
176         return resultFlag;
177     }
178 
179     do {
180         int ret = g_deviceGroupManager->getRelatedGroups(userId, HICHAIN_PKG_NAME, deviceId, &returnJsonStr,
181             &groupNumber);
182         if (ret != HC_SUCCESS) {
183             DMLOGE("failed to get related group ret: %d.", ret);
184             resultFlag = ERR_DM_HICHAIN_FAILED;
185             break;
186         }
187         if (groupNumber == 0) {
188             DMLOGE("get related groups number is zero.");
189             resultFlag = ERR_DM_HICHAIN_FAILED;
190             break;
191         }
192         DMLOGI("get related groups size %u.", groupNumber);
193         ret = ParseReturnJson(returnJsonStr, authForm);
194         if (ret != DM_OK) {
195             DMLOGE("parse group infomation failed.");
196             resultFlag = ret;
197             break;
198         }
199         resultFlag = DM_OK;
200     } while (false);
201 
202     g_deviceGroupManager->destroyInfo(&returnJsonStr);
203     return resultFlag;
204 }
205 
OnFinish(int64_t requestId,int operationCode,const char * returnData)206 static void OnFinish(int64_t requestId, int operationCode, const char *returnData)
207 {
208     (void)returnData;
209     DMLOGI("OnFinish callback complete with requestId: %lld, operation: %d.", requestId, operationCode);
210 }
211 
OnError(int64_t requestId,int operationCode,int errorCode,const char * errorReturn)212 static void OnError(int64_t requestId, int operationCode, int errorCode, const char *errorReturn)
213 {
214     (void)errorReturn;
215     DMLOGI("OnError callback complete with requestId: %lld, operation: %d, errorCode: %d.",
216         requestId, operationCode, errorCode);
217 }
218