• 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 #if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
46 #define DM_MAX_DEVICE_ID_LEN (97)
47 #endif
48 
HexifyLen(uint32_t len)49 uint32_t HexifyLen(uint32_t len)
50 {
51     return len * HEX_TO_UINT8 + 1;
52 }
53 
DmGenerateStrHash(const void * data,size_t dataSize,unsigned char * outBuf,uint32_t outBufLen,uint32_t startIndex)54 void Crypto::DmGenerateStrHash(const void *data, size_t dataSize, unsigned char *outBuf, uint32_t outBufLen,
55     uint32_t startIndex)
56 {
57     if (data == nullptr || outBuf == nullptr || startIndex > outBufLen) {
58         LOGE("Invalied param.");
59         return;
60     }
61     SHA256_CTX ctx;
62     SHA256_Init(&ctx);
63     SHA256_Update(&ctx, data, dataSize);
64     SHA256_Final(&outBuf[startIndex], &ctx);
65 }
66 
ConvertBytesToHexString(char * outBuf,uint32_t outBufLen,const unsigned char * inBuf,uint32_t inLen)67 int32_t Crypto::ConvertBytesToHexString(char *outBuf, uint32_t outBufLen, const unsigned char *inBuf,
68     uint32_t inLen)
69 {
70     if ((outBuf == nullptr) || (inBuf == nullptr) || (outBufLen < HexifyLen(inLen))) {
71         return ERR_DM_INPUT_PARA_INVALID;
72     }
73     while (inLen > 0) {
74         unsigned char h = *inBuf / HEX_DIGIT_MAX_NUM;
75         unsigned char l = *inBuf % HEX_DIGIT_MAX_NUM;
76         if (h < DEC_MAX_NUM) {
77             *outBuf++ = '0' + h;
78         } else {
79             *outBuf++ = 'a' + h - DEC_MAX_NUM;
80         }
81         if (l < DEC_MAX_NUM) {
82             *outBuf++ = '0' + l;
83         } else {
84             *outBuf++ = 'a' + l - DEC_MAX_NUM;
85         }
86         ++inBuf;
87         inLen--;
88     }
89     return DM_OK;
90 }
91 
Sha256(const std::string & text,bool isUpper)92 std::string Crypto::Sha256(const std::string &text, bool isUpper)
93 {
94     return Sha256(text.data(), text.size(), isUpper);
95 }
96 
Sha256(const void * data,size_t size,bool isUpper)97 std::string Crypto::Sha256(const void *data, size_t size, bool isUpper)
98 {
99     unsigned char hash[SHA256_DIGEST_LENGTH * HEX_TO_UINT8 + 1] = "";
100     DmGenerateStrHash(data, size, hash, HexifyLen(SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH);
101     // here we translate sha256 hash to hexadecimal. each 8-bit char will be presented by two characters([0-9a-f])
102     const char* hexCode = isUpper ? "0123456789ABCDEF" : "0123456789abcdef";
103     for (int32_t i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
104         unsigned char value = hash[SHA256_DIGEST_LENGTH + i];
105         // uint8_t is 2 digits in hexadecimal.
106         hash[i * HEX_TO_UINT8] = hexCode[(value >> WIDTH) & MASK];
107         hash[i * HEX_TO_UINT8 + 1] = hexCode[value & MASK];
108     }
109     hash[SHA256_DIGEST_LENGTH * HEX_TO_UINT8] = 0;
110     std::stringstream ss;
111     ss << hash;
112     return ss.str();
113 }
114 
GetUdidHash(const std::string & udid,unsigned char * udidHash)115 int32_t Crypto::GetUdidHash(const std::string &udid, unsigned char *udidHash)
116 {
117     unsigned char hash[SHA256_DIGEST_LENGTH] = "";
118     DmGenerateStrHash(udid.data(), udid.size(), hash, SHA256_DIGEST_LENGTH, 0);
119     if (ConvertBytesToHexString(reinterpret_cast<char *>(udidHash), SHORT_DEVICE_ID_HASH_LENGTH + 1,
120         reinterpret_cast<const uint8_t *>(hash), SHORT_DEVICE_ID_HASH_LENGTH / HEX_TO_UINT8) != DM_OK) {
121         LOGE("ConvertBytesToHexString failed.");
122         return ERR_DM_FAILED;
123     }
124     return DM_OK;
125 }
126 
ConvertHexStringToBytes(unsigned char * outBuf,uint32_t outBufLen,const char * inBuf,uint32_t inLen)127 int32_t Crypto::ConvertHexStringToBytes(unsigned char *outBuf, uint32_t outBufLen, const char *inBuf,
128     uint32_t inLen)
129 {
130     (void)outBufLen;
131     if ((outBuf == NULL) || (inBuf == NULL) || (inLen % HEX_TO_UINT8 != 0)) {
132         LOGE("invalid param");
133         return ERR_DM_FAILED;
134     }
135 
136     uint32_t outLen = inLen / HEX_TO_UINT8;
137     uint32_t i = 0;
138     while (i < outLen) {
139         unsigned char c = *inBuf++;
140         if ((c >= '0') && (c <= '9')) {
141             c -= '0';
142         } else if ((c >= 'a') && (c <= 'f')) {
143             c -= 'a' - DEC_MAX_NUM;
144         } else if ((c >= 'A') && (c <= 'F')) {
145             c -= 'A' - DEC_MAX_NUM;
146         } else {
147             LOGE("HexToString Error! %{public}c", c);
148             return ERR_DM_FAILED;
149         }
150         unsigned char c2 = *inBuf++;
151         if ((c2 >= '0') && (c2 <= '9')) {
152             c2 -= '0';
153         } else if ((c2 >= 'a') && (c2 <= 'f')) {
154             c2 -= 'a' - DEC_MAX_NUM;
155         } else if ((c2 >= 'A') && (c2 <= 'F')) {
156             c2 -= 'A' - DEC_MAX_NUM;
157         } else {
158             LOGE("HexToString Error! %{public}c", c2);
159             return ERR_DM_FAILED;
160         }
161         *outBuf++ = (c << HEX_MAX_BIT_NUM) | c2;
162         i++;
163     }
164     return DM_OK;
165 }
166 
GetGroupIdHash(const std::string & groupId)167 std::string Crypto::GetGroupIdHash(const std::string &groupId)
168 {
169     unsigned char hash[SHA256_DIGEST_LENGTH] = "";
170     DmGenerateStrHash(groupId.data(), groupId.size(), hash, SHA256_DIGEST_LENGTH, 0);
171     std::stringstream ss;
172     for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
173         ss << std::hex << (int)hash[i];
174     }
175     return ss.str().substr(0, SHORT_DEVICE_ID_HASH_LENGTH);
176 }
177 
GetSecRandom(uint8_t * out,size_t outLen)178 int32_t Crypto::GetSecRandom(uint8_t *out, size_t outLen)
179 {
180     if (out == NULL) {
181         return DM_ERR;
182     }
183 
184     if (outLen == 0) {
185         return DM_ERR;
186     }
187 
188     RAND_poll();
189     RAND_bytes(out, outLen);
190     return DM_OK;
191 }
192 
GetSecSalt()193 std::string Crypto::GetSecSalt()
194 {
195     uint8_t out[SALT_LENGTH] = {0};
196     if (Crypto::GetSecRandom(out, SALT_LENGTH) != DM_OK) {
197         return SALT_DEFAULT;
198     }
199 
200     char outHex[SALT_LENGTH * HEX_TO_UINT8 + 1] = {0};
201     if (ConvertBytesToHexString(outHex, SALT_LENGTH * HEX_TO_UINT8 + 1, out, SALT_LENGTH) != DM_OK) {
202         return SALT_DEFAULT;
203     }
204 
205     return std::string(outHex);
206 }
207 
GetHashWithSalt(const std::string & text,const std::string & salt)208 std::string Crypto::GetHashWithSalt(const std::string &text, const std::string &salt)
209 {
210     std::string rawText = text + salt;
211     return Crypto::Sha256(rawText);
212 }
213 
GetAccountIdHash(const std::string & accountId,unsigned char * accountIdHash)214 int32_t Crypto::GetAccountIdHash(const std::string &accountId, unsigned char *accountIdHash)
215 {
216     unsigned char hash[SHA256_DIGEST_LENGTH] = "";
217     DmGenerateStrHash(accountId.data(), accountId.size(), hash, SHA256_DIGEST_LENGTH, 0);
218     if (ConvertBytesToHexString(reinterpret_cast<char *>(accountIdHash), SHORT_ACCOUNTID_ID_HASH_LENGTH + 1,
219         reinterpret_cast<const uint8_t *>(hash), SHORT_ACCOUNTID_ID_HASH_LENGTH / HEX_TO_UINT8) != DM_OK) {
220         LOGE("ConvertBytesToHexString failed.");
221         return ERR_DM_FAILED;
222     }
223     return DM_OK;
224 }
225 
226 #if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
ConvertUdidHashToAnoyAndSave(const std::string & appId,const std::string & udidHash,DmKVValue & kvValue)227 int32_t Crypto::ConvertUdidHashToAnoyAndSave(const std::string &appId, const std::string &udidHash,
228     DmKVValue &kvValue)
229 {
230     if (GetAnoyDeviceInfo(appId, udidHash, kvValue) == DM_OK) {
231         kvValue.lastModifyTime = GetSecondsSince1970ToNow();
232         KVAdapterManager::GetInstance().PutByAnoyDeviceId(kvValue.anoyDeviceId, kvValue);
233         return DM_OK;
234     }
235     int32_t ret = ConvertUdidHashToAnoyGenerate(appId, udidHash, kvValue);
236     if (ret != DM_OK) {
237         LOGE("failed");
238         return ERR_DM_FAILED;
239     }
240     KVAdapterManager::GetInstance().PutByAnoyDeviceId(kvValue.anoyDeviceId, kvValue);
241     return DM_OK;
242 }
243 
ConvertUdidHashToAnoyDeviceId(const std::string & appId,const std::string & udidHash,DmKVValue & kvValue)244 int32_t Crypto::ConvertUdidHashToAnoyDeviceId(const std::string &appId, const std::string &udidHash,
245     DmKVValue &kvValue)
246 {
247     LOGI("start.");
248     if (GetAnoyDeviceInfo(appId, udidHash, kvValue) == DM_OK) {
249         return DM_OK;
250     }
251     return ConvertUdidHashToAnoyGenerate(appId, udidHash, kvValue);
252 }
253 
GetAnoyDeviceInfo(const std::string & appId,const std::string & udidHash,DmKVValue & kvValue)254 int32_t Crypto::GetAnoyDeviceInfo(const std::string &appId, const std::string &udidHash, DmKVValue &kvValue)
255 {
256     LOGI("start");
257     std::string udidPrefix = appId + DB_KEY_DELIMITER + udidHash;
258     if (KVAdapterManager::GetInstance().Get(udidPrefix, kvValue) != DM_OK) {
259         LOGI("Get kv value from DB failed");
260         return ERR_DM_FAILED;
261     }
262     return DM_OK;
263 }
264 
ConvertUdidHashToAnoyGenerate(const std::string & appId,const std::string & udidHash,DmKVValue & kvValue)265 int32_t Crypto::ConvertUdidHashToAnoyGenerate(const std::string &appId, const std::string &udidHash,
266     DmKVValue &kvValue)
267 {
268     LOGI("start.");
269     std::string salt = GetSecSalt();
270     std::string udidTemp = appId + DB_KEY_DELIMITER + udidHash + DB_KEY_DELIMITER + salt;
271     char anoyDeviceId[DM_MAX_DEVICE_ID_LEN] = {0};
272     if (GetUdidHash(udidTemp, reinterpret_cast<uint8_t *>(anoyDeviceId)) != DM_OK) {
273         LOGE("get anoyDeviceId by udidTemp failed.");
274         return ERR_DM_FAILED;
275     }
276     kvValue.udidHash = udidHash;
277     kvValue.anoyDeviceId = std::string(anoyDeviceId);
278     kvValue.appID = appId;
279     kvValue.salt = salt;
280     kvValue.lastModifyTime = GetSecondsSince1970ToNow();
281     return DM_OK;
282 }
283 #endif
284 } // namespace DistributedHardware
285 } // namespace OHOS
286