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 "mbedtls/base64.h"
21 #include "mbedtls/ctr_drbg.h"
22 #include "mbedtls/entropy.h"
23 #include "mbedtls/gcm.h"
24 #include "mbedtls/md.h"
25 #include "mbedtls/platform.h"
26 #include "softbus_adapter_file.h"
27 #include "softbus_adapter_log.h"
28 #include "softbus_errcode.h"
29
30 #ifndef MBEDTLS_CTR_DRBG_C
31 #define MBEDTLS_CTR_DRBG_C
32 #endif
33
34 #ifndef MBEDTLS_MD_C
35 #define MBEDTLS_MD_C
36 #endif
37
38 #ifndef MBEDTLS_SHA256_C
39 #define MBEDTLS_SHA256_C
40 #endif
41
42 #ifndef MBEDTLS_ENTROPY_C
43 #define MBEDTLS_ENTROPY_C
44 #endif
45
46 static pthread_mutex_t g_randomLock = PTHREAD_MUTEX_INITIALIZER;
47
MbedAesGcmEncrypt(const AesGcmCipherKey * cipherkey,const unsigned char * plainText,uint32_t plainTextSize,unsigned char * cipherText,uint32_t cipherTextLen)48 static int32_t MbedAesGcmEncrypt(const AesGcmCipherKey *cipherkey, const unsigned char *plainText,
49 uint32_t plainTextSize, unsigned char *cipherText, uint32_t cipherTextLen)
50 {
51 if ((cipherkey == NULL) || (plainText == NULL) || (plainTextSize == 0) || cipherText == NULL ||
52 (cipherTextLen < plainTextSize + OVERHEAD_LEN)) {
53 HILOG_ERROR(SOFTBUS_HILOG_ID, "Encrypt invalid para\n");
54 return SOFTBUS_INVALID_PARAM;
55 }
56
57 int32_t ret;
58 unsigned char tagBuf[TAG_LEN] = {0};
59 mbedtls_gcm_context aesContext;
60 mbedtls_gcm_init(&aesContext);
61
62 ret = mbedtls_gcm_setkey(&aesContext, MBEDTLS_CIPHER_ID_AES, cipherkey->key, cipherkey->keyLen * KEY_BITS_UNIT);
63 if (ret != 0) {
64 mbedtls_gcm_free(&aesContext);
65 return SOFTBUS_ENCRYPT_ERR;
66 }
67
68 ret = mbedtls_gcm_crypt_and_tag(&aesContext, MBEDTLS_GCM_ENCRYPT, plainTextSize, cipherkey->iv,
69 GCM_IV_LEN, NULL, 0, plainText, cipherText + GCM_IV_LEN, TAG_LEN, tagBuf);
70 if (ret != 0) {
71 mbedtls_gcm_free(&aesContext);
72 return SOFTBUS_ENCRYPT_ERR;
73 }
74
75 if (memcpy_s(cipherText, cipherTextLen, cipherkey->iv, GCM_IV_LEN) != EOK) {
76 mbedtls_gcm_free(&aesContext);
77 return SOFTBUS_ENCRYPT_ERR;
78 }
79
80 if (memcpy_s(cipherText + GCM_IV_LEN + plainTextSize, cipherTextLen - GCM_IV_LEN - plainTextSize,
81 tagBuf, TAG_LEN) != 0) {
82 mbedtls_gcm_free(&aesContext);
83 return SOFTBUS_ENCRYPT_ERR;
84 }
85
86 mbedtls_gcm_free(&aesContext);
87 return (plainTextSize + OVERHEAD_LEN);
88 }
89
MbedAesGcmDecrypt(const AesGcmCipherKey * cipherkey,const unsigned char * cipherText,uint32_t cipherTextSize,unsigned char * plain,uint32_t plainLen)90 static int32_t MbedAesGcmDecrypt(const AesGcmCipherKey *cipherkey, const unsigned char *cipherText,
91 uint32_t cipherTextSize, unsigned char *plain, uint32_t plainLen)
92 {
93 if ((cipherkey == NULL) || (cipherText == NULL) || (cipherTextSize <= OVERHEAD_LEN) || plain == NULL ||
94 (plainLen < cipherTextSize - OVERHEAD_LEN)) {
95 HILOG_ERROR(SOFTBUS_HILOG_ID, "Decrypt invalid para\n");
96 return SOFTBUS_INVALID_PARAM;
97 }
98
99 mbedtls_gcm_context aesContext;
100 mbedtls_gcm_init(&aesContext);
101 int32_t ret = mbedtls_gcm_setkey(&aesContext, MBEDTLS_CIPHER_ID_AES, cipherkey->key,
102 cipherkey->keyLen * KEY_BITS_UNIT);
103 if (ret != 0) {
104 HILOG_ERROR(SOFTBUS_HILOG_ID, "Decrypt mbedtls_gcm_setkey fail\n");
105 mbedtls_gcm_free(&aesContext);
106 return SOFTBUS_DECRYPT_ERR;
107 }
108
109 int32_t actualPlainLen = (int32_t)(cipherTextSize - OVERHEAD_LEN);
110 ret = mbedtls_gcm_auth_decrypt(&aesContext, cipherTextSize - OVERHEAD_LEN, cipherkey->iv,
111 GCM_IV_LEN, NULL, 0, cipherText + actualPlainLen + GCM_IV_LEN, TAG_LEN, cipherText + GCM_IV_LEN, plain);
112 if (ret != 0) {
113 HILOG_ERROR(SOFTBUS_HILOG_ID, "[TRANS] Decrypt mbedtls_gcm_auth_decrypt fail.[%d]\n", ret);
114 mbedtls_gcm_free(&aesContext);
115 return SOFTBUS_DECRYPT_ERR;
116 }
117
118 mbedtls_gcm_free(&aesContext);
119 return actualPlainLen;
120 }
121
SoftBusBase64Encode(unsigned char * dst,size_t dlen,size_t * olen,const unsigned char * src,size_t slen)122 int32_t SoftBusBase64Encode(unsigned char *dst, size_t dlen,
123 size_t *olen, const unsigned char *src, size_t slen)
124 {
125 if (dst == NULL || dlen == 0 || olen == NULL || src == NULL || slen == 0) {
126 return SOFTBUS_INVALID_PARAM;
127 }
128 return mbedtls_base64_encode(dst, dlen, olen, src, slen);
129 }
130
SoftBusBase64Decode(unsigned char * dst,size_t dlen,size_t * olen,const unsigned char * src,size_t slen)131 int32_t SoftBusBase64Decode(unsigned char *dst, size_t dlen,
132 size_t *olen, const unsigned char *src, size_t slen)
133 {
134 if (dst == NULL || dlen == 0 || olen == NULL || src == NULL || slen == 0) {
135 return SOFTBUS_INVALID_PARAM;
136 }
137 return mbedtls_base64_decode(dst, dlen, olen, src, slen);
138 }
139
SoftBusGenerateStrHash(const unsigned char * str,uint32_t len,unsigned char * hash)140 int32_t SoftBusGenerateStrHash(const unsigned char *str, uint32_t len, unsigned char *hash)
141 {
142 if (str == NULL || hash == NULL || len == 0) {
143 return SOFTBUS_INVALID_PARAM;
144 }
145
146 mbedtls_md_context_t ctx;
147 const mbedtls_md_info_t *info = NULL;
148 mbedtls_md_init(&ctx);
149
150 info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
151 if (mbedtls_md_setup(&ctx, info, 0) != 0) {
152 mbedtls_md_free(&ctx);
153 return SOFTBUS_ENCRYPT_ERR;
154 }
155 if (mbedtls_md_starts(&ctx) != 0) {
156 mbedtls_md_free(&ctx);
157 return SOFTBUS_ENCRYPT_ERR;
158 }
159 if (mbedtls_md_update(&ctx, str, len) != 0) {
160 mbedtls_md_free(&ctx);
161 return SOFTBUS_ENCRYPT_ERR;
162 }
163 if (mbedtls_md_finish(&ctx, hash) != 0) {
164 mbedtls_md_free(&ctx);
165 return SOFTBUS_ENCRYPT_ERR;
166 }
167
168 mbedtls_md_free(&ctx);
169 return SOFTBUS_OK;
170 }
171
SoftBusGenerateRandomArray(unsigned char * randStr,uint32_t len)172 int32_t SoftBusGenerateRandomArray(unsigned char *randStr, uint32_t len)
173 {
174 if (randStr == NULL || len == 0) {
175 return SOFTBUS_INVALID_PARAM;
176 }
177
178 static mbedtls_entropy_context entropy;
179 static mbedtls_ctr_drbg_context ctrDrbg;
180 static bool initFlag = false;
181 int32_t ret;
182
183 if (pthread_mutex_lock(&g_randomLock) != 0) {
184 HILOG_ERROR(SOFTBUS_HILOG_ID, "lock mutex failed");
185 return SOFTBUS_ERR;
186 }
187
188 if (initFlag == false) {
189 mbedtls_ctr_drbg_init(&ctrDrbg);
190 mbedtls_entropy_init(&entropy);
191 ret = mbedtls_ctr_drbg_seed(&ctrDrbg, mbedtls_entropy_func, &entropy, NULL, 0);
192 if (ret != 0) {
193 pthread_mutex_unlock(&g_randomLock);
194 HILOG_ERROR(SOFTBUS_HILOG_ID, "gen random seed error, ret[%d]", ret);
195 return SOFTBUS_ERR;
196 }
197 initFlag = true;
198 }
199
200 ret = mbedtls_ctr_drbg_random(&ctrDrbg, randStr, len);
201 pthread_mutex_unlock(&g_randomLock);
202 if (ret != 0) {
203 HILOG_ERROR(SOFTBUS_HILOG_ID, "gen random error, ret[%d]", ret);
204 return SOFTBUS_ERR;
205 }
206 return SOFTBUS_OK;
207 }
208
SoftBusGenerateSessionKey(char * key,uint32_t len)209 int32_t SoftBusGenerateSessionKey(char *key, uint32_t len)
210 {
211 if (SoftBusGenerateRandomArray((unsigned char*)key, len) != SOFTBUS_OK) {
212 HILOG_ERROR(SOFTBUS_HILOG_ID, "generate sessionKey error.");
213 return SOFTBUS_ENCRYPT_ERR;
214 }
215 return SOFTBUS_OK;
216 }
217
SoftBusEncryptData(AesGcmCipherKey * cipherKey,const unsigned char * input,uint32_t inLen,unsigned char * encryptData,uint32_t * encryptLen)218 int32_t SoftBusEncryptData(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
219 unsigned char *encryptData, uint32_t *encryptLen)
220 {
221 if (cipherKey == NULL || input == NULL || inLen == 0 || encryptData == NULL || encryptLen == NULL) {
222 return SOFTBUS_INVALID_PARAM;
223 }
224
225 if (SoftBusGenerateRandomArray(cipherKey->iv, sizeof(cipherKey->iv)) != SOFTBUS_OK) {
226 HILOG_ERROR(SOFTBUS_HILOG_ID, "generate random iv error.");
227 return SOFTBUS_ENCRYPT_ERR;
228 }
229 uint32_t outLen = inLen + OVERHEAD_LEN;
230 int32_t result = MbedAesGcmEncrypt(cipherKey, input, inLen, encryptData, outLen);
231 if (result <= 0) {
232 return SOFTBUS_ENCRYPT_ERR;
233 }
234 *encryptLen = result;
235 return SOFTBUS_OK;
236 }
237
SoftBusEncryptDataWithSeq(AesGcmCipherKey * cipherKey,const unsigned char * input,uint32_t inLen,unsigned char * encryptData,uint32_t * encryptLen,int32_t seqNum)238 int32_t SoftBusEncryptDataWithSeq(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
239 unsigned char *encryptData, uint32_t *encryptLen, int32_t seqNum)
240 {
241 if (cipherKey == NULL || input == NULL || inLen == 0 || encryptData == NULL || encryptLen == NULL) {
242 return SOFTBUS_INVALID_PARAM;
243 }
244 if (SoftBusGenerateRandomArray(cipherKey->iv, sizeof(cipherKey->iv)) != SOFTBUS_OK) {
245 HILOG_ERROR(SOFTBUS_HILOG_ID, "generate random iv error.");
246 return SOFTBUS_ENCRYPT_ERR;
247 }
248 if (memcpy_s(cipherKey->iv, sizeof(int32_t), &seqNum, sizeof(int32_t)) != EOK) {
249 return SOFTBUS_ENCRYPT_ERR;
250 }
251 uint32_t outLen = inLen + OVERHEAD_LEN;
252 int32_t result = MbedAesGcmEncrypt(cipherKey, input, inLen, encryptData, outLen);
253 if (result <= 0) {
254 return SOFTBUS_ENCRYPT_ERR;
255 }
256 *encryptLen = result;
257 return SOFTBUS_OK;
258 }
259
SoftBusDecryptData(AesGcmCipherKey * cipherKey,const unsigned char * input,uint32_t inLen,unsigned char * decryptData,uint32_t * decryptLen)260 int32_t SoftBusDecryptData(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
261 unsigned char *decryptData, uint32_t *decryptLen)
262 {
263 if (cipherKey == NULL || input == NULL || inLen < GCM_IV_LEN || decryptData == NULL || decryptLen == NULL) {
264 return SOFTBUS_INVALID_PARAM;
265 }
266
267 if (memcpy_s(cipherKey->iv, sizeof(cipherKey->iv), input, GCM_IV_LEN) != EOK) {
268 HILOG_ERROR(SOFTBUS_HILOG_ID, "copy iv failed.");
269 return SOFTBUS_ENCRYPT_ERR;
270 }
271 uint32_t outLen = inLen - OVERHEAD_LEN;
272 int32_t result = MbedAesGcmDecrypt(cipherKey, input, inLen, decryptData, outLen);
273 if (result <= 0) {
274 return SOFTBUS_ENCRYPT_ERR;
275 }
276 *decryptLen = (uint32_t)result;
277 return SOFTBUS_OK;
278 }
279
SoftBusDecryptDataWithSeq(AesGcmCipherKey * cipherKey,const unsigned char * input,uint32_t inLen,unsigned char * decryptData,uint32_t * decryptLen,int32_t seqNum)280 int32_t SoftBusDecryptDataWithSeq(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
281 unsigned char *decryptData, uint32_t *decryptLen, int32_t seqNum)
282 {
283 (void)seqNum;
284 return SoftBusDecryptData(cipherKey, input, inLen, decryptData, decryptLen);
285 }
286
SoftBusCryptoRand(void)287 uint32_t SoftBusCryptoRand(void)
288 {
289 int32_t fd = SoftBusOpenFile("/dev/urandom", SOFTBUS_O_RDONLY);
290 if (fd < 0) {
291 HILOG_ERROR(SOFTBUS_HILOG_ID, "CryptoRand open file fail");
292 return 0;
293 }
294 uint32_t value = 0;
295 int32_t len = SoftBusReadFile(fd, &value, sizeof(uint32_t));
296 if (len < 0) {
297 HILOG_ERROR(SOFTBUS_HILOG_ID, "CryptoRand read file fail");
298 return 0;
299 }
300 SoftBusCloseFile(fd);
301 return value;
302 }
303