• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 "mine_hichain_connector.h"
17 
18 #include <cstdlib>
19 #include <chrono>
20 #include <unistd.h>
21 #include <securec.h>
22 
23 #include "device_auth.h"
24 #include "device_auth_defines.h"
25 #include "dm_anonymous.h"
26 #include "dm_constants.h"
27 #include "dm_log.h"
28 #include "json_object.h"
29 #include "parameter.h"
30 
31 
32 namespace OHOS {
33 namespace DistributedHardware {
34 constexpr int32_t DEVICE_UDID_LENGTH = 65;
35 constexpr int64_t CREATE_GROUP_REQUESTID = 159357462;
36 constexpr int32_t MAX_HICHAIN_DELAY_TIME = 10;
37 
38 std::mutex g_createGroupMutex;
39 std::condition_variable g_createGroupNotify;
40 
41 bool g_mineCreateGroupFlag = false;
42 
43 const DeviceGroupManager *g_deviceGroupManager = nullptr;
44 DeviceAuthCallback g_deviceAuthCallback = {
45     .onTransmit = nullptr,
46     .onFinish = MineHiChainConnector::onFinish,
47     .onError = MineHiChainConnector::onError,
48     .onRequest = nullptr
49 };
MineHiChainConnector()50 MineHiChainConnector::MineHiChainConnector()
51 {
52     Init();
53     LOGI("HiChainConnector::constructor success.");
54 }
55 
~MineHiChainConnector()56 MineHiChainConnector::~MineHiChainConnector()
57 {
58     UnInit();
59     LOGI("HiChainConnector::destructor.");
60 }
61 
onFinish(int64_t requestId,int operationCode,const char * returnData)62 void MineHiChainConnector::onFinish(int64_t requestId, int operationCode, const char *returnData)
63 {
64     (void)returnData;
65     LOGD("start to notify the asynchronous operation group of the successful result.");
66     if (requestId == CREATE_GROUP_REQUESTID) {
67         std::unique_lock<std::mutex> locker(g_createGroupMutex);
68         g_mineCreateGroupFlag = true;
69         g_createGroupNotify.notify_one();
70         LOGI("Create group success");
71     }
72     LOGI("OnFinish callback complete with requestId: %{public}" PRId64 ", operation: %{public}d.", requestId,
73         operationCode);
74 }
75 
onError(int64_t requestId,int operationCode,int errorCode,const char * errorReturn)76 void MineHiChainConnector::onError(int64_t requestId, int operationCode, int errorCode, const char *errorReturn)
77 {
78     (void)errorReturn;
79     LOGD("start to notify the asynchronous operation group of the successful result.");
80     if (requestId == CREATE_GROUP_REQUESTID) {
81         std::unique_lock<std::mutex> locker(g_createGroupMutex);
82         g_mineCreateGroupFlag = false;
83         g_createGroupNotify.notify_one();
84         LOGI("failed to create group");
85     }
86     LOGI("OnError callback complete with requestId: %{public}" PRId64 ", operation: %{public}d, errorCode: %{public}d.",
87         requestId, operationCode, errorCode);
88 }
89 
Init(void)90 int32_t MineHiChainConnector::Init(void)
91 {
92     int retValue = InitDeviceAuthService();
93     if (retValue != HC_SUCCESS) {
94         LOGE("failed to init device auth service with ret:%{public}d.", retValue);
95         return ERR_DM_FAILED;
96     }
97     g_deviceGroupManager = GetGmInstance();
98     if (g_deviceGroupManager == nullptr) {
99         LOGE("failed to get Gm instance from hichain");
100         return ERR_DM_FAILED;
101     }
102 #if (defined(MINE_HARMONY))
103     retValue = g_deviceGroupManager->unRegCallback(DM_PKG_NAME);
104     if (retValue != HC_SUCCESS) {
105         LOGE("failed to register callback function to hichain with ret:%{public}d.", retValue);
106     }
107     retValue = g_deviceGroupManager->regCallback(DM_PKG_NAME, &g_deviceAuthCallback);
108     if (retValue != HC_SUCCESS) {
109         LOGE("failed to register callback function to hichain with ret:%{public}d.", retValue);
110         return ERR_DM_FAILED;
111     }
112 #endif
113     LOGI("init hichain modle successfully.");
114     return DM_OK;
115 }
116 
117 
UnInit(void)118 int32_t MineHiChainConnector::UnInit(void)
119 {
120     if (g_deviceGroupManager == nullptr) {
121         LOGE("g_deviceGroupManager os nullptr");
122         return ERR_DM_POINT_NULL;
123     }
124 #if (defined(MINE_HARMONY))
125     if (g_deviceGroupManager->unRegCallback(DM_PKG_NAME) != HC_SUCCESS) {
126         LOGE("failed to unregister callback to hichain");
127         return ERR_DM_HICHAIN_UNREGISTER_CALLBACK;
128     }
129     DestroyDeviceAuthService();
130 #endif
131     LOGI("uninit hichain modle successfully");
132     return DM_OK;
133 }
134 
DeleteCredentialAndGroup(void)135 int32_t MineHiChainConnector::DeleteCredentialAndGroup(void)
136 {
137     JsonObject jsonObj;
138     jsonObj[FIELD_IS_DELETE_ALL] = true;
139     std::string params = jsonObj.Dump();
140 #if (defined(MINE_HARMONY))
141     char *returnInfo = nullptr;
142     int32_t retValue = g_deviceGroupManager->processCredential(DELETE_SELF_CREDENTIAL, params.c_str(), &returnInfo);
143     if (retValue != HC_SUCCESS) {
144         LOGE("failed to delete hichain credential and group with ret:%{public}d.", retValue);
145         return ERR_DM_FAILED;
146     }
147     g_deviceGroupManager->destroyInfo(&returnInfo);
148 #endif
149     return DM_OK;
150 }
151 
CreateGroup(const std::string & reqJsonStr)152 int32_t MineHiChainConnector::CreateGroup(const std::string &reqJsonStr)
153 {
154     int64_t requestId = CREATE_GROUP_REQUESTID;
155     char deviceUdid[DEVICE_UDID_LENGTH + 1] = {0};
156 
157     JsonObject jsonObject(reqJsonStr);
158     if (jsonObject.IsDiscarded()) {
159         LOGE("reqJsonStr string not a json type.");
160         return ERR_DM_FAILED;
161     }
162     if (!jsonObject.Contains(FIELD_USER_ID) || !jsonObject[FIELD_USER_ID].IsString()) {
163         LOGE("userId key is not exist in reqJsonStr.");
164         return ERR_DM_FAILED;
165     }
166     int32_t retValue = GetDevUdid(deviceUdid, DEVICE_UDID_LENGTH);
167     if (retValue != 0) {
168         LOGE("failed to local device Udid with ret: %{public}d", retValue);
169         return ERR_DM_FAILED;
170     }
171 
172     JsonObject jsonObj;
173     jsonObj[FIELD_USER_ID] = jsonObject[FIELD_USER_ID];
174     jsonObj[FIELD_GROUP_NAME] = DEVICE_MANAGER_GROUPNAME;
175     jsonObj[FIELD_DEVICE_ID] = std::string(deviceUdid);
176     jsonObj[FIELD_GROUP_TYPE] = IDENTICAL_ACCOUNT_GROUP;
177     std::string createParams = jsonObj.Dump();
178     retValue = g_deviceGroupManager->createGroup(DEFAULT_OS_ACCOUNT, requestId, DM_PKG_NAME, createParams.c_str());
179     if (retValue != HC_SUCCESS) {
180         LOGE("failed to create group with ret:%{public}d.", retValue);
181         return ERR_DM_FAILED;
182     }
183 
184     std::chrono::seconds timeout = std::chrono::seconds(MAX_HICHAIN_DELAY_TIME);
185     std::unique_lock<std::mutex> locker(g_createGroupMutex);
186     if (g_createGroupNotify.wait_for(locker, timeout, [] { return g_mineCreateGroupFlag; })) {
187         g_mineCreateGroupFlag = false;
188         return DM_OK;
189     }
190     g_mineCreateGroupFlag = false;
191     return ERR_DM_FAILED;
192 }
193 
RequestCredential(std::string & returnJsonStr)194 int MineHiChainConnector::RequestCredential(std::string &returnJsonStr)
195 {
196     if (g_deviceGroupManager == nullptr) {
197         LOGE("HiChainConnector::g_deviceGroupManager is nullptr.");
198         return ERR_DM_INPUT_PARA_INVALID;
199     }
200 
201     LOGI("start to request device credential.");
202 #if (defined(MINE_HARMONY))
203     char *returnInfo = nullptr;
204     int32_t retValue = g_deviceGroupManager->getRegisterInfo(&returnInfo);
205     if (retValue != HC_SUCCESS || returnInfo == nullptr) {
206         LOGE("failed to request hichain credential with ret:%{public}d.", retValue);
207         return ERR_DM_HICHAIN_GET_REGISTER_INFO;
208     }
209     returnJsonStr = returnInfo;
210     g_deviceGroupManager->destroyInfo(&returnInfo);
211 #endif
212     LOGI("request hichain device credential successfully with JsonStrLen:%{public}zu", returnJsonStr.size());
213     return DM_OK;
214 }
215 
CheckCredential(std::string reqJsonStr,std::string & returnJsonStr)216 int MineHiChainConnector::CheckCredential(std::string reqJsonStr, std::string &returnJsonStr)
217 {
218     if (reqJsonStr.empty() || g_deviceGroupManager == nullptr) {
219         LOGE("HiChainConnector::g_deviceGroupManager is nullptr.");
220         return ERR_DM_INPUT_PARA_INVALID;
221     }
222     LOGI("start to check device credential.");
223 #if (defined(MINE_HARMONY))
224     char *returnInfo = nullptr;
225     int32_t retValue = g_deviceGroupManager->processCredential(QUERY_SELF_CREDENTIAL_INFO,
226         reqJsonStr.c_str(), &returnInfo);
227     if (retValue != HC_SUCCESS) {
228         LOGE("failed to check device credential info with ret:%{public}d.", retValue);
229         return ERR_DM_HICHAIN_GET_REGISTER_INFO;
230     }
231     returnJsonStr = returnInfo;
232     g_deviceGroupManager->destroyInfo(&returnInfo);
233 #endif
234     LOGI("check device credential info successfully with JsonStrLen:%{public}zu", returnJsonStr.size());
235     return DM_OK;
236 }
237 
ImportCredential(std::string reqJsonStr,std::string & returnJsonStr)238 int MineHiChainConnector::ImportCredential(std::string reqJsonStr, std::string &returnJsonStr)
239 {
240     if (reqJsonStr.empty() || g_deviceGroupManager == nullptr) {
241         LOGE("reqJsonStr is empty or g_deviceGroupManager is nullptr.");
242         return ERR_DM_INPUT_PARA_INVALID;
243     }
244     JsonObject jsonObject(reqJsonStr);
245     if (jsonObject.IsDiscarded()) {
246         LOGE("import credenfial input reqJsonStr string not a json string type.");
247         return ERR_DM_INPUT_PARA_INVALID;
248     }
249     if (IsCredentialExist()) {
250         LOGE("the device has already exists credential.");
251         return ERR_DM_HICHAIN_CREDENTIAL_EXISTS;
252     }
253     int32_t retValue = g_deviceGroupManager->regCallback(DM_PKG_NAME, &g_deviceAuthCallback);
254     if (retValue != HC_SUCCESS) {
255         LOGE("failed to register callback function to hichain with ret:%{public}d.", retValue);
256         return ERR_DM_HICHAIN_REGISTER_CALLBACK;
257     }
258     LOGI("start to import device credential info to hichain.");
259 #if (defined(MINE_HARMONY))
260     char *returnInfo = nullptr;
261     retValue = g_deviceGroupManager->processCredential(IMPORT_SELF_CREDENTIAL, reqJsonStr.c_str(), &returnInfo);
262     if (retValue != HC_SUCCESS) {
263         LOGE("failed to import hichain credential with ret:%{public}d.", retValue);
264         return ERR_DM_HICHAIN_GROUP_CREATE_FAILED;
265     }
266     if (CreateGroup(reqJsonStr) != DM_OK) {
267         DeleteCredentialAndGroup();
268         g_deviceGroupManager->destroyInfo(&returnInfo);
269         LOGE("fail to import hichain credential bacause create group unsuccessfully.");
270         return ERR_DM_HICHAIN_GROUP_CREATE_FAILED;
271     }
272     g_deviceGroupManager->destroyInfo(&returnInfo);
273 #endif
274     LOGI("import device credential info successfully.");
275     return DM_OK;
276 }
277 
DeleteCredential(std::string reqJsonStr,std::string & returnJsonStr)278 int MineHiChainConnector::DeleteCredential(std::string reqJsonStr, std::string &returnJsonStr)
279 {
280     if (reqJsonStr.empty() || g_deviceGroupManager == nullptr) {
281         LOGE("reqJsonStr is empty or g_deviceGroupManager is nullptr.");
282         return ERR_DM_INPUT_PARA_INVALID;
283     }
284 
285     LOGI("start to delete device credential from hichain.");
286     if (DeleteCredentialAndGroup() != DM_OK) {
287         LOGE("failed to delete hichain credential.");
288         return ERR_DM_HICHAIN_CREDENTIAL_DELETE_FAILED;
289     }
290     LOGI("delete device credential info from hichain successfully.");
291     return DM_OK;
292 }
293 
IsCredentialExist(void)294 bool MineHiChainConnector::IsCredentialExist(void)
295 {
296     bool resultFlag = false;
297     std::string reqJsonStr = "{\n}";
298 
299     if (g_deviceGroupManager == nullptr) {
300         LOGE("g_deviceGroupManager is nullptr.");
301         return resultFlag;
302     }
303 #if (defined(MINE_HARMONY))
304     char *returnInfo = nullptr;
305     int32_t retValue = g_deviceGroupManager->processCredential(QUERY_SELF_CREDENTIAL_INFO,
306         reqJsonStr.c_str(), &returnInfo);
307     if (retValue != HC_SUCCESS || returnInfo == nullptr) {
308         LOGE("failed to check device credential info with ret:%{public}d.", retValue);
309         return resultFlag;
310     }
311 
312     do {
313         JsonObject jsonObject(returnInfo);
314         if (jsonObject.IsDiscarded()) {
315             LOGE("reqJsonStr is not a json string type.");
316             break;
317         }
318         if (!jsonObject.Contains(FIELD_CREDENTIAL_EXISTS) || !jsonObject[FIELD_CREDENTIAL_EXISTS].IsBoolean()) {
319             LOGE("failed to get key:%{public}s from import json object.", FIELD_CREDENTIAL_EXISTS);
320             break;
321         }
322         if (!jsonObject[FIELD_CREDENTIAL_EXISTS]) {
323             LOGI("credential information does not exist on the current device.");
324             break;
325         }
326         LOGI("credential information exist on the current device.");
327         resultFlag = true;
328     } while (false);
329 
330     g_deviceGroupManager->destroyInfo(&returnInfo);
331 #endif
332     return resultFlag;
333 }
334 } // namespace DistributedHardware
335 } // namespace OHOS