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
63static SoftBusMutex g_randomLock;
64
65static 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
78static 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
120static 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
152static 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
163int32_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
173int32_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
183int32_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
219int32_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
260int32_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
269int32_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
289int32_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
311int32_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
331int32_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
338uint32_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
356int32_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
396int32_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