• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025-2025 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 "antifraud_cloud_service.h"
17 
18 #include <chrono>
19 #include <cJSON.h>
20 #include <iomanip>
21 #include <limits>
22 #include <openssl/sha.h>
23 #include <openssl/hmac.h>
24 #include <parameter.h>
25 #include <parameters.h>
26 #include <random>
27 #include <sstream>
28 #include "base64.h"
29 #include "telephony_log_wrapper.h"
30 
31 namespace OHOS {
32 namespace Telephony {
33 constexpr size_t BOUNDARY_LENGTH = 32;
34 constexpr size_t REQUEST_NO_LENGTH = 10;
35 constexpr size_t SERIAL_NUM_LEN = 16;
36 constexpr int BASE64_NUMBER2 = 2;
37 constexpr int COMMON_TIME_OUT = 5000;
38 const std::string RANDOM_CHAR_SET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
39 const std::string UPLOAD_MODEL_PATH = "/rms/v1/antiFraud/upload-model-result";
40 const std::string CLOUD_CONNECT_SERVICE_NAME = "com.cloud.afs.ROOT";
41 const std::string UCS_SERVICE_NAME = "com.hmos.hsdr.antifraud";
42 
AntiFraudCloudService(const std::string & phoneNum)43 AntiFraudCloudService::AntiFraudCloudService(const std::string &phoneNum) : phoneNum_(phoneNum) {}
44 
UploadPostRequest(const OHOS::AntiFraudService::AntiFraudResult & antiFraudResult)45 bool AntiFraudCloudService::UploadPostRequest(const OHOS::AntiFraudService::AntiFraudResult &antiFraudResult)
46 {
47     auto &helper = DelayedRefSingleton<HsdrHelper>().GetInstance();
48     std::string metaData = GeneratePayload(antiFraudResult);
49     std::weak_ptr<AntiFraudCloudService> weakPtr = shared_from_this();
50     std::unique_lock<std::mutex> lock(mutex_);
51     isSettled_ = false;
52     std::string auth;
53     helper.ConnectHsdr([weakPtr, metaData, &auth](sptr<IRemoteObject> remoteObject) {
54         auto ptr = weakPtr.lock();
55         if (ptr == nullptr) {
56             auto &helper = DelayedRefSingleton<HsdrHelper>().GetInstance();
57             helper.DisconnectHsdr();
58             return;
59         }
60         std::lock_guard<std::mutex> lock(ptr->mutex_);
61         auto pair = ptr->EncryptSync(metaData, remoteObject);
62         auto ak = pair.first;
63         if (ak.empty()) {
64             TELEPHONY_LOGE("Failed to get ak.");
65             ptr->isSettled_ = true;
66             ptr->cv_.notify_all();
67             return;
68         }
69         auth = ptr->GetAuthSync(metaData, ak, remoteObject);
70         ptr->isSettled_ = true;
71         ptr->cv_.notify_all();
72     });
73 
74     while (!isSettled_) {
75         if (cv_.wait_for(lock, std::chrono::milliseconds(COMMON_TIME_OUT)) == std::cv_status::timeout) {
76             TELEPHONY_LOGE("get auth timeout.");
77             helper.DisconnectHsdr();
78             return false;
79         }
80     }
81 
82     if (auth.empty()) {
83         TELEPHONY_LOGE("Failed to get auth.");
84         helper.DisconnectHsdr();
85         return false;
86     }
87 
88     helper.ConnectHsdr([metaData, auth, antiFraudResult, weakPtr](sptr<IRemoteObject> remoteObject) {
89         auto ptr = weakPtr.lock();
90         if (ptr == nullptr) {
91             auto &helper = DelayedRefSingleton<HsdrHelper>().GetInstance();
92             helper.DisconnectHsdr();
93             return;
94         }
95         ptr->ConnectCloudAsync(metaData, auth, antiFraudResult, remoteObject);
96     });
97     return true;
98 }
99 
GeneratePayload(const OHOS::AntiFraudService::AntiFraudResult & antiFraudResult)100 std::string AntiFraudCloudService::GeneratePayload(const OHOS::AntiFraudService::AntiFraudResult &antiFraudResult)
101 {
102     cJSON *root = cJSON_CreateObject();
103     if (root == nullptr) {
104         TELEPHONY_LOGE("Failed to create json object");
105         return "";
106     }
107     cJSON_AddStringToObject(root, "modelCaller", "com.hsdr");
108     cJSON_AddStringToObject(root, "reqNo", GenerateRandomString(REQUEST_NO_LENGTH).c_str());
109     cJSON_AddStringToObject(root, "calleeId", "15564984");
110     cJSON_AddStringToObject(root, "osType", "1");
111     cJSON_AddStringToObject(root, "serviceType", "00000002");
112     cJSON_AddStringToObject(root, "callerNum", phoneNum_.c_str());
113     cJSON_AddStringToObject(root, "markerId", "11");
114     cJSON_AddStringToObject(root, "romVer", GetRomVersion().c_str());
115     cJSON_AddStringToObject(root, "modelVer", std::to_string(antiFraudResult.modelVersion).c_str());
116     cJSON_AddNumberToObject(root, "modelScore", antiFraudResult.pvalue);
117     cJSON_AddStringToObject(root, "modelDecision", std::to_string(antiFraudResult.fraudType).c_str());
118     char *jsonString = cJSON_Print(root);
119     if (jsonString == nullptr) {
120         TELEPHONY_LOGE("Failed to generate json string.");
121         cJSON_Delete(root);
122         return "";
123     }
124     std::string payload(jsonString);
125     cJSON_Delete(root);
126     free(jsonString);
127     return payload;
128 }
129 
EncryptSync(const std::string & metaData,sptr<IRemoteObject> remoteObject)130 std::pair<std::string, std::string> AntiFraudCloudService::EncryptSync(const std::string &metaData,
131     sptr<IRemoteObject> remoteObject)
132 {
133     if (remoteObject == nullptr) {
134         TELEPHONY_LOGE("remoteObject is nullptr.");
135         return {"", ""};
136     }
137     HsdrProxy service(remoteObject);
138     std::string encryptResult;
139     HsdrRequest encryptReq = { std::to_string(GenerateRandomLong()), UCS_SERVICE_NAME,
140         HsdrCommands::COMMAND_UCS_REQUEST, GenerateUcsRequestBody(UcsMethod::Encrypt, metaData) };
141     auto ret = service.RequestHsdrServiceSync(encryptReq, encryptResult);
142     TELEPHONY_LOGI("RequestHsdrServiceSync ret = %{public}d", ret);
143 
144     auto pair = ProcessEncryptResult(encryptResult);
145     return pair;
146 }
147 
ProcessEncryptResult(const std::string & encryptResult)148 std::pair<std::string, std::string> AntiFraudCloudService::ProcessEncryptResult(const std::string &encryptResult)
149 {
150     cJSON *root = cJSON_Parse(encryptResult.c_str());
151     if (root == nullptr) {
152         TELEPHONY_LOGE("cJSON_Parse failed");
153         return {"", ""};
154     }
155     cJSON *ak = cJSON_GetObjectItem(root, "ak");
156     if (ak == nullptr || ak->type != cJSON_String) {
157         TELEPHONY_LOGE("ak is not string.");
158         cJSON_Delete(root);
159         return {"", ""};
160     }
161     std::string akString(ak->valuestring);
162     cJSON *encrypt = cJSON_GetObjectItem(root, "data");
163     if (encrypt == nullptr || encrypt->type != cJSON_String) {
164         TELEPHONY_LOGE("encrypt is not string.");
165         cJSON_Delete(root);
166         return {akString, ""};
167     }
168     std::string encryptString(encrypt->valuestring);
169     cJSON_Delete(root);
170     return {akString, encryptString};
171 }
172 
GetAuthSync(const std::string & metaData,const std::string & ak,sptr<IRemoteObject> remoteObject)173 std::string AntiFraudCloudService::GetAuthSync(const std::string &metaData, const std::string &ak,
174     sptr<IRemoteObject> remoteObject)
175 {
176     if (remoteObject == nullptr) {
177         TELEPHONY_LOGE("remoteObject is nullptr.");
178         return "";
179     }
180     HsdrProxy service(remoteObject);
181     auto timestamp = std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(
182         std::chrono::system_clock::now().time_since_epoch()).count());
183     std::string toSign = "POST&" + UPLOAD_MODEL_PATH + "&&";
184     toSign += metaData + "&";
185     toSign += "ak=" + ak + "&";
186     toSign += "timestamp=" + timestamp;
187     std::string signResult;
188     HsdrRequest signReq = { std::to_string(GenerateRandomLong()), UCS_SERVICE_NAME, HsdrCommands::COMMAND_UCS_REQUEST,
189         GenerateUcsRequestBody(UcsMethod::Sign, toSign) };
190     auto ret = service.RequestHsdrServiceSync(signReq, signResult);
191     TELEPHONY_LOGI("RequestHsdrServiceSync ret = %{public}d", ret);
192     std::string signature = ProcessSignResult(signResult);
193     std::string auth = "EXT-CLOUDSOA-HMAC-SHA256 ak=\"" + ak + "\",timestamp=" + timestamp +
194         ",signature=\"" + signature + "\"";
195     return auth;
196 }
197 
ProcessSignResult(const std::string & signResult)198 std::string AntiFraudCloudService::ProcessSignResult(const std::string &signResult)
199 {
200     cJSON *root = cJSON_Parse(signResult.c_str());
201     if (root == nullptr) {
202         TELEPHONY_LOGE("cJSON_Parse failed");
203         return "";
204     }
205     cJSON *data = cJSON_GetObjectItem(root, "data");
206     if (data == nullptr || data->type != cJSON_String) {
207         TELEPHONY_LOGE("signature data is not string.");
208         cJSON_Delete(root);
209         return "";
210     }
211     std::string signature(data->valuestring);
212     cJSON_Delete(root);
213     return signature;
214 }
215 
GenerateUcsRequestBody(UcsMethod code,const std::string & requestData)216 std::string AntiFraudCloudService::GenerateUcsRequestBody(UcsMethod code, const std::string &requestData)
217 {
218     cJSON *root = cJSON_CreateObject();
219     if (root == nullptr) {
220         TELEPHONY_LOGE("Failed to create json object.");
221         return "";
222     }
223     cJSON_AddNumberToObject(root, "method", static_cast<int>(code));
224     cJSON_AddStringToObject(root, "data", EncodeBase64(requestData).c_str());
225     char *jsonString = cJSON_Print(root);
226     if (jsonString == nullptr) {
227         TELEPHONY_LOGE("Failed to generate json string.");
228         cJSON_Delete(root);
229         return "";
230     }
231     std::string requestBody(jsonString);
232     free(jsonString);
233     cJSON_Delete(root);
234     return requestBody;
235 }
236 
EncodeBase64(const std::string & src)237 std::string AntiFraudCloudService::EncodeBase64(const std::string &src)
238 {
239     auto results = Base64::Encode(std::vector<unsigned char>(src.begin(), src.end()));
240     std::string res = (results != nullptr) ? *results : "";
241     return res;
242 }
243 
ConnectCloudAsync(const std::string & metaData,const std::string & auth,const OHOS::AntiFraudService::AntiFraudResult & antiFraudResult,sptr<IRemoteObject> remoteObject)244 bool AntiFraudCloudService::ConnectCloudAsync(const std::string &metaData, const std::string &auth,
245     const OHOS::AntiFraudService::AntiFraudResult &antiFraudResult, sptr<IRemoteObject> remoteObject)
246 {
247     if (remoteObject == nullptr) {
248         TELEPHONY_LOGE("remoteObject is nullptr.");
249         auto &helper = DelayedRefSingleton<HsdrHelper>().GetInstance();
250         helper.DisconnectHsdr();
251         return false;
252     }
253     HsdrProxy service(remoteObject);
254     std::string boundary = GenerateRandomString(BOUNDARY_LENGTH);
255     std::map<std::string, std::string> headers = GenerateHeadersMap(auth, antiFraudResult.text, boundary);
256     std::ostringstream bodyStream;
257     bodyStream << "--" << boundary << "\r\n" <<
258         "Content-Disposition: form-data; name=\"meta-data\"\r\n" <<
259         "Content-Type: application/json\r\n" <<
260         "\r\n" <<
261         metaData << "\r\n" <<
262         "--" << boundary << "\r\n" <<
263         "Content-Disposition: form-data; name=\"file-data\"; filename=\"file.txt\"\r\n" <<
264         "Content-Type: text/plain\r\n" <<
265         "\r\n" <<
266         antiFraudResult.text << "\r\n" <<
267         "--" << boundary << "--";
268     std::string body = bodyStream.str();
269     std::string requestJson = GenerateRequestJson(headers, body);
270     OnResponse onResponse = [](const HsdrResponse &response) {
271         TELEPHONY_LOGI("Onresponse, body: %{public}s", response.body_.c_str());
272         auto &helper = DelayedRefSingleton<HsdrHelper>().GetInstance();
273         helper.DisconnectHsdr();
274     };
275     OnError onError = [](int errCode) {
276         TELEPHONY_LOGE("error code = %{public}d", errCode);
277         auto &helper = DelayedRefSingleton<HsdrHelper>().GetInstance();
278         helper.DisconnectHsdr();
279     };
280     std::string requestId = std::to_string(GenerateRandomLong());
281     sptr<HsdrCallbackStub> callbackStub =
282         new (std::nothrow) HsdrCallbackStub(requestId, onResponse, onError);
283     if (callbackStub == nullptr) {
284         TELEPHONY_LOGE("callbackStub is nullptr.");
285         auto &helper = DelayedRefSingleton<HsdrHelper>().GetInstance();
286         helper.DisconnectHsdr();
287         return false;
288     }
289     HsdrRequest request = { requestId, CLOUD_CONNECT_SERVICE_NAME, HsdrCommands::COMMAND_CLOUD_CONNECT,
290         requestJson };
291     int ret = service.RequestHsdrServiceAsync(callbackStub, request);
292     TELEPHONY_LOGI("RequestHsdrServiceAsync ret = %{public}d", ret);
293     return ret == 0;
294 }
295 
GenerateHeadersMap(const std::string & auth,const std::string & fileContent,const std::string & boundary)296 std::map<std::string, std::string> AntiFraudCloudService::GenerateHeadersMap(const std::string &auth,
297     const std::string &fileContent, const std::string &boundary)
298 {
299     std::map<std::string, std::string> headers;
300     headers["Authorization"] = auth;
301     headers["X-Request-ID"] = GetDeviceSerial();
302     headers["Content-Digest"] = CalculateDigest(fileContent);
303     headers["down-algo"] = "AES-GCM";
304     headers["X-OS-Version"] = GetOsVersion();
305     std::string contentType = "multipart/form-data; boundary=" + boundary;
306     headers["Content-Type"] = contentType;
307     return headers;
308 }
309 
CalculateDigest(const std::string & payload)310 std::string AntiFraudCloudService::CalculateDigest(const std::string &payload)
311 {
312     unsigned char hash[SHA256_DIGEST_LENGTH];
313     SHA256_CTX sha256;
314     SHA256_Init(&sha256);
315     SHA256_Update(&sha256, payload.c_str(), payload.size());
316     SHA256_Final(hash, &sha256);
317 
318     std::stringstream ss;
319     for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
320         ss << std::hex << std::setw(BASE64_NUMBER2) << std::setfill('0') << (int)hash[i];
321     }
322     return ss.str();
323 }
324 
GenerateRequestJson(const std::map<std::string,std::string> & headersMap,const std::string & body)325 std::string AntiFraudCloudService::GenerateRequestJson(const std::map<std::string, std::string> &headersMap,
326     const std::string &body)
327 {
328     cJSON *root = cJSON_CreateObject();
329     if (root == nullptr) {
330         TELEPHONY_LOGE("Failed to create json object.");
331         return "";
332     }
333     cJSON_AddStringToObject(root, "method", "POST");
334     cJSON_AddStringToObject(root, "path", UPLOAD_MODEL_PATH.c_str());
335 
336     cJSON *headers = cJSON_CreateObject();
337     if (headers == nullptr) {
338         TELEPHONY_LOGE("Failed to create json object.");
339         cJSON_Delete(root);
340         return "";
341     }
342     cJSON *params = cJSON_CreateArray();
343     if (params == nullptr) {
344         TELEPHONY_LOGE("Failed to create json object.");
345         cJSON_Delete(root);
346         cJSON_Delete(headers);
347         return "";
348     }
349     for (auto header : headersMap) {
350         cJSON *param = cJSON_CreateObject();
351         if (param == nullptr) {
352             TELEPHONY_LOGE("Failed to create json object.");
353             cJSON_Delete(root);
354             cJSON_Delete(headers);
355             cJSON_Delete(params);
356             return "";
357         }
358         cJSON_AddStringToObject(param, "name", header.first.c_str());
359         cJSON_AddStringToObject(param, "value", header.second.c_str());
360         cJSON_AddItemToArray(params, param);
361     }
362     cJSON_AddItemToObject(headers, "params", params);
363     cJSON_AddItemToObject(root, "headers", headers);
364 
365     cJSON_AddStringToObject(root, "body", body.c_str());
366     cJSON_AddNumberToObject(root, "connectTimeout", COMMON_TIME_OUT);
367     cJSON_AddNumberToObject(root, "readTimeout", COMMON_TIME_OUT);
368     char *str = cJSON_Print(root);
369     if (str == nullptr) {
370         TELEPHONY_LOGE("Failed to generate json string.");
371         cJSON_Delete(root);
372         return "";
373     }
374     std::string requestJson(str);
375     cJSON_Delete(root);
376     free(str);
377     return requestJson;
378 }
379 
GenerateRandomString(size_t length)380 std::string AntiFraudCloudService::GenerateRandomString(size_t length)
381 {
382     std::string randomString;
383     randomString.reserve(length);
384     for (size_t i = 0; i < length; i++) {
385         std::random_device rd;
386         std::uniform_int_distribution<size_t> dist(0, RANDOM_CHAR_SET.size() - 1);
387         size_t randomNum = dist(rd);
388         randomString += RANDOM_CHAR_SET[randomNum];
389     }
390 
391     return randomString;
392 }
393 
GenerateRandomLong()394 uint64_t AntiFraudCloudService::GenerateRandomLong()
395 {
396     std::random_device seed;
397     std::mt19937_64 gen(seed());
398     std::uniform_int_distribution<uint64_t> dis(std::numeric_limits<uint64_t>::min(),
399         std::numeric_limits<uint64_t>::max());
400     return dis(gen);
401 }
402 
GetOsVersion()403 std::string AntiFraudCloudService::GetOsVersion()
404 {
405     return system::GetParameter("const.ohos.fullname", "");
406 }
407 
GetDeviceSerial()408 std::string AntiFraudCloudService::GetDeviceSerial()
409 {
410     const char *serial = GetSerial();
411     if (serial == nullptr) {
412         TELEPHONY_LOGE("GetSerial failed.");
413         return GenerateRandomString(SERIAL_NUM_LEN);
414     }
415     std::string deviceSerial(serial);
416     return deviceSerial;
417 }
418 
GetRomVersion()419 std::string AntiFraudCloudService::GetRomVersion()
420 {
421     std::string fullVersion = system::GetParameter("const.product.software.version", "");
422     return GetSubstringBeforeSymbol(fullVersion, "(");
423 }
424 
GetSubstringBeforeSymbol(const std::string & str,const std::string & symbol)425 std::string AntiFraudCloudService::GetSubstringBeforeSymbol(const std::string &str, const std::string &symbol)
426 {
427     size_t pos = str.rfind(symbol);
428     if (pos != std::string::npos) {
429         return str.substr(0, pos);
430     } else {
431         return str;
432     }
433 }
434 } // namespace Telephony
435 } // namsespace OHOS