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 #include "hichain_auth_connector.h"
16 
17 #include "dm_log.h"
18 #include "dm_anonymous.h"
19 #include "hichain_connector_callback.h"
20 #include "parameter.h"
21 
22 namespace OHOS {
23 namespace DistributedHardware {
24 
25 std::shared_ptr<IDmDeviceAuthCallback> HiChainAuthConnector::dmDeviceAuthCallback_ = nullptr;
26 
HiChainAuthConnector()27 HiChainAuthConnector::HiChainAuthConnector()
28 {
29     int32_t ret = InitDeviceAuthService();
30     if (ret != HC_SUCCESS) {
31         LOGE("hichain InitDeviceAuthService failed, err %{public}d.", ret);
32     }
33     deviceAuthCallback_ = {.onTransmit = HiChainAuthConnector::onTransmit,
34                            .onSessionKeyReturned = HiChainAuthConnector::onSessionKeyReturned,
35                            .onFinish = HiChainAuthConnector::onFinish,
36                            .onError = HiChainAuthConnector::onError,
37                            .onRequest = HiChainAuthConnector::onRequest};
38     LOGI("hichain GetGaInstance success.");
39 }
40 
~HiChainAuthConnector()41 HiChainAuthConnector::~HiChainAuthConnector()
42 {
43     DestroyDeviceAuthService();
44 }
45 
RegisterHiChainAuthCallback(std::shared_ptr<IDmDeviceAuthCallback> callback)46 int32_t HiChainAuthConnector::RegisterHiChainAuthCallback(std::shared_ptr<IDmDeviceAuthCallback> callback)
47 {
48     dmDeviceAuthCallback_ = callback;
49     return DM_OK;
50 }
51 
AuthDevice(int32_t pinCode,int32_t osAccountId,std::string udid,int64_t requestId)52 int32_t HiChainAuthConnector::AuthDevice(int32_t pinCode, int32_t osAccountId, std::string udid, int64_t requestId)
53 {
54     LOGI("HiChainAuthConnector::AuthDevice start.");
55     nlohmann::json authParamJson;
56     authParamJson["osAccountId"] = osAccountId;
57     authParamJson["pinCode"] = std::to_string(pinCode);
58     authParamJson["acquireType"] = AcquireType::P2P_BIND;
59     std::string authParam = authParamJson.dump();
60     LOGI("StartAuthDevice authParam %{public}s ,requestId %{public}" PRId64, GetAnonyString(authParam).c_str(),
61         requestId);
62     int32_t ret = StartAuthDevice(requestId, authParam.c_str(), &deviceAuthCallback_);
63     if (ret != HC_SUCCESS) {
64         LOGE("Hichain authDevice failed, ret is %{public}d.", ret);
65         return ERR_DM_FAILED;
66     }
67     return DM_OK;
68 }
69 
ProcessAuthData(int64_t requestId,std::string authData,int32_t osAccountId)70 int32_t HiChainAuthConnector::ProcessAuthData(int64_t requestId, std::string authData, int32_t osAccountId)
71 {
72     LOGI("HiChainAuthConnector::ProcessAuthData start.");
73     nlohmann::json jsonAuthParam;
74     jsonAuthParam["osAccountId"] = osAccountId;
75     jsonAuthParam["data"] = authData;
76     int32_t ret = ProcessAuthDevice(requestId, jsonAuthParam.dump().c_str(), &deviceAuthCallback_);
77     if (ret != HC_SUCCESS) {
78         LOGE("Hichain processData failed ret %{public}d.", ret);
79         return ERR_DM_FAILED;
80     }
81     return DM_OK;
82 }
83 
onTransmit(int64_t requestId,const uint8_t * data,uint32_t dataLen)84 bool HiChainAuthConnector::onTransmit(int64_t requestId, const uint8_t *data, uint32_t dataLen)
85 {
86     LOGI("AuthDevice onTransmit, requestId %{public}" PRId64, requestId);
87     if (dmDeviceAuthCallback_ == nullptr) {
88         LOGE("HiChainAuthConnector::onTransmit dmDeviceAuthCallback_ is nullptr.");
89         return false;
90     }
91     return dmDeviceAuthCallback_->AuthDeviceTransmit(requestId, data, dataLen);
92 }
93 
onRequest(int64_t requestId,int operationCode,const char * reqParams)94 char *HiChainAuthConnector::onRequest(int64_t requestId, int operationCode, const char *reqParams)
95 {
96     LOGI("HiChainAuthConnector::onRequest start.");
97     (void)requestId;
98     (void)reqParams;
99     if (dmDeviceAuthCallback_ == nullptr) {
100         LOGE("HiChainAuthConnector::onRequest dmDeviceAuthCallback_ is nullptr.");
101         return nullptr;
102     }
103     nlohmann::json jsonObj;
104     int32_t pinCode = 0;
105     if (dmDeviceAuthCallback_->GetPinCode(pinCode) == ERR_DM_FAILED) {
106         jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_REJECTED;
107     } else {
108         jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_ACCEPTED;
109     }
110     std::string deviceId = "";
111     dmDeviceAuthCallback_->GetRemoteDeviceId(deviceId);
112     jsonObj[FIELD_PIN_CODE] = std::to_string(pinCode);
113     jsonObj[FIELD_PEER_CONN_DEVICE_ID] = deviceId;
114     std::string jsonStr = jsonObj.dump();
115     char *buffer = strdup(jsonStr.c_str());
116     return buffer;
117 }
118 
onFinish(int64_t requestId,int operationCode,const char * returnData)119 void HiChainAuthConnector::onFinish(int64_t requestId, int operationCode, const char *returnData)
120 {
121     LOGI("HiChainAuthConnector::onFinish reqId:%{public}" PRId64 ", operation:%{public}d.",
122         requestId, operationCode);
123     (void)returnData;
124     if (dmDeviceAuthCallback_ == nullptr) {
125         LOGE("HiChainAuthConnector::onFinish dmDeviceAuthCallback_ is nullptr.");
126         return;
127     }
128     dmDeviceAuthCallback_->AuthDeviceFinish(requestId);
129 }
130 
onError(int64_t requestId,int operationCode,int errorCode,const char * errorReturn)131 void HiChainAuthConnector::onError(int64_t requestId, int operationCode, int errorCode, const char *errorReturn)
132 {
133     LOGI("HichainAuthenCallBack::onError reqId:%{public}" PRId64 ", operation:%{public}d, errorCode:%{public}d.",
134         requestId, operationCode, errorCode);
135     (void)operationCode;
136     (void)errorReturn;
137     if (dmDeviceAuthCallback_ == nullptr) {
138         LOGE("HiChainAuthConnector::onError dmDeviceAuthCallback_ is nullptr.");
139         return;
140     }
141     dmDeviceAuthCallback_->AuthDeviceError(requestId, ERR_DM_FAILED);
142 }
143 
onSessionKeyReturned(int64_t requestId,const uint8_t * sessionKey,uint32_t sessionKeyLen)144 void HiChainAuthConnector::onSessionKeyReturned(int64_t requestId, const uint8_t *sessionKey, uint32_t sessionKeyLen)
145 {
146     LOGI("HiChainAuthConnector::onSessionKeyReturned start.");
147     if (dmDeviceAuthCallback_ == nullptr) {
148         LOGE("HiChainAuthConnector::onSessionKeyReturned dmDeviceAuthCallback_ is nullptr.");
149         return;
150     }
151     dmDeviceAuthCallback_->AuthDeviceSessionKey(requestId, sessionKey, sessionKeyLen);
152 }
153 
GenerateCredential(std::string & localUdid,int32_t osAccountId,std::string & publicKey)154 int32_t HiChainAuthConnector::GenerateCredential(std::string &localUdid, int32_t osAccountId, std::string &publicKey)
155 {
156     LOGI("HiChainAuthConnector::GenerateCredential start.");
157     nlohmann::json jsonObj;
158     jsonObj["osAccountId"] = osAccountId;
159     jsonObj["deviceId"] = localUdid;
160     jsonObj["acquireType"] = AcquireType::P2P_BIND;
161     jsonObj["flag"] = 1;
162     std::string requestParam = jsonObj.dump();
163     char *returnData = nullptr;
164     if (ProcessCredential(CRED_OP_CREATE, requestParam.c_str(), &returnData) != HC_SUCCESS) {
165         LOGE("Hichain generate credential failed.");
166         return ERR_DM_FAILED;
167     }
168     std::string returnDataStr = static_cast<std::string>(returnData);
169     nlohmann::json jsonObject = nlohmann::json::parse(returnDataStr, nullptr, false);
170     if (jsonObject.is_discarded()) {
171         LOGE("Decode generate return data jsonStr error.");
172         return ERR_DM_FAILED;
173     }
174     if (!IsInt32(jsonObject, "result") || !IsString(jsonObject, "publicKey") ||
175         jsonObject["result"].get<int32_t>() != HC_SUCCESS) {
176         LOGE("Hichain generate public key jsonObject invalied.");
177         return ERR_DM_FAILED;
178     }
179     if (jsonObject["result"].get<int32_t>() != 0) {
180         LOGE("Hichain generate public key failed");
181         return ERR_DM_FAILED;
182     }
183     publicKey = jsonObject["publicKey"].get<std::string>();
184     return DM_OK;
185 }
186 
QueryCredential(std::string & localUdid,int32_t osAccountId)187 bool HiChainAuthConnector::QueryCredential(std::string &localUdid, int32_t osAccountId)
188 {
189     LOGI("HiChainAuthConnector::QueryCredential start.");
190     nlohmann::json jsonObj;
191     jsonObj["osAccountId"] = osAccountId;
192     jsonObj["deviceId"] = localUdid;
193     jsonObj["acquireType"] = AcquireType::P2P_BIND;
194     jsonObj["flag"] = 1;
195     std::string requestParam = jsonObj.dump();
196     char *returnData = nullptr;
197     if (ProcessCredential(CRED_OP_QUERY, requestParam.c_str(), &returnData) != HC_SUCCESS) {
198         LOGE("Hichain query credential failed.");
199         return false;
200     }
201     std::string returnDataStr = static_cast<std::string>(returnData);
202     nlohmann::json jsonObject = nlohmann::json::parse(returnDataStr, nullptr, false);
203     if (jsonObject.is_discarded()) {
204         LOGE("Decode query return data jsonStr error.");
205         return false;
206     }
207     if (!IsInt32(jsonObject, "result") || jsonObject["result"].get<int32_t>() == -1) {
208         LOGE("Hichain generate public key failed.");
209         return false;
210     }
211     if (!IsString(jsonObject, "publicKey") || jsonObject["result"].get<int32_t>() == 1) {
212         LOGI("Credential not exist.");
213         return false;
214     }
215     return true;
216 }
217 
GetCredential(std::string & localUdid,int32_t osAccountId,std::string & publicKey)218 int32_t HiChainAuthConnector::GetCredential(std::string &localUdid, int32_t osAccountId, std::string &publicKey)
219 {
220     LOGI("HiChainAuthConnector::GetCredential");
221     nlohmann::json jsonObj;
222     jsonObj["osAccountId"] = osAccountId;
223     jsonObj["deviceId"] = localUdid;
224     jsonObj["acquireType"] = AcquireType::P2P_BIND;
225     jsonObj["flag"] = 1;
226     std::string requestParam = jsonObj.dump();
227     char *returnData = nullptr;
228     if (ProcessCredential(CRED_OP_QUERY, requestParam.c_str(), &returnData) != HC_SUCCESS) {
229         LOGE("Hichain query credential failed.");
230         return ERR_DM_FAILED;
231     }
232     std::string returnDataStr = static_cast<std::string>(returnData);
233     nlohmann::json jsonObject = nlohmann::json::parse(returnDataStr, nullptr, false);
234     if (jsonObject.is_discarded()) {
235         LOGE("Decode query return data jsonStr error.");
236         return ERR_DM_FAILED;
237     }
238     if (!IsInt32(jsonObject, "result") || jsonObject["result"].get<int32_t>() == -1) {
239         LOGE("Hichain generate public key failed.");
240         return ERR_DM_FAILED;
241     }
242     if (!IsString(jsonObject, "publicKey") || jsonObject["result"].get<int32_t>() == 1) {
243         LOGI("Credential not exist.");
244         return ERR_DM_FAILED;
245     }
246     publicKey = jsonObject["publicKey"].get<std::string>();
247     return DM_OK;
248 }
249 
ImportCredential(int32_t osAccountId,std::string deviceId,std::string publicKey)250 int32_t HiChainAuthConnector::ImportCredential(int32_t osAccountId, std::string deviceId, std::string publicKey)
251 {
252     LOGI("HiChainAuthConnector::ImportCredential");
253     nlohmann::json jsonObj;
254     jsonObj["osAccountId"] = osAccountId;
255     jsonObj["deviceId"] = deviceId;
256     jsonObj["acquireType"] = AcquireType::P2P_BIND;
257     jsonObj["publicKey"] = publicKey;
258     std::string requestParam = jsonObj.dump();
259     char *returnData = nullptr;
260     if (ProcessCredential(CRED_OP_IMPORT, requestParam.c_str(), &returnData) != HC_SUCCESS) {
261         LOGE("Hichain query credential failed.");
262         return ERR_DM_FAILED;
263     }
264     std::string returnDataStr = static_cast<std::string>(returnData);
265     nlohmann::json jsonObject = nlohmann::json::parse(returnDataStr, nullptr, false);
266     if (jsonObject.is_discarded()) {
267         LOGE("Decode import return data jsonStr error.");
268         return ERR_DM_FAILED;
269     }
270     if (!IsInt32(jsonObject, "result")) {
271         LOGI("Hichain import public key jsonObject invalied.");
272         return ERR_DM_FAILED;
273     }
274     int32_t result = jsonObject["result"].get<int32_t>();
275     if (result != 0) {
276         LOGE("Hichain import public key result is %{public}d.", result);
277         return ERR_DM_FAILED;
278     }
279     return DM_OK;
280 }
281 
DeleteCredential(const std::string & deviceId,int32_t userId)282 int32_t HiChainAuthConnector::DeleteCredential(const std::string &deviceId, int32_t userId)
283 {
284     LOGI("DeleteCredential start.");
285     nlohmann::json jsonObj;
286     jsonObj["deviceId"] = deviceId;
287     jsonObj["acquireType"] = AcquireType::P2P_BIND;
288     jsonObj["osAccountId"] = userId;
289     std::string requestParam = jsonObj.dump();
290     char *returnData = nullptr;
291     if (ProcessCredential(CRED_OP_DELETE, requestParam.c_str(), &returnData) != HC_SUCCESS) {
292         LOGE("Hichain query credential failed.");
293         return false;
294     }
295     std::string returnDataStr = static_cast<std::string>(returnData);
296     nlohmann::json jsonObject = nlohmann::json::parse(returnDataStr, nullptr, false);
297     if (jsonObject.is_discarded()) {
298         LOGE("Decode import return data jsonStr error.");
299         return false;
300     }
301     if (!IsInt32(jsonObject, "result")) {
302         LOGI("Hichain delete credential result json key is invalid.");
303         return ERR_DM_FAILED;
304     }
305     return jsonObject["result"].get<int32_t>();
306 }
307 } // namespace DistributedHardware
308 } // namespace OHOS
309