• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the openHiTLS project.
3  *
4  * openHiTLS is licensed under the Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *
8  *     http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  * See the Mulan PSL v2 for more details.
14  */
15 
16 #include "hitls_build.h"
17 #if defined(HITLS_CRYPTO_EAL) && defined(HITLS_CRYPTO_CIPHER)
18 
19 #include "securec.h"
20 #include "crypt_algid.h"
21 #include "crypt_eal_cipher.h"
22 #include "bsl_err_internal.h"
23 #include "bsl_sal.h"
24 #include "crypt_errno.h"
25 #include "eal_cipher_local.h"
26 #include "eal_common.h"
27 #include "crypt_utils.h"
28 #include "crypt_ealinit.h"
29 #include "crypt_types.h"
30 #ifdef HITLS_CRYPTO_PROVIDER
31 #include "crypt_provider.h"
32 #endif
33 
CipherCopyMethod(const EAL_CipherMethod * modeMethod,EAL_CipherUnitaryMethod * method)34 static void CipherCopyMethod(const EAL_CipherMethod *modeMethod, EAL_CipherUnitaryMethod *method)
35 {
36     method->newCtx = modeMethod->newCtx;
37     method->initCtx = modeMethod->initCtx;
38     method->deinitCtx = modeMethod->deinitCtx;
39     method->update = modeMethod->update;
40     method->final = modeMethod->final;
41     method->ctrl = modeMethod->ctrl;
42     method->freeCtx = modeMethod->freeCtx;
43 }
44 
CipherNewDefaultCtx(CRYPT_CIPHER_AlgId id)45 static CRYPT_EAL_CipherCtx *CipherNewDefaultCtx(CRYPT_CIPHER_AlgId id)
46 {
47     int32_t ret;
48     const EAL_CipherMethod *modeMethod = NULL;
49     ret = EAL_FindCipher(id, &modeMethod);
50     if (ret != CRYPT_SUCCESS) {
51         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, id, ret);
52         return NULL;
53     }
54 
55     CRYPT_EAL_CipherCtx *ctx = (CRYPT_EAL_CipherCtx *)BSL_SAL_Calloc(1u, sizeof(struct CryptEalCipherCtx));
56     if (ctx == NULL) {
57         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, id, CRYPT_MEM_ALLOC_FAIL);
58         return NULL;
59     }
60 
61     EAL_CipherUnitaryMethod *method = (EAL_CipherUnitaryMethod *)BSL_SAL_Calloc(1u, sizeof(EAL_CipherUnitaryMethod));
62     if (method == NULL) {
63         BSL_SAL_Free(ctx);
64         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, id, CRYPT_MEM_ALLOC_FAIL);
65         return NULL;
66     }
67 
68     void *modeCtx = modeMethod->newCtx(id);
69     if (modeCtx == NULL) {
70         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, id, CRYPT_EAL_CIPHER_ERR_NEWCTX);
71         BSL_SAL_Free(ctx);
72         BSL_SAL_Free(method);
73         return NULL;
74     }
75 
76     CipherCopyMethod(modeMethod, method);
77     ctx->id = id;
78     ctx->method = method;
79     ctx->ctx = modeCtx;
80     ctx->states = EAL_CIPHER_STATE_NEW;
81 
82     return ctx;
83 }
84 
85 #ifdef HITLS_CRYPTO_PROVIDER
CRYPT_EAL_SetCipherMethod(CRYPT_EAL_CipherCtx * ctx,const CRYPT_EAL_Func * funcs)86 static int32_t CRYPT_EAL_SetCipherMethod(CRYPT_EAL_CipherCtx *ctx, const CRYPT_EAL_Func *funcs)
87 {
88     int32_t index = 0;
89     EAL_CipherUnitaryMethod *method = BSL_SAL_Calloc(1, sizeof(EAL_CipherUnitaryMethod));
90     if (method == NULL) {
91         BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
92         return BSL_MALLOC_FAIL;
93     }
94 
95     while (funcs[index].id != 0) {
96         switch (funcs[index].id) {
97             case CRYPT_EAL_IMPLCIPHER_NEWCTX:
98                 method->provNewCtx = funcs[index].func;
99                 break;
100             case CRYPT_EAL_IMPLCIPHER_INITCTX:
101                 method->initCtx = funcs[index].func;
102                 break;
103             case CRYPT_EAL_IMPLCIPHER_UPDATE:
104                 method->update = funcs[index].func;
105                 break;
106             case CRYPT_EAL_IMPLCIPHER_FINAL:
107                 method->final = funcs[index].func;
108                 break;
109             case CRYPT_EAL_IMPLCIPHER_DEINITCTX:
110                 method->deinitCtx = funcs[index].func;
111                 break;
112             case CRYPT_EAL_IMPLCIPHER_FREECTX:
113                 method->freeCtx = funcs[index].func;
114                 break;
115             case CRYPT_EAL_IMPLCIPHER_CTRL:
116                 method->ctrl = funcs[index].func;
117                 break;
118             default:
119                 BSL_SAL_FREE(method);
120                 BSL_ERR_PUSH_ERROR(CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL);
121                 return CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL;
122         }
123         index++;
124     }
125     ctx->method = method;
126     return CRYPT_SUCCESS;
127 }
128 
CRYPT_EAL_ProviderCipherNewCtxInner(CRYPT_EAL_LibCtx * libCtx,int32_t algId,const char * attrName)129 CRYPT_EAL_CipherCtx *CRYPT_EAL_ProviderCipherNewCtxInner(CRYPT_EAL_LibCtx *libCtx, int32_t algId, const char *attrName)
130 {
131     const CRYPT_EAL_Func *funcs = NULL;
132     void *provCtx = NULL;
133     int32_t ret = CRYPT_EAL_ProviderGetFuncs(libCtx, CRYPT_EAL_OPERAID_SYMMCIPHER, algId, attrName,
134         (const CRYPT_EAL_Func **)&funcs, &provCtx);
135     if (ret != CRYPT_SUCCESS) {
136         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, algId, ret);
137         return NULL;
138     }
139     CRYPT_EAL_CipherCtx *ctx = BSL_SAL_Calloc(1u, sizeof(CRYPT_EAL_CipherCtx));
140     if (ctx == NULL) {
141         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, algId, CRYPT_MEM_ALLOC_FAIL);
142         return NULL;
143     }
144 
145     ret = CRYPT_EAL_SetCipherMethod(ctx, funcs);
146     if (ret != BSL_SUCCESS) {
147         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, algId, ret);
148         BSL_SAL_FREE(ctx);
149         return NULL;
150     }
151     if (ctx->method->provNewCtx == NULL) {
152         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, algId, CRYPT_PROVIDER_ERR_IMPL_NULL);
153         BSL_SAL_FREE(ctx->method);
154         BSL_SAL_FREE(ctx);
155         return NULL;
156     }
157     ctx->ctx = ctx->method->provNewCtx(provCtx, algId);
158     if (ctx->ctx == NULL) {
159         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, algId, CRYPT_MEM_ALLOC_FAIL);
160         BSL_SAL_FREE(ctx->method);
161         BSL_SAL_FREE(ctx);
162         return NULL;
163     }
164     ctx->id = algId;
165     ctx->states = EAL_CIPHER_STATE_NEW;
166     ctx->isProvider = true;
167     return ctx;
168 }
169 #endif
170 
CRYPT_EAL_ProviderCipherNewCtx(CRYPT_EAL_LibCtx * libCtx,int32_t algId,const char * attrName)171 CRYPT_EAL_CipherCtx *CRYPT_EAL_ProviderCipherNewCtx(CRYPT_EAL_LibCtx *libCtx, int32_t algId, const char *attrName)
172 {
173 #ifdef HITLS_CRYPTO_PROVIDER
174     return CRYPT_EAL_ProviderCipherNewCtxInner(libCtx, algId, attrName);
175 #else
176     (void)libCtx;
177     (void)attrName;
178     return CRYPT_EAL_CipherNewCtx(algId);
179 #endif
180 }
181 
CRYPT_EAL_CipherNewCtx(CRYPT_CIPHER_AlgId id)182 CRYPT_EAL_CipherCtx *CRYPT_EAL_CipherNewCtx(CRYPT_CIPHER_AlgId id)
183 {
184 #ifdef HITLS_CRYPTO_ASM_CHECK
185     if (CRYPT_ASMCAP_Cipher(id) != CRYPT_SUCCESS) {
186         BSL_ERR_PUSH_ERROR(CRYPT_EAL_ALG_ASM_NOT_SUPPORT);
187         return NULL;
188     }
189 #endif
190     return CipherNewDefaultCtx(id);
191 }
192 
CRYPT_EAL_CipherFreeCtx(CRYPT_EAL_CipherCtx * ctx)193 void CRYPT_EAL_CipherFreeCtx(CRYPT_EAL_CipherCtx *ctx)
194 {
195     if (ctx == NULL) {
196         // If the input parameter is NULL, it is not considered as an error.
197         return;
198     }
199     if (ctx->method == NULL || ctx->method->freeCtx == NULL) {
200         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_EAL_ALG_NOT_SUPPORT);
201         BSL_SAL_FREE(ctx->method);
202         BSL_SAL_FREE(ctx);
203         return;
204     }
205 
206     (void)ctx->method->freeCtx(ctx->ctx);
207     BSL_SAL_FREE(ctx->method);
208     // Free the memory eal ctx and mode ctx at the EAL layer.
209     BSL_SAL_FREE(ctx);
210 }
211 
CRYPT_EAL_CipherInit(CRYPT_EAL_CipherCtx * ctx,const uint8_t * key,uint32_t keyLen,const uint8_t * iv,uint32_t ivLen,bool enc)212 int32_t CRYPT_EAL_CipherInit(CRYPT_EAL_CipherCtx *ctx, const uint8_t *key, uint32_t keyLen, const uint8_t *iv,
213     uint32_t ivLen, bool enc)
214 {
215     int32_t ret;
216     if (ctx == NULL) {
217         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, CRYPT_CIPHER_MAX, CRYPT_NULL_INPUT);
218         return CRYPT_NULL_INPUT;
219     }
220     if (ctx->method == NULL || ctx->method->initCtx == NULL) {
221         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_EAL_ALG_NOT_SUPPORT);
222         return CRYPT_EAL_ALG_NOT_SUPPORT;
223     }
224 
225     CRYPT_EAL_CipherDeinit(ctx);
226     if (ctx->states != EAL_CIPHER_STATE_NEW) {
227         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_EAL_ERR_STATE);
228         return CRYPT_EAL_ERR_STATE;
229     }
230 
231     ret = ctx->method->initCtx(ctx->ctx, key, keyLen, iv, ivLen, NULL, enc);
232     if (ret != CRYPT_SUCCESS) {
233         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, ret);
234         return ret;
235     }
236 
237     EAL_EventReport(CRYPT_EVENT_SETSSP, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_SUCCESS);
238     ctx->states = EAL_CIPHER_STATE_INIT;
239     return CRYPT_SUCCESS;
240 }
241 
CRYPT_EAL_CipherDeinit(CRYPT_EAL_CipherCtx * ctx)242 void CRYPT_EAL_CipherDeinit(CRYPT_EAL_CipherCtx *ctx)
243 {
244     if (ctx == NULL) {
245         // If the ctx is NULL during deinit, it is not considered as an error.
246         return;
247     }
248     if (ctx->method == NULL || ctx->method->deinitCtx == NULL) {
249         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_EAL_ALG_NOT_SUPPORT);
250         return;
251     }
252 
253     int32_t ret = ctx->method->deinitCtx(ctx->ctx);
254     if (ret != CRYPT_SUCCESS) {
255         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, ret);
256     }
257 
258     // Restore the state to the state after the new is successful.
259     ctx->states = EAL_CIPHER_STATE_NEW;
260     EAL_EventReport(CRYPT_EVENT_ZERO, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_SUCCESS);
261 }
262 
263 // no need for IV, the value can be set to NULL
CRYPT_EAL_CipherReinit(CRYPT_EAL_CipherCtx * ctx,uint8_t * iv,uint32_t ivLen)264 int32_t CRYPT_EAL_CipherReinit(CRYPT_EAL_CipherCtx *ctx, uint8_t *iv, uint32_t ivLen)
265 {
266     int32_t ret;
267     if (ctx == NULL) {
268         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, CRYPT_CIPHER_MAX, CRYPT_NULL_INPUT);
269         return CRYPT_NULL_INPUT;
270     }
271 
272     // Without init, reinit cannot be invoked directly.
273     if (ctx->states == EAL_CIPHER_STATE_NEW) {
274         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_EAL_ERR_STATE);
275         return CRYPT_EAL_ERR_STATE;
276     }
277 
278     // Reset the IV. In this case, reset the IV is not restricted by the states.
279     if (ctx->method == NULL || ctx->method->ctrl == NULL) {
280         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_EAL_ALG_NOT_SUPPORT);
281         return CRYPT_EAL_ALG_NOT_SUPPORT;
282     }
283     ret = ctx->method->ctrl(ctx->ctx, CRYPT_CTRL_REINIT_STATUS, iv, ivLen);
284     if (ret != CRYPT_SUCCESS) {
285         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, ret);
286         return ret;
287     }
288 
289     // Reset the states.
290     ctx->states = EAL_CIPHER_STATE_INIT;
291     EAL_EventReport(CRYPT_EVENT_SETSSP, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_SUCCESS);
292     return CRYPT_SUCCESS;
293 }
294 
IsPartialOverLap(const void * out,const void * in,uint32_t len)295 static bool IsPartialOverLap(const void *out, const void *in, uint32_t len)
296 {
297     uintptr_t diff;
298     if ((uintptr_t)out > (uintptr_t)in) {
299         diff = (uintptr_t)out - (uintptr_t)in;
300         return diff < (uintptr_t)len;
301     }
302     // If in >= out, this case is valid.
303     return false;
304 }
305 
CheckUpdateParam(const CRYPT_EAL_CipherCtx * ctx,const uint8_t * in,uint32_t inLen,const uint8_t * out,const uint32_t * outLen)306 static int32_t CheckUpdateParam(const CRYPT_EAL_CipherCtx *ctx, const uint8_t *in, uint32_t inLen, const uint8_t *out,
307     const uint32_t *outLen)
308 {
309     if (ctx == NULL || out == NULL || outLen == NULL || (in == NULL && inLen != 0)) {
310         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
311         return CRYPT_NULL_INPUT;
312     }
313     if ((in != NULL && inLen != 0) && IsPartialOverLap(out, in, inLen)) {
314         BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_PART_OVERLAP);
315         return CRYPT_EAL_ERR_PART_OVERLAP;
316     }
317     // If the state is not init or update, the state is regarded as an error.
318     // If the state is final or new, update cannot be directly invoked.
319     if (!(ctx->states == EAL_CIPHER_STATE_INIT || ctx->states == EAL_CIPHER_STATE_UPDATE)) {
320         BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_STATE);
321         return CRYPT_EAL_ERR_STATE;
322     }
323     if (ctx->method == NULL || ctx->method->update == NULL) {
324         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_EAL_ALG_NOT_SUPPORT);
325         return CRYPT_EAL_ALG_NOT_SUPPORT;
326     }
327     return CRYPT_SUCCESS;
328 }
329 
CRYPT_EAL_CipherUpdate(CRYPT_EAL_CipherCtx * ctx,const uint8_t * in,uint32_t inLen,uint8_t * out,uint32_t * outLen)330 int32_t CRYPT_EAL_CipherUpdate(CRYPT_EAL_CipherCtx *ctx, const uint8_t *in, uint32_t inLen, uint8_t *out,
331     uint32_t *outLen)
332 {
333     int32_t ret = CheckUpdateParam(ctx, in, inLen, out, outLen);
334     if (ret != CRYPT_SUCCESS) {
335         // The push error in CheckUpdateParam can be locate the only error location. No need to add the push error here.
336         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, (ctx == NULL) ? CRYPT_CIPHER_MAX : ctx->id, ret);
337         return ret;
338     }
339 
340     ret = ctx->method->update(ctx->ctx, in, inLen, out, outLen);
341     if (ret != CRYPT_SUCCESS) {
342         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, ret);
343         return ret;
344     }
345     ctx->states = EAL_CIPHER_STATE_UPDATE;
346     return CRYPT_SUCCESS;
347 }
348 
CheckFinalParam(const CRYPT_EAL_CipherCtx * ctx,const uint8_t * out,const uint32_t * outLen)349 int32_t CheckFinalParam(const CRYPT_EAL_CipherCtx *ctx, const uint8_t *out, const uint32_t *outLen)
350 {
351     if (ctx == NULL || out == NULL || outLen == NULL) {
352         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
353         return CRYPT_NULL_INPUT;
354     }
355     // If the state is not init or update, the state is regarded as an error.
356     // If the state is final or new, update cannot be directly invoked.
357     if (!(ctx->states == EAL_CIPHER_STATE_UPDATE || ctx->states == EAL_CIPHER_STATE_INIT)) {
358         BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_STATE);
359         return CRYPT_EAL_ERR_STATE;
360     }
361 
362     if (ctx->method == NULL || ctx->method->final == NULL) {
363         BSL_ERR_PUSH_ERROR(CRYPT_EAL_ALG_NOT_SUPPORT);
364         return CRYPT_EAL_ALG_NOT_SUPPORT;
365     }
366     return CRYPT_SUCCESS;
367 }
368 
CRYPT_EAL_CipherFinal(CRYPT_EAL_CipherCtx * ctx,uint8_t * out,uint32_t * outLen)369 int32_t CRYPT_EAL_CipherFinal(CRYPT_EAL_CipherCtx *ctx, uint8_t *out, uint32_t *outLen)
370 {
371     int32_t ret;
372     ret = CheckFinalParam(ctx, out, outLen);
373     if (ret != CRYPT_SUCCESS) {
374         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, (ctx == NULL) ? CRYPT_CIPHER_MAX : ctx->id, ret);
375         return ret;
376     }
377 
378     ret = ctx->method->final(ctx->ctx, out, outLen);
379     if (ret != CRYPT_SUCCESS) {
380         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, ret);
381         return ret;
382     }
383 
384     ctx->states = EAL_CIPHER_STATE_FINAL;
385     return CRYPT_SUCCESS;
386 }
387 
CipherCtrlIsCanSet(const CRYPT_EAL_CipherCtx * ctx,int32_t type)388 static bool CipherCtrlIsCanSet(const CRYPT_EAL_CipherCtx *ctx, int32_t type)
389 {
390     if (ctx->states == EAL_CIPHER_STATE_NEW) {
391         return false;
392     }
393     if (ctx->states == EAL_CIPHER_STATE_FINAL) {
394         return false;
395     }
396     if ((ctx->states == EAL_CIPHER_STATE_UPDATE) &&
397         (type == CRYPT_CTRL_SET_COUNT || type == CRYPT_CTRL_SET_TAGLEN ||
398         type == CRYPT_CTRL_SET_MSGLEN || type == CRYPT_CTRL_SET_AAD)) {
399         return false;
400     }
401     return true;
402 }
403 
CRYPT_EAL_CipherCtrl(CRYPT_EAL_CipherCtx * ctx,int32_t type,void * data,uint32_t len)404 int32_t CRYPT_EAL_CipherCtrl(CRYPT_EAL_CipherCtx *ctx, int32_t type, void *data, uint32_t len)
405 {
406     if (ctx == NULL) {
407         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, CRYPT_CIPHER_MAX, CRYPT_NULL_INPUT);
408         return CRYPT_NULL_INPUT;
409     }
410     // The IV cannot be set through the Ctrl. You need to set the IV through the init and reinit.
411     if (type == CRYPT_CTRL_SET_IV || type == CRYPT_CTRL_REINIT_STATUS) {
412         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_EAL_CIPHER_CTRL_ERROR);
413         return CRYPT_EAL_CIPHER_CTRL_ERROR;
414     }
415 
416     // If the algorithm is running in the intermediate state, write operations are not allowed.
417     if (!CipherCtrlIsCanSet(ctx, type)) {
418         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_EAL_ERR_STATE);
419         return CRYPT_EAL_ERR_STATE;
420     }
421     // Setting AAD indicates that the encryption operation has started and no more write operations are allowed.
422     if (type == CRYPT_CTRL_SET_AAD) {
423         ctx->states = EAL_CIPHER_STATE_UPDATE;
424     } else if (type == CRYPT_CTRL_GET_TAG) {
425         // After getTag the system enters the final state.
426         ctx->states = EAL_CIPHER_STATE_FINAL;
427     }
428     if (ctx->method == NULL || ctx->method->ctrl == NULL) {
429         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_EAL_ALG_NOT_SUPPORT);
430         return CRYPT_EAL_ALG_NOT_SUPPORT;
431     }
432     int32_t ret = ctx->method->ctrl(ctx->ctx, type, data, len);
433     if (ret != CRYPT_SUCCESS) {
434         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, ret);
435         return ret;
436     }
437     return ret;
438 }
439 
CRYPT_EAL_CipherSetPadding(CRYPT_EAL_CipherCtx * ctx,CRYPT_PaddingType type)440 int32_t CRYPT_EAL_CipherSetPadding(CRYPT_EAL_CipherCtx *ctx, CRYPT_PaddingType type)
441 {
442     if (ctx == NULL) {
443         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, CRYPT_CIPHER_MAX, CRYPT_NULL_INPUT);
444         return CRYPT_NULL_INPUT;
445     }
446 
447     if (ctx->method == NULL || ctx->method->ctrl == NULL) {
448         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_EAL_ALG_NOT_SUPPORT);
449         return CRYPT_EAL_ALG_NOT_SUPPORT;
450     }
451     int32_t ret = ctx->method->ctrl(ctx->ctx, CRYPT_CTRL_SET_PADDING, (void *)&type, sizeof(type));
452     if (ret != CRYPT_SUCCESS) {
453         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, ret);
454     }
455     return ret;
456 }
457 
CRYPT_EAL_CipherGetPadding(CRYPT_EAL_CipherCtx * ctx)458 int32_t CRYPT_EAL_CipherGetPadding(CRYPT_EAL_CipherCtx *ctx)
459 {
460     if (ctx == NULL) {
461         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, CRYPT_CIPHER_MAX, CRYPT_NULL_INPUT);
462         return CRYPT_NULL_INPUT;
463     }
464 
465     if (ctx->method == NULL || ctx->method->ctrl == NULL) {
466         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, CRYPT_EAL_ALG_NOT_SUPPORT);
467         return CRYPT_EAL_ALG_NOT_SUPPORT;
468     }
469     int32_t type;
470     int32_t ret = ctx->method->ctrl(ctx->ctx, CRYPT_CTRL_GET_PADDING, (void *)&type, sizeof(type));
471     if (ret != CRYPT_SUCCESS) {
472         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, ctx->id, ret);
473         return CRYPT_PADDING_MAX_COUNT;
474     }
475     return type;
476 }
477 
CRYPT_EAL_CipherIsValidAlgId(CRYPT_CIPHER_AlgId id)478 bool CRYPT_EAL_CipherIsValidAlgId(CRYPT_CIPHER_AlgId id)
479 {
480     const EAL_CipherMethod *m = NULL;
481     return EAL_FindCipher(id, &m) == CRYPT_SUCCESS;
482 }
483 
484 
485 static const uint32_t CIPHER_IS_AEAD[] = {
486     CRYPT_CIPHER_AES128_CCM,
487     CRYPT_CIPHER_AES192_CCM,
488     CRYPT_CIPHER_AES256_CCM,
489     CRYPT_CIPHER_AES128_GCM,
490     CRYPT_CIPHER_AES192_GCM,
491     CRYPT_CIPHER_AES256_GCM,
492     CRYPT_CIPHER_CHACHA20_POLY1305,
493     CRYPT_CIPHER_SM4_GCM,
494 };
495 
496 // Check whether the algorithm is the AEAD algorithm. If yes, true is returned. Otherwise, false is returned.
IsAeadAlg(CRYPT_CIPHER_AlgId id)497 static bool IsAeadAlg(CRYPT_CIPHER_AlgId id)
498 {
499     if (ParamIdIsValid(id, CIPHER_IS_AEAD, sizeof(CIPHER_IS_AEAD) / sizeof(CIPHER_IS_AEAD[0]))) {
500         return true;
501     }
502     return false;
503 }
504 
CRYPT_EAL_CipherGetInfo(CRYPT_CIPHER_AlgId id,int32_t type,uint32_t * infoValue)505 int32_t CRYPT_EAL_CipherGetInfo(CRYPT_CIPHER_AlgId id, int32_t type, uint32_t *infoValue)
506 {
507     if (infoValue == NULL) {
508         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, id, CRYPT_INVALID_ARG);
509         return CRYPT_INVALID_ARG;
510     }
511 
512     CRYPT_CipherInfo info = {0};
513     if (EAL_GetCipherInfo(id, &info) != CRYPT_SUCCESS) {
514         EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, id, CRYPT_ERR_ALGID);
515         return CRYPT_ERR_ALGID;
516     }
517 
518     switch (type) {
519         case CRYPT_INFO_IS_AEAD:
520             (*infoValue) = IsAeadAlg(id) ? 1 : 0;
521             break;
522         case CRYPT_INFO_IS_STREAM:
523             (*infoValue) = (uint32_t)!((info.blockSize) != 1);
524             break;
525         case CRYPT_INFO_IV_LEN:
526             (*infoValue) = info.ivLen;
527             break;
528         case CRYPT_INFO_KEY_LEN:
529             (*infoValue) = info.keyLen;
530             break;
531         case CRYPT_INFO_BLOCK_LEN:
532             (*infoValue) = (uint32_t)info.blockSize;
533             break;
534         default:
535             EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_CIPHER, id, CRYPT_EAL_INTO_TYPE_NOT_SUPPORT);
536             return CRYPT_EAL_INTO_TYPE_NOT_SUPPORT;
537     }
538 
539     return CRYPT_SUCCESS;
540 }
541 
542 #endif
543