• 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     switch (cryptPara->keylen) {
56         case AES_128_KEY_LENGTH:
57             cipher = EVP_aes_128_gcm();
58             break;
59         case AES_192_KEY_LENGTH:
60             cipher = EVP_aes_192_gcm();
61             break;
62         case AES_256_KEY_LENGTH:
63             cipher = EVP_aes_256_gcm();
64             break;
65         default:
66             return NSTACKX_EFAILED;
67     }
68 
69     if (cryptPara->aadLen == 0 || cryptPara->ctx == NULL) {
70         return NSTACKX_EFAILED;
71     }
72 
73     cryptPara->ivLen = GCM_IV_LENGTH;
74 
75     if (GetRandBytes(cryptPara->iv, cryptPara->ivLen) != NSTACKX_EOK) {
76         LOGE(TAG, "get rand iv failed");
77         return NSTACKX_EFAILED;
78     }
79 
80     if (EVP_EncryptInit_ex(cryptPara->ctx, cipher, NULL, cryptPara->key, cryptPara->iv) == 0) {
81         LOGE(TAG, "encrypt init error");
82         return NSTACKX_EFAILED;
83     }
84     if (EVP_EncryptUpdate(cryptPara->ctx, NULL, &length, cryptPara->aad, (int32_t)cryptPara->aadLen) == 0) {
85         LOGE(TAG, "add aad error");
86         return NSTACKX_EFAILED;
87     }
88     return NSTACKX_EOK;
89 }
90 
AesGcmEncryptVec(AesVec * vec,uint32_t vecNum,CryptPara * cryptPara,uint8_t * outBuf,uint32_t outLen)91 uint32_t AesGcmEncryptVec(AesVec *vec, uint32_t vecNum, CryptPara *cryptPara, uint8_t *outBuf,
92                           uint32_t outLen)
93 {
94     int32_t length;
95     uint32_t retLen = 0;
96     if (vecNum == 0 || outLen <= GCM_ADDED_LEN || cryptPara == NULL ||
97         vec == NULL || outBuf == NULL) {
98         return 0;
99     }
100     if (InitEncryptCtx(cryptPara) != NSTACKX_EOK) {
101         LOGE(TAG, "InitEncryptCtx error");
102         return 0;
103     }
104 
105     for (uint32_t i = 0; i < vecNum; i++) {
106         if ((outLen - GCM_ADDED_LEN) < (retLen + vec[i].len)) {
107             LOGE(TAG, "outBuf len %u is less to %u bytes input", outLen, retLen + vec[i].len);
108             return 0;
109         }
110         if (EVP_EncryptUpdate(cryptPara->ctx, outBuf + retLen, &length, vec[i].buf, (int32_t)vec[i].len) == 0 ||
111             length != (int)vec[i].len) {
112             LOGE(TAG, "encrypt data error");
113             return 0;
114         }
115         retLen += (uint32_t)length;
116     }
117     if (EVP_EncryptFinal_ex(cryptPara->ctx, outBuf + retLen, &length) == 0 || length != 0) {
118         LOGE(TAG, "encrypt final error");
119         return 0;
120     }
121     if (EVP_CIPHER_CTX_ctrl(cryptPara->ctx, EVP_CTRL_AEAD_GET_TAG, GCM_TAG_LENGTH, outBuf + retLen) == 0) {
122         LOGE(TAG, "get tag error.");
123         return 0;
124     }
125     retLen += GCM_TAG_LENGTH;
126     if (memcpy_s(outBuf + retLen, outLen - retLen, cryptPara->iv, cryptPara->ivLen) != EOK) {
127         LOGE(TAG, "pad iv error.");
128         return 0;
129     }
130     retLen += cryptPara->ivLen;
131     return retLen;
132 }
133 
AesGcmEncrypt(const uint8_t * inBuf,uint32_t inLen,CryptPara * cryptPara,uint8_t * outBuf,uint32_t outLen)134 uint32_t AesGcmEncrypt(const uint8_t *inBuf, uint32_t inLen, CryptPara *cryptPara, uint8_t *outBuf,
135                        uint32_t outLen)
136 {
137     AesVec vec;
138     vec.buf = inBuf;
139     vec.len = inLen;
140     return AesGcmEncryptVec(&vec, 1, cryptPara, outBuf, outLen);
141 }
142 
InitDecryptCtx(CryptPara * cryptPara)143 static int32_t InitDecryptCtx(CryptPara *cryptPara)
144 {
145     int32_t length;
146     const EVP_CIPHER *cipher = NULL;
147     switch (cryptPara->keylen) {
148         case AES_128_KEY_LENGTH:
149             cipher = EVP_aes_128_gcm();
150             break;
151         case AES_192_KEY_LENGTH:
152             cipher = EVP_aes_192_gcm();
153             break;
154         case AES_256_KEY_LENGTH:
155             cipher = EVP_aes_256_gcm();
156             break;
157         default:
158             return NSTACKX_EFAILED;
159     }
160     if (cryptPara->ivLen != GCM_IV_LENGTH || cryptPara->aadLen == 0 || cryptPara->ctx == NULL) {
161         return NSTACKX_EFAILED;
162     }
163 
164     if (EVP_DecryptInit_ex(cryptPara->ctx, cipher, NULL, cryptPara->key, cryptPara->iv) == 0) {
165         LOGE(TAG, "decrypt init error");
166         return NSTACKX_EFAILED;
167     }
168     if (EVP_DecryptUpdate(cryptPara->ctx, NULL, &length, cryptPara->aad, (int32_t)cryptPara->aadLen) == 0) {
169         LOGE(TAG, "decrypt update error");
170         return NSTACKX_EFAILED;
171     }
172     return NSTACKX_EOK;
173 }
174 
AesGcmDecrypt(uint8_t * inBuf,uint32_t inLen,CryptPara * cryptPara,uint8_t * outBuf,uint32_t outLen)175 uint32_t AesGcmDecrypt(uint8_t *inBuf, uint32_t inLen, CryptPara *cryptPara, uint8_t *outBuf,
176                        uint32_t outLen)
177 {
178     int32_t length;
179     int32_t dataLen;
180     uint32_t retLen;
181     uint8_t buffer[AES_BLOCK_SIZE];
182     if (inLen <= GCM_ADDED_LEN || outLen < inLen - GCM_ADDED_LEN || cryptPara == NULL ||
183         inBuf == NULL || outBuf == NULL) {
184         return 0;
185     }
186     cryptPara->ivLen = GCM_IV_LENGTH;
187     if (memcpy_s(cryptPara->iv, cryptPara->ivLen, inBuf + (inLen - GCM_IV_LENGTH), GCM_IV_LENGTH) != EOK) {
188         return 0;
189     }
190 
191     if (InitDecryptCtx(cryptPara) != NSTACKX_EOK) {
192         LOGE(TAG, "InitDecryptCtx error");
193         return 0;
194     }
195     dataLen = (int32_t)(inLen - GCM_ADDED_LEN);
196     if (EVP_DecryptUpdate(cryptPara->ctx, outBuf, &length, inBuf, dataLen) == 0 || length != dataLen) {
197         LOGE(TAG, "decrypt data error");
198         return 0;
199     }
200     retLen = (uint32_t)length;
201 
202     if (EVP_CIPHER_CTX_ctrl(cryptPara->ctx, EVP_CTRL_AEAD_SET_TAG, GCM_TAG_LENGTH, inBuf + dataLen) == 0) {
203         LOGE(TAG, "set tag error.");
204         return 0;
205     }
206 
207     if (EVP_DecryptFinal_ex(cryptPara->ctx, buffer, &length) == 0 || length != 0) {
208         LOGE(TAG, "data verify error");
209         return 0;
210     }
211     return retLen;
212 }
213 
IsCryptoIncluded(void)214 uint8_t IsCryptoIncluded(void)
215 {
216     return NSTACKX_TRUE;
217 }
218 
219 #else
GetRandBytes(uint8_t * buf,uint32_t len)220 int32_t GetRandBytes(uint8_t *buf, uint32_t len)
221 {
222     LOGI(TAG, "encryption not deployed");
223     return NSTACKX_EFAILED;
224 }
225 
CreateCryptCtx(void)226 EVP_CIPHER_CTX *CreateCryptCtx(void)
227 {
228     LOGI(TAG, "encryption not deployed");
229     EVP_CIPHER_CTX *ctx = NULL;
230     return ctx;
231 }
232 
ClearCryptCtx(EVP_CIPHER_CTX * ctx)233 void ClearCryptCtx(EVP_CIPHER_CTX *ctx)
234 {
235     LOGI(TAG, "encryption not deployed");
236     (void)ctx;
237 }
238 
AesGcmEncrypt(const uint8_t * inBuf,uint32_t inLen,CryptPara * cryptPara,uint8_t * outBuf,uint32_t outLen)239 uint32_t AesGcmEncrypt(const uint8_t *inBuf, uint32_t inLen, CryptPara *cryptPara, uint8_t *outBuf,
240                        uint32_t outLen)
241 {
242     (void)inBuf;
243     (void)inLen;
244     (void)cryptPara;
245     (void)outBuf;
246     (void)outLen;
247     LOGI(TAG, "encryption not deployed");
248     return 0;
249 }
250 
AesGcmDecrypt(uint8_t * inBuf,uint32_t inLen,CryptPara * cryptPara,uint8_t * outBuf,uint32_t outLen)251 uint32_t AesGcmDecrypt(uint8_t *inBuf, uint32_t inLen, CryptPara *cryptPara, uint8_t *outBuf,
252                        uint32_t outLen)
253 {
254     (void)inBuf;
255     (void)inLen;
256     (void)cryptPara;
257     (void)outBuf;
258     (void)outLen;
259     LOGI(TAG, "encryption not deployed");
260     return 0;
261 }
262 
IsCryptoIncluded(void)263 uint8_t IsCryptoIncluded(void)
264 {
265     return NSTACKX_FALSE;
266 }
267 
268 #endif // SSL_AND_CRYPTO_INCLUDED
269