• 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 
16 #include "nstackx_openssl.h"
17 #include "nstackx_error.h"
18 #include "nstackx_log.h"
19 #include "securec.h"
20 
21 #define TAG "nStackXDFile"
22 
23 #ifdef SSL_AND_CRYPTO_INCLUDED
GetRandBytes(uint8_t * buf,uint32_t len)24 int32_t GetRandBytes(uint8_t *buf, uint32_t len)
25 {
26     if (buf == NULL || len == 0) {
27         LOGE(TAG, "buf is NULL or illegal length %u", len);
28         return NSTACKX_EFAILED;
29     }
30     if (RAND_bytes(buf, (int)len) != 1) {
31         LOGE(TAG, "get rand_bytes failed");
32         return NSTACKX_EFAILED;
33     }
34     return NSTACKX_EOK;
35 }
36 
CreateCryptCtx()37 EVP_CIPHER_CTX *CreateCryptCtx()
38 {
39     EVP_CIPHER_CTX *ctx = NULL;
40     ctx = EVP_CIPHER_CTX_new();
41     return ctx;
42 }
43 
ClearCryptCtx(EVP_CIPHER_CTX * ctx)44 void ClearCryptCtx(EVP_CIPHER_CTX *ctx)
45 {
46     if (ctx != NULL) {
47         EVP_CIPHER_CTX_free(ctx);
48     }
49 }
50 
InitEncryptCtx(CryptPara * cryptPara)51 static int32_t InitEncryptCtx(CryptPara *cryptPara)
52 {
53     int32_t length;
54     const EVP_CIPHER *cipher = NULL;
55     if (cryptPara->cipherType == CIPHER_CHACHA) {
56         cipher = EVP_get_cipherbyname(CHACHA20_POLY1305_NAME);
57     } else if (cryptPara->cipherType == CIPHER_AES_GCM) {
58         switch (cryptPara->keylen) {
59             case AES_128_KEY_LENGTH:
60                 cipher = EVP_aes_128_gcm();
61                 break;
62             case AES_192_KEY_LENGTH:
63                 cipher = EVP_aes_192_gcm();
64                 break;
65             case AES_256_KEY_LENGTH:
66                 cipher = EVP_aes_256_gcm();
67                 break;
68             default:
69                 return NSTACKX_EFAILED;
70         }
71     }
72 
73     if (cryptPara->aadLen == 0 || cryptPara->ctx == NULL) {
74         return NSTACKX_EFAILED;
75     }
76 
77     cryptPara->ivLen = GCM_IV_LENGTH;
78 
79     if (GetRandBytes(cryptPara->iv, cryptPara->ivLen) != NSTACKX_EOK) {
80         LOGE(TAG, "get rand iv failed");
81         return NSTACKX_EFAILED;
82     }
83 
84     if (EVP_EncryptInit_ex(cryptPara->ctx, cipher, NULL, cryptPara->key, cryptPara->iv) == 0) {
85         LOGE(TAG, "encrypt init error");
86         return NSTACKX_EFAILED;
87     }
88     if (EVP_EncryptUpdate(cryptPara->ctx, NULL, &length, cryptPara->aad, (int32_t)cryptPara->aadLen) == 0) {
89         LOGE(TAG, "add aad error");
90         return NSTACKX_EFAILED;
91     }
92     return NSTACKX_EOK;
93 }
94 
AesGcmEncryptVec(AesVec * vec,uint32_t vecNum,CryptPara * cryptPara,uint8_t * outBuf,uint32_t outLen)95 uint32_t AesGcmEncryptVec(AesVec *vec, uint32_t vecNum, CryptPara *cryptPara, uint8_t *outBuf,
96                           uint32_t outLen)
97 {
98     int32_t length;
99     uint32_t retLen = 0;
100     if (vecNum == 0 || outLen <= GCM_ADDED_LEN || cryptPara == NULL ||
101         vec == NULL || outBuf == NULL) {
102         return 0;
103     }
104     if (InitEncryptCtx(cryptPara) != NSTACKX_EOK) {
105         LOGE(TAG, "InitEncryptCtx error");
106         return 0;
107     }
108 
109     for (uint32_t i = 0; i < vecNum; i++) {
110         if ((outLen - GCM_ADDED_LEN) < (retLen + vec[i].len)) {
111             LOGE(TAG, "outBuf len %u is less to %u bytes input", outLen, retLen + vec[i].len);
112             return 0;
113         }
114         if (EVP_EncryptUpdate(cryptPara->ctx, outBuf + retLen, &length, vec[i].buf, (int32_t)vec[i].len) == 0 ||
115             length != (int)vec[i].len) {
116             LOGE(TAG, "encrypt data error");
117             return 0;
118         }
119         retLen += (uint32_t)length;
120     }
121     if (EVP_EncryptFinal_ex(cryptPara->ctx, outBuf + retLen, &length) == 0 || length != 0) {
122         LOGE(TAG, "encrypt final error");
123         return 0;
124     }
125     if (EVP_CIPHER_CTX_ctrl(cryptPara->ctx, EVP_CTRL_AEAD_GET_TAG, GCM_TAG_LENGTH, outBuf + retLen) == 0) {
126         LOGE(TAG, "get tag error.");
127         return 0;
128     }
129     retLen += GCM_TAG_LENGTH;
130     if (memcpy_s(outBuf + retLen, outLen - retLen, cryptPara->iv, cryptPara->ivLen) != EOK) {
131         LOGE(TAG, "pad iv error.");
132         return 0;
133     }
134     retLen += cryptPara->ivLen;
135     return retLen;
136 }
137 
AesGcmEncrypt(const uint8_t * inBuf,uint32_t inLen,CryptPara * cryptPara,uint8_t * outBuf,uint32_t outLen)138 uint32_t AesGcmEncrypt(const uint8_t *inBuf, uint32_t inLen, CryptPara *cryptPara, uint8_t *outBuf,
139                        uint32_t outLen)
140 {
141     AesVec vec;
142     vec.buf = inBuf;
143     vec.len = inLen;
144     return AesGcmEncryptVec(&vec, 1, cryptPara, outBuf, outLen);
145 }
146 
InitDecryptCtx(CryptPara * cryptPara)147 static int32_t InitDecryptCtx(CryptPara *cryptPara)
148 {
149     int32_t length;
150     const EVP_CIPHER *cipher = NULL;
151     if (cryptPara->cipherType == CIPHER_CHACHA) {
152         cipher = EVP_get_cipherbyname(CHACHA20_POLY1305_NAME);
153     } else if (cryptPara->cipherType == CIPHER_AES_GCM) {
154         switch (cryptPara->keylen) {
155             case AES_128_KEY_LENGTH:
156                 cipher = EVP_aes_128_gcm();
157                 break;
158             case AES_192_KEY_LENGTH:
159                 cipher = EVP_aes_192_gcm();
160                 break;
161             case AES_256_KEY_LENGTH:
162                 cipher = EVP_aes_256_gcm();
163                 break;
164             default:
165                 return NSTACKX_EFAILED;
166         }
167     }
168     if (cryptPara->ivLen != GCM_IV_LENGTH || cryptPara->aadLen == 0 || cryptPara->ctx == NULL) {
169         return NSTACKX_EFAILED;
170     }
171 
172     if (EVP_DecryptInit_ex(cryptPara->ctx, cipher, NULL, cryptPara->key, cryptPara->iv) == 0) {
173         LOGE(TAG, "decrypt init error");
174         return NSTACKX_EFAILED;
175     }
176     if (EVP_DecryptUpdate(cryptPara->ctx, NULL, &length, cryptPara->aad, (int32_t)cryptPara->aadLen) == 0) {
177         LOGE(TAG, "decrypt update error");
178         return NSTACKX_EFAILED;
179     }
180     return NSTACKX_EOK;
181 }
182 
AesGcmDecrypt(uint8_t * inBuf,uint32_t inLen,CryptPara * cryptPara,uint8_t * outBuf,uint32_t outLen)183 uint32_t AesGcmDecrypt(uint8_t *inBuf, uint32_t inLen, CryptPara *cryptPara, uint8_t *outBuf,
184                        uint32_t outLen)
185 {
186     int32_t length;
187     int32_t dataLen;
188     uint32_t retLen;
189     uint8_t buffer[AES_BLOCK_SIZE];
190     if (inLen <= GCM_ADDED_LEN || outLen < inLen - GCM_ADDED_LEN || cryptPara == NULL ||
191         inBuf == NULL || outBuf == NULL) {
192         return 0;
193     }
194     cryptPara->ivLen = GCM_IV_LENGTH;
195     if (memcpy_s(cryptPara->iv, cryptPara->ivLen, inBuf + (inLen - GCM_IV_LENGTH), GCM_IV_LENGTH) != EOK) {
196         return 0;
197     }
198 
199     if (InitDecryptCtx(cryptPara) != NSTACKX_EOK) {
200         LOGE(TAG, "InitDecryptCtx error");
201         return 0;
202     }
203     dataLen = (int32_t)(inLen - GCM_ADDED_LEN);
204     if (EVP_DecryptUpdate(cryptPara->ctx, outBuf, &length, inBuf, dataLen) == 0 || length != dataLen) {
205         LOGE(TAG, "decrypt data error");
206         return 0;
207     }
208     retLen = (uint32_t)length;
209 
210     if (EVP_CIPHER_CTX_ctrl(cryptPara->ctx, EVP_CTRL_AEAD_SET_TAG, GCM_TAG_LENGTH, inBuf + dataLen) == 0) {
211         LOGE(TAG, "set tag error.");
212         return 0;
213     }
214 
215     if (EVP_DecryptFinal_ex(cryptPara->ctx, buffer, &length) == 0 || length != 0) {
216         LOGE(TAG, "data verify error");
217         return 0;
218     }
219     return retLen;
220 }
221 
IsCryptoIncluded(void)222 uint8_t IsCryptoIncluded(void)
223 {
224     return NSTACKX_TRUE;
225 }
226 
QueryCipherSupportByName(char * name)227 uint8_t QueryCipherSupportByName(char *name)
228 {
229     if (EVP_get_cipherbyname(name) != NULL) {
230         return NSTACKX_TRUE;
231     }
232 
233     LOGI(TAG, "devices no support %s", name);
234     return NSTACKX_FALSE;
235 }
236 
237 #else
GetRandBytes(uint8_t * buf,uint32_t len)238 int32_t GetRandBytes(uint8_t *buf, uint32_t len)
239 {
240     LOGI(TAG, "encryption not deployed");
241     return NSTACKX_EFAILED;
242 }
243 
CreateCryptCtx(void)244 EVP_CIPHER_CTX *CreateCryptCtx(void)
245 {
246     LOGI(TAG, "encryption not deployed");
247     EVP_CIPHER_CTX *ctx = NULL;
248     return ctx;
249 }
250 
ClearCryptCtx(EVP_CIPHER_CTX * ctx)251 void ClearCryptCtx(EVP_CIPHER_CTX *ctx)
252 {
253     LOGI(TAG, "encryption not deployed");
254     (void)ctx;
255 }
256 
AesGcmEncrypt(const uint8_t * inBuf,uint32_t inLen,CryptPara * cryptPara,uint8_t * outBuf,uint32_t outLen)257 uint32_t AesGcmEncrypt(const uint8_t *inBuf, uint32_t inLen, CryptPara *cryptPara, uint8_t *outBuf,
258                        uint32_t outLen)
259 {
260     (void)inBuf;
261     (void)inLen;
262     (void)cryptPara;
263     (void)outBuf;
264     (void)outLen;
265     LOGI(TAG, "encryption not deployed");
266     return 0;
267 }
268 
AesGcmDecrypt(uint8_t * inBuf,uint32_t inLen,CryptPara * cryptPara,uint8_t * outBuf,uint32_t outLen)269 uint32_t AesGcmDecrypt(uint8_t *inBuf, uint32_t inLen, CryptPara *cryptPara, uint8_t *outBuf,
270                        uint32_t outLen)
271 {
272     (void)inBuf;
273     (void)inLen;
274     (void)cryptPara;
275     (void)outBuf;
276     (void)outLen;
277     LOGI(TAG, "encryption not deployed");
278     return 0;
279 }
280 
IsCryptoIncluded(void)281 uint8_t IsCryptoIncluded(void)
282 {
283     return NSTACKX_FALSE;
284 }
285 
QueryCipherSupportByName(char * name)286 uint8_t QueryCipherSupportByName(char *name)
287 {
288     LOGI(TAG, "devices no support %s", name);
289     return NSTACKX_FALSE;
290 }
291 
292 #endif // SSL_AND_CRYPTO_INCLUDED
293