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