1 /*
2 * Copyright (c) 2022 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 "softbus_adapter_crypto.h"
17
18 #include <securec.h>
19
20 #include <openssl/evp.h>
21 #include <openssl/rand.h>
22 #include "softbus_adapter_file.h"
23 #include "softbus_adapter_log.h"
24 #include "softbus_errcode.h"
25
26 static pthread_mutex_t g_randomLock = PTHREAD_MUTEX_INITIALIZER;
27
28 #define OPENSSL_EVP_PADDING_FUNC_OPEN (1)
29 #define OPENSSL_EVP_PADDING_FUNC_CLOSE (0)
30
31 #define EVP_AES_128_GCM_KEYLEN 16
32 #define EVP_AES_256_GCM_KEYLEN 32
33
GetSslAlgorithmByKeyLen(uint32_t keyLen)34 static EVP_CIPHER *GetSslAlgorithmByKeyLen(uint32_t keyLen)
35 {
36 switch (keyLen) {
37 case EVP_AES_128_GCM_KEYLEN:
38 return (EVP_CIPHER *)EVP_aes_128_gcm();
39 case EVP_AES_256_GCM_KEYLEN:
40 return (EVP_CIPHER *)EVP_aes_256_gcm();
41 }
42 return NULL;
43 }
44
OpensslEvpInit(EVP_CIPHER_CTX ** ctx,const AesGcmCipherKey * cipherkey,bool mode)45 static int32_t OpensslEvpInit(EVP_CIPHER_CTX **ctx, const AesGcmCipherKey *cipherkey, bool mode)
46 {
47 EVP_CIPHER *cipher = GetSslAlgorithmByKeyLen(cipherkey->keyLen);
48 if (cipher == NULL) {
49 HILOG_ERROR(SOFTBUS_HILOG_ID, "get cipher fail.");
50 return SOFTBUS_DECRYPT_ERR;
51 }
52 int32_t ret;
53 *ctx = EVP_CIPHER_CTX_new();
54 if (*ctx == NULL) {
55 return SOFTBUS_DECRYPT_ERR;
56 }
57 EVP_CIPHER_CTX_set_padding(*ctx, OPENSSL_EVP_PADDING_FUNC_OPEN);
58 if (mode == true) {
59 ret = EVP_EncryptInit_ex(*ctx, cipher, NULL, NULL, NULL);
60 if (ret != 1) {
61 HILOG_ERROR(SOFTBUS_HILOG_ID, "EVP_EncryptInit_ex fail.");
62 EVP_CIPHER_CTX_free(*ctx);
63 return SOFTBUS_DECRYPT_ERR;
64 }
65 } else {
66 ret = EVP_DecryptInit_ex(*ctx, cipher, NULL, NULL, NULL);
67 if (ret != 1) {
68 HILOG_ERROR(SOFTBUS_HILOG_ID, "EVP_DecryptInit_ex fail.");
69 EVP_CIPHER_CTX_free(*ctx);
70 return SOFTBUS_DECRYPT_ERR;
71 }
72 }
73 ret = EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_GCM_SET_IVLEN, GCM_IV_LEN, NULL);
74 if (ret != 1) {
75 HILOG_ERROR(SOFTBUS_HILOG_ID, "Set iv len fail.");
76 EVP_CIPHER_CTX_free(*ctx);
77 return SOFTBUS_DECRYPT_ERR;
78 }
79 return SOFTBUS_OK;
80 }
81
PackIvAndTag(EVP_CIPHER_CTX * ctx,const AesGcmCipherKey * cipherkey,uint32_t dataLen,unsigned char * cipherText,uint32_t cipherTextLen)82 static int32_t PackIvAndTag(EVP_CIPHER_CTX *ctx, const AesGcmCipherKey *cipherkey,
83 uint32_t dataLen, unsigned char *cipherText, uint32_t cipherTextLen)
84 {
85 if ((dataLen + OVERHEAD_LEN) > cipherTextLen) {
86 HILOG_ERROR(SOFTBUS_HILOG_ID, "Encrypt invalid para.");
87 return SOFTBUS_ENCRYPT_ERR;
88 }
89 if (memcpy_s(cipherText, cipherTextLen - dataLen, cipherkey->iv, GCM_IV_LEN) != EOK) {
90 HILOG_ERROR(SOFTBUS_HILOG_ID, "EVP memcpy iv fail.");
91 return SOFTBUS_ENCRYPT_ERR;
92 }
93 char tagbuf[TAG_LEN];
94 int ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, TAG_LEN, (void *)tagbuf);
95 if (ret != 1) {
96 HILOG_ERROR(SOFTBUS_HILOG_ID, "EVP_CIPHER_CTX_ctrl fail.");
97 return SOFTBUS_DECRYPT_ERR;
98 }
99 if (memcpy_s(cipherText + dataLen + GCM_IV_LEN,
100 cipherTextLen - dataLen - GCM_IV_LEN, tagbuf, TAG_LEN) != EOK) {
101 HILOG_ERROR(SOFTBUS_HILOG_ID, "EVP memcpy tag fail.");
102 return SOFTBUS_ENCRYPT_ERR;
103 }
104 return SOFTBUS_OK;
105 }
106
SslAesGcmEncrypt(const AesGcmCipherKey * cipherkey,const unsigned char * plainText,uint32_t plainTextSize,unsigned char * cipherText,uint32_t cipherTextLen)107 static int32_t SslAesGcmEncrypt(const AesGcmCipherKey *cipherkey, const unsigned char *plainText,
108 uint32_t plainTextSize, unsigned char *cipherText, uint32_t cipherTextLen)
109 {
110 if ((cipherkey == NULL) || (plainText == NULL) || (plainTextSize == 0) || cipherText == NULL ||
111 (cipherTextLen < plainTextSize + OVERHEAD_LEN)) {
112 HILOG_ERROR(SOFTBUS_HILOG_ID, "Encrypt invalid para.");
113 return SOFTBUS_INVALID_PARAM;
114 }
115
116 int32_t outlen = 0;
117 int32_t outbufLen;
118 EVP_CIPHER_CTX *ctx = NULL;
119 int32_t ret = OpensslEvpInit(&ctx, cipherkey, true);
120 if (ret != SOFTBUS_OK) {
121 HILOG_ERROR(SOFTBUS_HILOG_ID, "OpensslEvpInit fail.");
122 return SOFTBUS_DECRYPT_ERR;
123 }
124 ret = EVP_EncryptInit_ex(ctx, NULL, NULL, cipherkey->key, cipherkey->iv);
125 if (ret != 1) {
126 HILOG_ERROR(SOFTBUS_HILOG_ID, "EVP_EncryptInit_ex fail.");
127 EVP_CIPHER_CTX_free(ctx);
128 return SOFTBUS_DECRYPT_ERR;
129 }
130 ret = EVP_EncryptUpdate(ctx, cipherText + GCM_IV_LEN,
131 (int32_t *)&outbufLen, plainText, plainTextSize);
132 if (ret != 1) {
133 HILOG_ERROR(SOFTBUS_HILOG_ID, "EVP_EncryptUpdate fail.");
134 EVP_CIPHER_CTX_free(ctx);
135 return SOFTBUS_DECRYPT_ERR;
136 }
137 outlen += outbufLen;
138 ret = EVP_EncryptFinal_ex(ctx, cipherText + GCM_IV_LEN + outbufLen, (int32_t *)&outbufLen);
139 if (ret != 1) {
140 HILOG_ERROR(SOFTBUS_HILOG_ID, "EVP_EncryptFinal_ex fail.");
141 EVP_CIPHER_CTX_free(ctx);
142 return SOFTBUS_DECRYPT_ERR;
143 }
144 outlen += outbufLen;
145 ret = PackIvAndTag(ctx, cipherkey, outlen, cipherText, cipherTextLen);
146 if (ret != SOFTBUS_OK) {
147 HILOG_ERROR(SOFTBUS_HILOG_ID, "pack iv and tag fail.");
148 EVP_CIPHER_CTX_free(ctx);
149 return SOFTBUS_DECRYPT_ERR;
150 }
151 EVP_CIPHER_CTX_free(ctx);
152 return (outlen + OVERHEAD_LEN);
153 }
154
SslAesGcmDecrypt(const AesGcmCipherKey * cipherkey,const unsigned char * cipherText,uint32_t cipherTextSize,unsigned char * plain,uint32_t plainLen)155 static int32_t SslAesGcmDecrypt(const AesGcmCipherKey *cipherkey, const unsigned char *cipherText,
156 uint32_t cipherTextSize, unsigned char *plain, uint32_t plainLen)
157 {
158 if ((cipherkey == NULL) || (cipherText == NULL) || (cipherTextSize <= OVERHEAD_LEN) || plain == NULL ||
159 (plainLen < cipherTextSize - OVERHEAD_LEN)) {
160 HILOG_ERROR(SOFTBUS_HILOG_ID, "Decrypt invalid para.");
161 return SOFTBUS_INVALID_PARAM;
162 }
163
164 int32_t outlen = 0;
165 EVP_CIPHER_CTX *ctx = NULL;
166 int32_t ret = OpensslEvpInit(&ctx, cipherkey, false);
167 if (ret != SOFTBUS_OK) {
168 HILOG_ERROR(SOFTBUS_HILOG_ID, "OpensslEvpInit fail.");
169 return SOFTBUS_DECRYPT_ERR;
170 }
171 ret = EVP_DecryptInit_ex(ctx, NULL, NULL, cipherkey->key, cipherkey->iv);
172 if (ret != 1) {
173 HILOG_ERROR(SOFTBUS_HILOG_ID, "EVP_EncryptInit_ex fail.");
174 EVP_CIPHER_CTX_free(ctx);
175 return SOFTBUS_DECRYPT_ERR;
176 }
177 ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, TAG_LEN,
178 (void *)(cipherText + (cipherTextSize - TAG_LEN)));
179 if (ret != 1) {
180 HILOG_ERROR(SOFTBUS_HILOG_ID, "EVP_DecryptUpdate fail.");
181 EVP_CIPHER_CTX_free(ctx);
182 return SOFTBUS_DECRYPT_ERR;
183 }
184 ret = EVP_DecryptUpdate(ctx, plain, (int32_t *)&plainLen,
185 cipherText + GCM_IV_LEN, cipherTextSize - OVERHEAD_LEN);
186 if (ret != 1) {
187 HILOG_ERROR(SOFTBUS_HILOG_ID, "EVP_DecryptUpdate fail.");
188 EVP_CIPHER_CTX_free(ctx);
189 return SOFTBUS_DECRYPT_ERR;
190 }
191 outlen += plainLen;
192 ret = EVP_DecryptFinal_ex(ctx, plain + plainLen, (int32_t *)&plainLen);
193 if (ret != 1) {
194 HILOG_ERROR(SOFTBUS_HILOG_ID, "EVP_DecryptFinal_ex fail.");
195 EVP_CIPHER_CTX_free(ctx);
196 return SOFTBUS_DECRYPT_ERR;
197 }
198 outlen += plainLen;
199 EVP_CIPHER_CTX_free(ctx);
200 return outlen;
201 }
202
SoftBusBase64Encode(unsigned char * dst,size_t dlen,size_t * olen,const unsigned char * src,size_t slen)203 int32_t SoftBusBase64Encode(unsigned char *dst, size_t dlen,
204 size_t *olen, const unsigned char *src, size_t slen)
205 {
206 if (dst == NULL || dlen == 0 || olen == NULL || src == NULL || slen == 0) {
207 return SOFTBUS_INVALID_PARAM;
208 }
209 *olen = 0;
210 int32_t outlen;
211 EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
212 if (ctx == NULL) {
213 return SOFTBUS_DECRYPT_ERR;
214 }
215 EVP_EncodeInit(ctx);
216 int32_t ret = EVP_EncodeUpdate(ctx, dst, &outlen, src, slen);
217 if (ret != 1) {
218 HILOG_ERROR(SOFTBUS_HILOG_ID, "[TRANS] EVP_EncodeUpdate fail.");
219 EVP_ENCODE_CTX_free(ctx);
220 return SOFTBUS_DECRYPT_ERR;
221 }
222 *olen += outlen;
223 EVP_EncodeFinal(ctx, dst + outlen, &outlen);
224 *olen += outlen;
225 if ((*olen > 0) && (dst[*olen - 1] == '\n')) {
226 (*olen)--;
227 dst[*olen] = 0;
228 }
229 EVP_ENCODE_CTX_free(ctx);
230 return SOFTBUS_OK;
231 }
232
SoftBusBase64Decode(unsigned char * dst,size_t dlen,size_t * olen,const unsigned char * src,size_t slen)233 int32_t SoftBusBase64Decode(unsigned char *dst, size_t dlen,
234 size_t *olen, const unsigned char *src, size_t slen)
235 {
236 if (dst == NULL || dlen == 0 || olen == NULL || src == NULL || slen == 0) {
237 return SOFTBUS_INVALID_PARAM;
238 }
239 *olen = 0;
240 int32_t outlen;
241 EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
242 if (ctx == NULL) {
243 return SOFTBUS_DECRYPT_ERR;
244 }
245 EVP_DecodeInit(ctx);
246 int32_t ret = EVP_DecodeUpdate(ctx, dst, &outlen, src, slen);
247 if (ret == -1) {
248 HILOG_ERROR(SOFTBUS_HILOG_ID, "[TRANS] EVP_DecodeUpdate fail.");
249 EVP_ENCODE_CTX_free(ctx);
250 return SOFTBUS_DECRYPT_ERR;
251 }
252 *olen += outlen;
253 ret = EVP_DecodeFinal(ctx, dst + outlen, &outlen);
254 if (ret != 1) {
255 HILOG_ERROR(SOFTBUS_HILOG_ID, "[TRANS] EVP_DecodeFinal fail.");
256 EVP_ENCODE_CTX_free(ctx);
257 return SOFTBUS_DECRYPT_ERR;
258 }
259 *olen += outlen;
260 EVP_ENCODE_CTX_free(ctx);
261 return SOFTBUS_OK;
262 }
263
SoftBusGenerateStrHash(const unsigned char * str,uint32_t len,unsigned char * hash)264 int32_t SoftBusGenerateStrHash(const unsigned char *str, uint32_t len, unsigned char *hash)
265 {
266 if (str == NULL || hash == NULL || len == 0) {
267 return SOFTBUS_INVALID_PARAM;
268 }
269 uint32_t olen;
270 int32_t ret = EVP_Digest(str, len, hash, &olen, EVP_sha256(), NULL);
271 if (ret != 1) {
272 HILOG_ERROR(SOFTBUS_HILOG_ID, "[TRANS] Get Openssl Hash fail.");
273 return SOFTBUS_DECRYPT_ERR;
274 }
275 return SOFTBUS_OK;
276 }
277
SoftBusGenerateRandomArray(unsigned char * randStr,uint32_t len)278 int32_t SoftBusGenerateRandomArray(unsigned char *randStr, uint32_t len)
279 {
280 if (randStr == NULL || len == 0) {
281 return SOFTBUS_INVALID_PARAM;
282 }
283
284 static bool initFlag = false;
285 int32_t ret;
286
287 if (pthread_mutex_lock(&g_randomLock) != 0) {
288 HILOG_ERROR(SOFTBUS_HILOG_ID, "lock mutex failed.");
289 return SOFTBUS_ERR;
290 }
291
292 if (initFlag == false) {
293 RAND_seed(randStr, (int32_t)len);
294 initFlag = true;
295 }
296
297 ret = RAND_bytes(randStr, (int32_t)len);
298 pthread_mutex_unlock(&g_randomLock);
299 if (ret != 1) {
300 HILOG_ERROR(SOFTBUS_HILOG_ID, "gen random error, ret[%d]", ret);
301 return SOFTBUS_ERR;
302 }
303 return SOFTBUS_OK;
304 }
305
SoftBusGenerateSessionKey(char * key,uint32_t len)306 int32_t SoftBusGenerateSessionKey(char *key, uint32_t len)
307 {
308 if (SoftBusGenerateRandomArray((unsigned char*)key, len) != SOFTBUS_OK) {
309 HILOG_ERROR(SOFTBUS_HILOG_ID, "generate sessionKey error.");
310 return SOFTBUS_ENCRYPT_ERR;
311 }
312 return SOFTBUS_OK;
313 }
314
SoftBusEncryptData(AesGcmCipherKey * cipherKey,const unsigned char * input,uint32_t inLen,unsigned char * encryptData,uint32_t * encryptLen)315 int32_t SoftBusEncryptData(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
316 unsigned char *encryptData, uint32_t *encryptLen)
317 {
318 if (cipherKey == NULL || input == NULL || inLen == 0 || encryptData == NULL || encryptLen == NULL) {
319 return SOFTBUS_INVALID_PARAM;
320 }
321
322 if (SoftBusGenerateRandomArray(cipherKey->iv, sizeof(cipherKey->iv)) != SOFTBUS_OK) {
323 HILOG_ERROR(SOFTBUS_HILOG_ID, "generate random iv error.");
324 return SOFTBUS_ENCRYPT_ERR;
325 }
326 uint32_t outLen = inLen + OVERHEAD_LEN;
327 int32_t result = SslAesGcmEncrypt(cipherKey, input, inLen, encryptData, outLen);
328 if (result <= 0) {
329 return SOFTBUS_ENCRYPT_ERR;
330 }
331 *encryptLen = result;
332 return SOFTBUS_OK;
333 }
334
SoftBusEncryptDataWithSeq(AesGcmCipherKey * cipherKey,const unsigned char * input,uint32_t inLen,unsigned char * encryptData,uint32_t * encryptLen,int32_t seqNum)335 int32_t SoftBusEncryptDataWithSeq(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
336 unsigned char *encryptData, uint32_t *encryptLen, int32_t seqNum)
337 {
338 if (cipherKey == NULL || input == NULL || inLen == 0 || encryptData == NULL || encryptLen == NULL) {
339 return SOFTBUS_INVALID_PARAM;
340 }
341 if (SoftBusGenerateRandomArray(cipherKey->iv, sizeof(cipherKey->iv)) != SOFTBUS_OK) {
342 HILOG_ERROR(SOFTBUS_HILOG_ID, "generate random iv error.");
343 return SOFTBUS_ENCRYPT_ERR;
344 }
345 if (memcpy_s(cipherKey->iv, sizeof(int32_t), &seqNum, sizeof(int32_t)) != EOK) {
346 return SOFTBUS_ENCRYPT_ERR;
347 }
348 uint32_t outLen = inLen + OVERHEAD_LEN;
349 int32_t result = SslAesGcmEncrypt(cipherKey, input, inLen, encryptData, outLen);
350 if (result <= 0) {
351 return SOFTBUS_ENCRYPT_ERR;
352 }
353 *encryptLen = result;
354 return SOFTBUS_OK;
355 }
356
SoftBusDecryptData(AesGcmCipherKey * cipherKey,const unsigned char * input,uint32_t inLen,unsigned char * decryptData,uint32_t * decryptLen)357 int32_t SoftBusDecryptData(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
358 unsigned char *decryptData, uint32_t *decryptLen)
359 {
360 if (cipherKey == NULL || input == NULL || inLen < GCM_IV_LEN || decryptData == NULL || decryptLen == NULL) {
361 return SOFTBUS_INVALID_PARAM;
362 }
363
364 if (memcpy_s(cipherKey->iv, sizeof(cipherKey->iv), input, GCM_IV_LEN) != EOK) {
365 HILOG_ERROR(SOFTBUS_HILOG_ID, "copy iv failed.");
366 return SOFTBUS_ENCRYPT_ERR;
367 }
368 uint32_t outLen = inLen - OVERHEAD_LEN;
369 int32_t result = SslAesGcmDecrypt(cipherKey, input, inLen, decryptData, outLen);
370 if (result <= 0) {
371 return SOFTBUS_ENCRYPT_ERR;
372 }
373 *decryptLen = (uint32_t)result;
374 return SOFTBUS_OK;
375 }
376
SoftBusDecryptDataWithSeq(AesGcmCipherKey * cipherKey,const unsigned char * input,uint32_t inLen,unsigned char * decryptData,uint32_t * decryptLen,int32_t seqNum)377 int32_t SoftBusDecryptDataWithSeq(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
378 unsigned char *decryptData, uint32_t *decryptLen, int32_t seqNum)
379 {
380 (void)seqNum;
381 return SoftBusDecryptData(cipherKey, input, inLen, decryptData, decryptLen);
382 }
383
SoftBusCryptoRand(void)384 uint32_t SoftBusCryptoRand(void)
385 {
386 int32_t fd = SoftBusOpenFile("/dev/urandom", SOFTBUS_O_RDONLY);
387 if (fd < 0) {
388 HILOG_ERROR(SOFTBUS_HILOG_ID, "CryptoRand open file fail");
389 return 0;
390 }
391 uint32_t value = 0;
392 int32_t len = SoftBusReadFile(fd, &value, sizeof(uint32_t));
393 if (len < 0) {
394 HILOG_ERROR(SOFTBUS_HILOG_ID, "CryptoRand read file fail");
395 return 0;
396 }
397 SoftBusCloseFile(fd);
398 return value;
399 }
400