• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "dm_crypto.h"
16 #include "dm_log.h"
17 #if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
18 #include "datetime_ex.h"
19 #include "kv_adapter_manager.h"
20 #endif
21 #include <iostream>
22 #include <sstream>
23 
24 #include <openssl/rand.h>
25 #include "openssl/sha.h"
26 
27 namespace OHOS {
28 namespace DistributedHardware {
29 
30 constexpr int32_t HEX_TO_UINT8 = 2;
31 constexpr int WIDTH = 4;
32 constexpr unsigned char MASK = 0x0F;
33 constexpr int DEC_MAX_NUM = 10;
34 constexpr int HEX_MAX_BIT_NUM = 4;
35 constexpr uint32_t ERR_DM_FAILED = 96929744;
36 constexpr int32_t DM_OK = 0;
37 constexpr int32_t DM_ERR = -1;
38 constexpr int32_t ERR_DM_INPUT_PARA_INVALID = 96929749;
39 constexpr int HEX_DIGIT_MAX_NUM = 16;
40 constexpr int SHORT_DEVICE_ID_HASH_LENGTH = 16;
41 constexpr int32_t SALT_LENGTH = 8;
42 const std::string SALT_DEFAULT = "salt_defsalt_def";
43 constexpr int SHORT_ACCOUNTID_ID_HASH_LENGTH = 6;
44 constexpr const char* DB_KEY_DELIMITER = "###";
45 #define DM_MAX_DEVICE_ID_LEN (97)
46 
HexifyLen(uint32_t len)47 uint32_t HexifyLen(uint32_t len)
48 {
49     return len * HEX_TO_UINT8 + 1;
50 }
51 
DmGenerateStrHash(const void * data,size_t dataSize,unsigned char * outBuf,uint32_t outBufLen,uint32_t startIndex)52 void Crypto::DmGenerateStrHash(const void *data, size_t dataSize, unsigned char *outBuf, uint32_t outBufLen,
53     uint32_t startIndex)
54 {
55     if (data == nullptr || outBuf == nullptr || startIndex > outBufLen) {
56         LOGE("Invalied param.");
57         return;
58     }
59     SHA256_CTX ctx;
60     SHA256_Init(&ctx);
61     SHA256_Update(&ctx, data, dataSize);
62     SHA256_Final(&outBuf[startIndex], &ctx);
63 }
64 
ConvertBytesToHexString(char * outBuf,uint32_t outBufLen,const unsigned char * inBuf,uint32_t inLen)65 DM_EXPORT int32_t Crypto::ConvertBytesToHexString(char *outBuf, uint32_t outBufLen,
66     const unsigned char *inBuf, uint32_t inLen)
67 {
68     if ((outBuf == nullptr) || (inBuf == nullptr) || (outBufLen < HexifyLen(inLen))) {
69         return ERR_DM_INPUT_PARA_INVALID;
70     }
71     while (inLen > 0) {
72         unsigned char h = *inBuf / HEX_DIGIT_MAX_NUM;
73         unsigned char l = *inBuf % HEX_DIGIT_MAX_NUM;
74         if (h < DEC_MAX_NUM) {
75             *outBuf++ = '0' + h;
76         } else {
77             *outBuf++ = 'a' + h - DEC_MAX_NUM;
78         }
79         if (l < DEC_MAX_NUM) {
80             *outBuf++ = '0' + l;
81         } else {
82             *outBuf++ = 'a' + l - DEC_MAX_NUM;
83         }
84         ++inBuf;
85         inLen--;
86     }
87     return DM_OK;
88 }
89 
Sha256(const std::string & text,bool isUpper)90 std::string Crypto::Sha256(const std::string &text, bool isUpper)
91 {
92     return Sha256(text.data(), text.size(), isUpper);
93 }
94 
Sha256(const void * data,size_t size,bool isUpper)95 std::string Crypto::Sha256(const void *data, size_t size, bool isUpper)
96 {
97     unsigned char hash[SHA256_DIGEST_LENGTH * HEX_TO_UINT8 + 1] = "";
98     DmGenerateStrHash(data, size, hash, HexifyLen(SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH);
99     // here we translate sha256 hash to hexadecimal. each 8-bit char will be presented by two characters([0-9a-f])
100     const char* hexCode = isUpper ? "0123456789ABCDEF" : "0123456789abcdef";
101     for (int32_t i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
102         unsigned char value = hash[SHA256_DIGEST_LENGTH + i];
103         // uint8_t is 2 digits in hexadecimal.
104         hash[i * HEX_TO_UINT8] = hexCode[(value >> WIDTH) & MASK];
105         hash[i * HEX_TO_UINT8 + 1] = hexCode[value & MASK];
106     }
107     hash[SHA256_DIGEST_LENGTH * HEX_TO_UINT8] = 0;
108     std::stringstream ss;
109     ss << hash;
110     return ss.str();
111 }
112 
GetUdidHash(const std::string & udid,unsigned char * udidHash)113 int32_t Crypto::GetUdidHash(const std::string &udid, unsigned char *udidHash)
114 {
115     unsigned char hash[SHA256_DIGEST_LENGTH] = "";
116     DmGenerateStrHash(udid.data(), udid.size(), hash, SHA256_DIGEST_LENGTH, 0);
117     if (ConvertBytesToHexString(reinterpret_cast<char *>(udidHash), SHORT_DEVICE_ID_HASH_LENGTH + 1,
118         reinterpret_cast<const uint8_t *>(hash), SHORT_DEVICE_ID_HASH_LENGTH / HEX_TO_UINT8) != DM_OK) {
119         LOGE("ConvertBytesToHexString failed.");
120         return ERR_DM_FAILED;
121     }
122     return DM_OK;
123 }
124 
GetUdidHash(const std::string & udid)125 DM_EXPORT std::string Crypto::GetUdidHash(const std::string &udid)
126 {
127     unsigned char hash[SHA256_DIGEST_LENGTH] = "";
128     char udidHash[DM_MAX_DEVICE_ID_LEN] = {0};
129     DmGenerateStrHash(udid.data(), udid.size(), hash, SHA256_DIGEST_LENGTH, 0);
130     if (ConvertBytesToHexString(reinterpret_cast<char *>(udidHash), SHORT_DEVICE_ID_HASH_LENGTH + 1,
131         reinterpret_cast<const uint8_t *>(hash), SHORT_DEVICE_ID_HASH_LENGTH / HEX_TO_UINT8) != DM_OK) {
132         LOGE("ConvertBytesToHexString failed.");
133         return "";
134     }
135     std::string udidHashStr = std::string(udidHash);
136     return udidHashStr;
137 }
138 
GetTokenIdHash(const std::string & tokenId)139 DM_EXPORT std::string Crypto::GetTokenIdHash(const std::string &tokenId)
140 {
141     unsigned char hash[SHA256_DIGEST_LENGTH] = "";
142     char idHash[DM_MAX_DEVICE_ID_LEN] = {0};
143     DmGenerateStrHash(tokenId.data(), tokenId.size(), hash, SHA256_DIGEST_LENGTH, 0);
144     if (ConvertBytesToHexString(reinterpret_cast<char *>(idHash), SHA256_DIGEST_LENGTH + 1,
145         reinterpret_cast<const uint8_t *>(hash), SHA256_DIGEST_LENGTH / HEX_TO_UINT8) != DM_OK) {
146         LOGE("ConvertBytesToHexString failed.");
147         return "";
148     }
149     std::string tokenIdHash = std::string(idHash);
150     return tokenIdHash;
151 }
152 
ConvertHexStringToBytes(unsigned char * outBuf,uint32_t outBufLen,const char * inBuf,uint32_t inLen)153 DM_EXPORT int32_t Crypto::ConvertHexStringToBytes(unsigned char *outBuf,
154     uint32_t outBufLen, const char *inBuf, uint32_t inLen)
155 {
156     if ((outBuf == NULL) || (inBuf == NULL) || (inLen % HEX_TO_UINT8 != 0)) {
157         LOGE("invalid param");
158         return ERR_DM_FAILED;
159     }
160 
161     uint32_t outLen = inLen / HEX_TO_UINT8;
162     if (outBufLen < outLen) {
163         LOGE("out of memory.");
164         return ERR_DM_FAILED;
165     }
166     uint32_t i = 0;
167     while (i < outLen) {
168         unsigned char c = *inBuf++;
169         if ((c >= '0') && (c <= '9')) {
170             c -= '0';
171         } else if ((c >= 'a') && (c <= 'f')) {
172             c -= 'a' - DEC_MAX_NUM;
173         } else if ((c >= 'A') && (c <= 'F')) {
174             c -= 'A' - DEC_MAX_NUM;
175         } else {
176             LOGE("HexToString Error! %{public}c", c);
177             return ERR_DM_FAILED;
178         }
179         unsigned char c2 = *inBuf++;
180         if ((c2 >= '0') && (c2 <= '9')) {
181             c2 -= '0';
182         } else if ((c2 >= 'a') && (c2 <= 'f')) {
183             c2 -= 'a' - DEC_MAX_NUM;
184         } else if ((c2 >= 'A') && (c2 <= 'F')) {
185             c2 -= 'A' - DEC_MAX_NUM;
186         } else {
187             LOGE("HexToString Error! %{public}c", c2);
188             return ERR_DM_FAILED;
189         }
190         *outBuf++ = (c << HEX_MAX_BIT_NUM) | c2;
191         i++;
192     }
193     return DM_OK;
194 }
195 
GetGroupIdHash(const std::string & groupId)196 DM_EXPORT std::string Crypto::GetGroupIdHash(const std::string &groupId)
197 {
198     unsigned char hash[SHA256_DIGEST_LENGTH] = "";
199     DmGenerateStrHash(groupId.data(), groupId.size(), hash, SHA256_DIGEST_LENGTH, 0);
200     std::stringstream ss;
201     for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
202         ss << std::hex << (int)hash[i];
203     }
204     return ss.str().substr(0, SHORT_DEVICE_ID_HASH_LENGTH);
205 }
206 
GetSecRandom(uint8_t * out,size_t outLen)207 int32_t Crypto::GetSecRandom(uint8_t *out, size_t outLen)
208 {
209     if (out == NULL) {
210         return DM_ERR;
211     }
212 
213     if (outLen == 0) {
214         return DM_ERR;
215     }
216 
217     RAND_poll();
218     RAND_bytes(out, outLen);
219     return DM_OK;
220 }
221 
GetSecSalt()222 std::string Crypto::GetSecSalt()
223 {
224     uint8_t out[SALT_LENGTH] = {0};
225     if (Crypto::GetSecRandom(out, SALT_LENGTH) != DM_OK) {
226         return SALT_DEFAULT;
227     }
228 
229     char outHex[SALT_LENGTH * HEX_TO_UINT8 + 1] = {0};
230     if (ConvertBytesToHexString(outHex, SALT_LENGTH * HEX_TO_UINT8 + 1, out, SALT_LENGTH) != DM_OK) {
231         return SALT_DEFAULT;
232     }
233 
234     return std::string(outHex);
235 }
236 
GetHashWithSalt(const std::string & text,const std::string & salt)237 std::string Crypto::GetHashWithSalt(const std::string &text, const std::string &salt)
238 {
239     std::string rawText = text + salt;
240     return Crypto::Sha256(rawText);
241 }
242 
GetAccountIdHash(const std::string & accountId,unsigned char * accountIdHash)243 DM_EXPORT int32_t Crypto::GetAccountIdHash(const std::string &accountId,
244     unsigned char *accountIdHash)
245 {
246     unsigned char hash[SHA256_DIGEST_LENGTH] = "";
247     DmGenerateStrHash(accountId.data(), accountId.size(), hash, SHA256_DIGEST_LENGTH, 0);
248     if (ConvertBytesToHexString(reinterpret_cast<char *>(accountIdHash), SHORT_ACCOUNTID_ID_HASH_LENGTH + 1,
249         reinterpret_cast<const uint8_t *>(hash), SHORT_ACCOUNTID_ID_HASH_LENGTH / HEX_TO_UINT8) != DM_OK) {
250         LOGE("ConvertBytesToHexString failed.");
251         return ERR_DM_FAILED;
252     }
253     return DM_OK;
254 }
255 
GetAccountIdHash16(const std::string & accountId)256 DM_EXPORT std::string Crypto::GetAccountIdHash16(const std::string &accountId)
257 {
258     unsigned char hash[SHA256_DIGEST_LENGTH] = "";
259     char accountIdHash[DM_MAX_DEVICE_ID_LEN] = {0};
260     DmGenerateStrHash(accountId.data(), accountId.size(), hash, SHA256_DIGEST_LENGTH, 0);
261     if (ConvertBytesToHexString(reinterpret_cast<char *>(accountIdHash), SHA256_DIGEST_LENGTH + 1,
262         reinterpret_cast<const uint8_t *>(hash), SHA256_DIGEST_LENGTH / HEX_TO_UINT8) != DM_OK) {
263         LOGE("ConvertBytesToHexString failed.");
264         return "";
265     }
266     std::string accountHashStr = std::string(accountIdHash);
267     return accountHashStr;
268 }
269 
270 #if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
ConvertUdidHashToAnoyAndSave(const std::string & appId,const std::string & udidHash,DmKVValue & kvValue)271 DM_EXPORT int32_t Crypto::ConvertUdidHashToAnoyAndSave(const std::string &appId,
272     const std::string &udidHash, DmKVValue &kvValue)
273 {
274     if (GetAnoyDeviceInfo(appId, udidHash, kvValue) == DM_OK) {
275         kvValue.lastModifyTime = GetSecondsSince1970ToNow();
276         KVAdapterManager::GetInstance().PutByAnoyDeviceId(kvValue.anoyDeviceId, kvValue);
277         return DM_OK;
278     }
279     int32_t ret = ConvertUdidHashToAnoyGenerate(appId, udidHash, kvValue);
280     if (ret != DM_OK) {
281         LOGE("failed");
282         return ERR_DM_FAILED;
283     }
284     KVAdapterManager::GetInstance().PutByAnoyDeviceId(kvValue.anoyDeviceId, kvValue);
285     return DM_OK;
286 }
287 
ConvertUdidHashToAnoyDeviceId(const std::string & appId,const std::string & udidHash,DmKVValue & kvValue)288 DM_EXPORT int32_t Crypto::ConvertUdidHashToAnoyDeviceId(const std::string &appId,
289     const std::string &udidHash, DmKVValue &kvValue)
290 {
291     LOGD("start.");
292     if (GetAnoyDeviceInfo(appId, udidHash, kvValue) == DM_OK) {
293         return DM_OK;
294     }
295     return ConvertUdidHashToAnoyGenerate(appId, udidHash, kvValue);
296 }
297 
GetAnoyDeviceInfo(const std::string & appId,const std::string & udidHash,DmKVValue & kvValue)298 int32_t Crypto::GetAnoyDeviceInfo(const std::string &appId, const std::string &udidHash, DmKVValue &kvValue)
299 {
300     LOGD("start");
301     std::string udidPrefix = appId + DB_KEY_DELIMITER + udidHash;
302     if (KVAdapterManager::GetInstance().Get(udidPrefix, kvValue) != DM_OK) {
303         LOGI("Get kv value from DB failed");
304         return ERR_DM_FAILED;
305     }
306     return DM_OK;
307 }
308 
ConvertUdidHashToAnoyGenerate(const std::string & appId,const std::string & udidHash,DmKVValue & kvValue)309 int32_t Crypto::ConvertUdidHashToAnoyGenerate(const std::string &appId, const std::string &udidHash,
310     DmKVValue &kvValue)
311 {
312     LOGD("start.");
313     std::string salt = GetSecSalt();
314     std::string udidTemp = appId + DB_KEY_DELIMITER + udidHash + DB_KEY_DELIMITER + salt;
315     char anoyDeviceId[DM_MAX_DEVICE_ID_LEN] = {0};
316     if (GetUdidHash(udidTemp, reinterpret_cast<uint8_t *>(anoyDeviceId)) != DM_OK) {
317         LOGE("get anoyDeviceId by udidTemp failed.");
318         return ERR_DM_FAILED;
319     }
320     kvValue.udidHash = udidHash;
321     kvValue.anoyDeviceId = std::string(anoyDeviceId);
322     kvValue.appID = appId;
323     kvValue.salt = salt;
324     kvValue.lastModifyTime = GetSecondsSince1970ToNow();
325     return DM_OK;
326 }
327 #endif
328 } // namespace DistributedHardware
329 } // namespace OHOS
330