• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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