1 /*
2  * Copyright (c) 2021 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 "comm_log.h"
21 #include "mbedtls/base64.h"
22 #include "mbedtls/cipher.h"
23 #include "mbedtls/ctr_drbg.h"
24 #include "mbedtls/entropy.h"
25 #include "mbedtls/gcm.h"
26 #include "mbedtls/md.h"
27 #include "mbedtls/platform.h"
28 #include "softbus_adapter_file.h"
29 #include "softbus_errcode.h"
30 
31 #ifndef MBEDTLS_CTR_DRBG_C
32 #define MBEDTLS_CTR_DRBG_C
33 #endif
34 
35 #ifndef MBEDTLS_MD_C
36 #define MBEDTLS_MD_C
37 #endif
38 
39 #ifndef MBEDTLS_SHA256_C
40 #define MBEDTLS_SHA256_C
41 #endif
42 
43 #ifndef MBEDTLS_ENTROPY_C
44 #define MBEDTLS_ENTROPY_C
45 #endif
46 
47 #ifndef MBEDTLS_CIPHER_MODE_CTR
48 #define MBEDTLS_CIPHER_MODE_CTR
49 #endif
50 
51 #ifndef MBEDTLS_AES_C
52 #define MBEDTLS_AES_C
53 #endif
54 
55 #ifndef MBEDTLS_CIPHER_C
56 #define MBEDTLS_CIPHER_C
57 #endif
58 
59 #define EVP_AES_128_KEYLEN 16
60 #define EVP_AES_256_KEYLEN 32
61 #define BYTES_BIT_NUM 8
62 
63 static SoftBusMutex g_randomLock;
64 
GetCtrAlgorithmByKeyLen(uint32_t keyLen)65 static mbedtls_cipher_type_t GetCtrAlgorithmByKeyLen(uint32_t keyLen)
66 {
67     switch (keyLen) {
68         case EVP_AES_128_KEYLEN:
69             return MBEDTLS_CIPHER_ARIA_128_CTR;
70         case EVP_AES_256_KEYLEN:
71             return MBEDTLS_CIPHER_ARIA_256_CTR;
72         default:
73             return MBEDTLS_CIPHER_NONE;
74     }
75     return MBEDTLS_CIPHER_NONE;
76 }
77 
MbedAesGcmEncrypt(const AesGcmCipherKey * cipherKey,const unsigned char * plainText,uint32_t plainTextSize,unsigned char * cipherText,uint32_t cipherTextLen)78 static int32_t MbedAesGcmEncrypt(const AesGcmCipherKey *cipherKey, const unsigned char *plainText,
79     uint32_t plainTextSize, unsigned char *cipherText, uint32_t cipherTextLen)
80 {
81     if ((cipherKey == NULL) || (plainText == NULL) || (plainTextSize == 0) || cipherText == NULL ||
82         (cipherTextLen < plainTextSize + OVERHEAD_LEN)) {
83         COMM_LOGE(COMM_ADAPTER, "Encrypt invalid para");
84         return SOFTBUS_INVALID_PARAM;
85     }
86 
87     int32_t ret;
88     unsigned char tagBuf[TAG_LEN] = { 0 };
89     mbedtls_gcm_context aesContext;
90     mbedtls_gcm_init(&aesContext);
91 
92     ret = mbedtls_gcm_setkey(&aesContext, MBEDTLS_CIPHER_ID_AES, cipherKey->key, cipherKey->keyLen * KEY_BITS_UNIT);
93     if (ret != 0) {
94         mbedtls_gcm_free(&aesContext);
95         return SOFTBUS_ENCRYPT_ERR;
96     }
97 
98     ret = mbedtls_gcm_crypt_and_tag(&aesContext, MBEDTLS_GCM_ENCRYPT, plainTextSize, cipherKey->iv, GCM_IV_LEN, NULL, 0,
99         plainText, cipherText + GCM_IV_LEN, TAG_LEN, tagBuf);
100     if (ret != 0) {
101         mbedtls_gcm_free(&aesContext);
102         return SOFTBUS_ENCRYPT_ERR;
103     }
104 
105     if (memcpy_s(cipherText, cipherTextLen, cipherKey->iv, GCM_IV_LEN) != EOK) {
106         mbedtls_gcm_free(&aesContext);
107         return SOFTBUS_ENCRYPT_ERR;
108     }
109 
110     if (memcpy_s(cipherText + GCM_IV_LEN + plainTextSize, cipherTextLen - GCM_IV_LEN - plainTextSize, tagBuf,
111         TAG_LEN) != 0) {
112         mbedtls_gcm_free(&aesContext);
113         return SOFTBUS_ENCRYPT_ERR;
114     }
115 
116     mbedtls_gcm_free(&aesContext);
117     return (plainTextSize + OVERHEAD_LEN);
118 }
119 
MbedAesGcmDecrypt(const AesGcmCipherKey * cipherKey,const unsigned char * cipherText,uint32_t cipherTextSize,unsigned char * plain,uint32_t plainLen)120 static int32_t MbedAesGcmDecrypt(const AesGcmCipherKey *cipherKey, const unsigned char *cipherText,
121     uint32_t cipherTextSize, unsigned char *plain, uint32_t plainLen)
122 {
123     if ((cipherKey == NULL) || (cipherText == NULL) || (cipherTextSize <= OVERHEAD_LEN) || plain == NULL ||
124         (plainLen < cipherTextSize - OVERHEAD_LEN)) {
125         COMM_LOGE(COMM_ADAPTER, "Decrypt invalid para");
126         return SOFTBUS_INVALID_PARAM;
127     }
128 
129     mbedtls_gcm_context aesContext;
130     mbedtls_gcm_init(&aesContext);
131     int32_t ret =
132         mbedtls_gcm_setkey(&aesContext, MBEDTLS_CIPHER_ID_AES, cipherKey->key, cipherKey->keyLen * KEY_BITS_UNIT);
133     if (ret != 0) {
134         COMM_LOGE(COMM_ADAPTER, "Decrypt mbedtls_gcm_setkey fail.");
135         mbedtls_gcm_free(&aesContext);
136         return SOFTBUS_DECRYPT_ERR;
137     }
138 
139     int32_t actualPlainLen = (int32_t)(cipherTextSize - OVERHEAD_LEN);
140     ret = mbedtls_gcm_auth_decrypt(&aesContext, cipherTextSize - OVERHEAD_LEN, cipherKey->iv, GCM_IV_LEN, NULL, 0,
141         cipherText + actualPlainLen + GCM_IV_LEN, TAG_LEN, cipherText + GCM_IV_LEN, plain);
142     if (ret != 0) {
143         COMM_LOGE(COMM_ADAPTER, "[TRANS] Decrypt mbedtls_gcm_auth_decrypt fail. ret=%{public}d", ret);
144         mbedtls_gcm_free(&aesContext);
145         return SOFTBUS_DECRYPT_ERR;
146     }
147 
148     mbedtls_gcm_free(&aesContext);
149     return actualPlainLen;
150 }
151 
HandleError(mbedtls_cipher_context_t * ctx,const char * buf)152 static int32_t HandleError(mbedtls_cipher_context_t *ctx, const char *buf)
153 {
154     if (buf != NULL) {
155         COMM_LOGE(COMM_ADAPTER, "buf=%{public}s", buf);
156     }
157     if (ctx != NULL) {
158         mbedtls_cipher_free(ctx);
159     }
160     return SOFTBUS_DECRYPT_ERR;
161 }
162 
SoftBusBase64Encode(unsigned char * dst,size_t dlen,size_t * olen,const unsigned char * src,size_t slen)163 int32_t SoftBusBase64Encode(unsigned char *dst, size_t dlen,
164     size_t *olen, const unsigned char *src, size_t slen)
165 {
166     if (dst == NULL || dlen == 0 || olen == NULL || src == NULL || slen == 0) {
167         COMM_LOGE(COMM_ADAPTER, "base64 encode invalid para");
168         return SOFTBUS_INVALID_PARAM;
169     }
170     return mbedtls_base64_encode(dst, dlen, olen, src, slen);
171 }
172 
SoftBusBase64Decode(unsigned char * dst,size_t dlen,size_t * olen,const unsigned char * src,size_t slen)173 int32_t SoftBusBase64Decode(unsigned char *dst, size_t dlen,
174     size_t *olen, const unsigned char *src, size_t slen)
175 {
176     if (dst == NULL || dlen == 0 || olen == NULL || src == NULL || slen == 0) {
177         COMM_LOGE(COMM_ADAPTER, "base64 decode invalid para");
178         return SOFTBUS_INVALID_PARAM;
179     }
180     return mbedtls_base64_decode(dst, dlen, olen, src, slen);
181 }
182 
SoftBusGenerateStrHash(const unsigned char * str,uint32_t len,unsigned char * hash)183 int32_t SoftBusGenerateStrHash(const unsigned char *str, uint32_t len, unsigned char *hash)
184 {
185     if (str == NULL || hash == NULL || len == 0) {
186         return SOFTBUS_INVALID_PARAM;
187     }
188 
189     mbedtls_md_context_t ctx;
190     const mbedtls_md_info_t *info = NULL;
191     mbedtls_md_init(&ctx);
192 
193     info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
194     if (info == NULL) {
195         mbedtls_md_free(&ctx);
196         return SOFTBUS_ENCRYPT_ERR;
197     }
198     if (mbedtls_md_setup(&ctx, info, 0) != 0) {
199         mbedtls_md_free(&ctx);
200         return SOFTBUS_ENCRYPT_ERR;
201     }
202     if (mbedtls_md_starts(&ctx) != 0) {
203         mbedtls_md_free(&ctx);
204         return SOFTBUS_ENCRYPT_ERR;
205     }
206     if (mbedtls_md_update(&ctx, str, len) != 0) {
207         mbedtls_md_free(&ctx);
208         return SOFTBUS_ENCRYPT_ERR;
209     }
210     if (mbedtls_md_finish(&ctx, hash) != 0) {
211         mbedtls_md_free(&ctx);
212         return SOFTBUS_ENCRYPT_ERR;
213     }
214 
215     mbedtls_md_free(&ctx);
216     return SOFTBUS_OK;
217 }
218 
SoftBusGenerateRandomArray(unsigned char * randStr,uint32_t len)219 int32_t SoftBusGenerateRandomArray(unsigned char *randStr, uint32_t len)
220 {
221     if (randStr == NULL || len == 0) {
222         return SOFTBUS_INVALID_PARAM;
223     }
224 
225     static mbedtls_entropy_context entropy;
226     static mbedtls_ctr_drbg_context ctrDrbg;
227     static bool initFlag = false;
228     int32_t ret;
229 
230     if (!initFlag) {
231         if (SoftBusMutexInit(&g_randomLock, NULL) != SOFTBUS_OK) {
232             COMM_LOGE(COMM_ADAPTER, "SoftBusGenerateRandomArray init lock fail");
233             return SOFTBUS_LOCK_ERR;
234         }
235         mbedtls_ctr_drbg_init(&ctrDrbg);
236         mbedtls_entropy_init(&entropy);
237         ret = mbedtls_ctr_drbg_seed(&ctrDrbg, mbedtls_entropy_func, &entropy, NULL, 0);
238         if (ret != 0) {
239             SoftBusMutexUnlock(&g_randomLock);
240             COMM_LOGE(COMM_ADAPTER, "gen random seed error, ret=%{public}d", ret);
241             return SOFTBUS_ERR;
242         }
243         initFlag = true;
244     }
245 
246     if (SoftBusMutexLock(&g_randomLock) != SOFTBUS_OK) {
247         COMM_LOGE(COMM_ADAPTER, "SoftBusGenerateRandomArray lock fail");
248         return SOFTBUS_LOCK_ERR;
249     }
250 
251     ret = mbedtls_ctr_drbg_random(&ctrDrbg, randStr, len);
252     SoftBusMutexUnlock(&g_randomLock);
253     if (ret != 0) {
254         COMM_LOGE(COMM_ADAPTER, "gen random error, ret=%{public}d", ret);
255         return SOFTBUS_ERR;
256     }
257     return SOFTBUS_OK;
258 }
259 
SoftBusGenerateSessionKey(char * key,uint32_t len)260 int32_t SoftBusGenerateSessionKey(char *key, uint32_t len)
261 {
262     if (SoftBusGenerateRandomArray((unsigned char *)key, len) != SOFTBUS_OK) {
263         COMM_LOGE(COMM_ADAPTER, "generate sessionKey error.");
264         return SOFTBUS_ENCRYPT_ERR;
265     }
266     return SOFTBUS_OK;
267 }
268 
SoftBusEncryptData(AesGcmCipherKey * cipherKey,const unsigned char * input,uint32_t inLen,unsigned char * encryptData,uint32_t * encryptLen)269 int32_t SoftBusEncryptData(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
270     unsigned char *encryptData, uint32_t *encryptLen)
271 {
272     if (cipherKey == NULL || input == NULL || inLen == 0 || encryptData == NULL || encryptLen == NULL) {
273         return SOFTBUS_INVALID_PARAM;
274     }
275 
276     if (SoftBusGenerateRandomArray(cipherKey->iv, sizeof(cipherKey->iv)) != SOFTBUS_OK) {
277         COMM_LOGE(COMM_ADAPTER, "generate random iv error.");
278         return SOFTBUS_ENCRYPT_ERR;
279     }
280     uint32_t outLen = inLen + OVERHEAD_LEN;
281     int32_t result = MbedAesGcmEncrypt(cipherKey, input, inLen, encryptData, outLen);
282     if (result <= 0) {
283         return SOFTBUS_ENCRYPT_ERR;
284     }
285     *encryptLen = result;
286     return SOFTBUS_OK;
287 }
288 
SoftBusEncryptDataWithSeq(AesGcmCipherKey * cipherKey,const unsigned char * input,uint32_t inLen,unsigned char * encryptData,uint32_t * encryptLen,int32_t seqNum)289 int32_t SoftBusEncryptDataWithSeq(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
290     unsigned char *encryptData, uint32_t *encryptLen, int32_t seqNum)
291 {
292     if (cipherKey == NULL || input == NULL || inLen == 0 || encryptData == NULL || encryptLen == NULL) {
293         return SOFTBUS_INVALID_PARAM;
294     }
295     if (SoftBusGenerateRandomArray(cipherKey->iv, sizeof(cipherKey->iv)) != SOFTBUS_OK) {
296         COMM_LOGE(COMM_ADAPTER, "generate random iv error.");
297         return SOFTBUS_ENCRYPT_ERR;
298     }
299     if (memcpy_s(cipherKey->iv, sizeof(int32_t), &seqNum, sizeof(int32_t)) != EOK) {
300         return SOFTBUS_ENCRYPT_ERR;
301     }
302     uint32_t outLen = inLen + OVERHEAD_LEN;
303     int32_t result = MbedAesGcmEncrypt(cipherKey, input, inLen, encryptData, outLen);
304     if (result <= 0) {
305         return SOFTBUS_ENCRYPT_ERR;
306     }
307     *encryptLen = result;
308     return SOFTBUS_OK;
309 }
310 
SoftBusDecryptData(AesGcmCipherKey * cipherKey,const unsigned char * input,uint32_t inLen,unsigned char * decryptData,uint32_t * decryptLen)311 int32_t SoftBusDecryptData(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
312     unsigned char *decryptData, uint32_t *decryptLen)
313 {
314     if (cipherKey == NULL || input == NULL || inLen < GCM_IV_LEN || decryptData == NULL || decryptLen == NULL) {
315         return SOFTBUS_INVALID_PARAM;
316     }
317 
318     if (memcpy_s(cipherKey->iv, sizeof(cipherKey->iv), input, GCM_IV_LEN) != EOK) {
319         COMM_LOGE(COMM_ADAPTER, "copy iv failed.");
320         return SOFTBUS_ENCRYPT_ERR;
321     }
322     uint32_t outLen = inLen - OVERHEAD_LEN;
323     int32_t result = MbedAesGcmDecrypt(cipherKey, input, inLen, decryptData, outLen);
324     if (result <= 0) {
325         return SOFTBUS_ENCRYPT_ERR;
326     }
327     *decryptLen = (uint32_t)result;
328     return SOFTBUS_OK;
329 }
330 
SoftBusDecryptDataWithSeq(AesGcmCipherKey * cipherKey,const unsigned char * input,uint32_t inLen,unsigned char * decryptData,uint32_t * decryptLen,int32_t seqNum)331 int32_t SoftBusDecryptDataWithSeq(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
332     unsigned char *decryptData, uint32_t *decryptLen, int32_t seqNum)
333 {
334     (void)seqNum;
335     return SoftBusDecryptData(cipherKey, input, inLen, decryptData, decryptLen);
336 }
337 
SoftBusCryptoRand(void)338 uint32_t SoftBusCryptoRand(void)
339 {
340     int32_t fd = SoftBusOpenFile("/dev/urandom", SOFTBUS_O_RDONLY);
341     if (fd < 0) {
342         COMM_LOGE(COMM_ADAPTER, "CryptoRand open file fail");
343         return 0;
344     }
345     uint32_t value = 0;
346     int32_t len = SoftBusReadFile(fd, &value, sizeof(uint32_t));
347     if (len < 0) {
348         COMM_LOGE(COMM_ADAPTER, "CryptoRand read file fail");
349         SoftBusCloseFile(fd);
350         return 0;
351     }
352     SoftBusCloseFile(fd);
353     return value;
354 }
355 
SoftBusEncryptDataByCtr(AesCtrCipherKey * key,const unsigned char * input,uint32_t inLen,unsigned char * encryptData,uint32_t * encryptLen)356 int32_t SoftBusEncryptDataByCtr(AesCtrCipherKey *key, const unsigned char *input, uint32_t inLen,
357     unsigned char *encryptData, uint32_t *encryptLen)
358 {
359     if (key == NULL || input == NULL || inLen == 0 || encryptData == NULL || encryptLen == NULL) {
360         COMM_LOGE(COMM_ADAPTER, "softbus encrypt data by ctr invalid para");
361         return SOFTBUS_INVALID_PARAM;
362     }
363     mbedtls_cipher_type_t type = GetCtrAlgorithmByKeyLen(key->keyLen);
364     if (type == MBEDTLS_CIPHER_NONE) {
365         return HandleError(NULL, "get cipher failed");
366     }
367     size_t len = 0;
368     *encryptLen = 0;
369     mbedtls_cipher_context_t ctx;
370     const mbedtls_cipher_info_t *info = NULL;
371     mbedtls_cipher_init(&ctx);
372     if (!(info = mbedtls_cipher_info_from_type(type))) {
373         return HandleError(&ctx, "mbedtls_cipher_info_from_type ctr failed");
374     }
375     if (mbedtls_cipher_setup(&ctx, info) != 0) {
376         return HandleError(&ctx, "mbedtls_cipher_setup ctr failed");
377     }
378     if (mbedtls_cipher_setkey(&ctx, key->key, key->keyLen * BYTES_BIT_NUM, MBEDTLS_ENCRYPT) != 0) {
379         return HandleError(&ctx, "mbedtls_cipher_setkey ctr failed");
380     }
381     if (mbedtls_cipher_set_iv(&ctx, key->iv, BLE_BROADCAST_IV_LEN) != 0) {
382         return HandleError(&ctx, "mbedtls_cipher_set_iv ctr failed");
383     }
384     if (mbedtls_cipher_update(&ctx, input, inLen, encryptData, &len) != 0) {
385         return HandleError(&ctx, "mbedtls_cipher_update ctr failed");
386     }
387     *encryptLen += len;
388     if (mbedtls_cipher_finish(&ctx, encryptData, &len) != 0) {
389         return HandleError(&ctx, "mbedtls_cipher_finish ctr failed");
390     }
391     *encryptLen += len;
392     mbedtls_cipher_free(&ctx);
393     return SOFTBUS_OK;
394 }
395 
SoftBusDecryptDataByCtr(AesCtrCipherKey * key,const unsigned char * input,uint32_t inLen,unsigned char * decryptData,uint32_t * decryptLen)396 int32_t SoftBusDecryptDataByCtr(AesCtrCipherKey *key, const unsigned char *input, uint32_t inLen,
397     unsigned char *decryptData, uint32_t *decryptLen)
398 {
399     return SoftBusEncryptDataByCtr(key, input, inLen, decryptData, decryptLen);
400 }
401