• 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 #ifdef HITLS_CRYPTO_GCM
18 
19 #include <stdint.h>
20 #include "securec.h"
21 #include "bsl_sal.h"
22 #include "bsl_err_internal.h"
23 #include "crypt_utils.h"
24 #include "crypt_errno.h"
25 #include "crypt_modes_gcm.h"
26 #include "modes_local.h"
27 #include "crypt_modes.h"
28 
MODES_GCM_SetKey(MODES_CipherGCMCtx * ctx,const uint8_t * key,uint32_t len)29 int32_t MODES_GCM_SetKey(MODES_CipherGCMCtx *ctx, const uint8_t *key, uint32_t len)
30 {
31     if (ctx == NULL) {
32         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
33         return CRYPT_NULL_INPUT;
34     }
35     int32_t ret = ctx->ciphMeth->setEncryptKey(ctx->ciphCtx, key, len);
36     if (ret != CRYPT_SUCCESS) {
37         BSL_ERR_PUSH_ERROR(ret);
38         return ret;
39     }
40     return MODES_GCM_InitHashTable(ctx);
41 }
42 
MODES_GCM_InitHashTable(MODES_CipherGCMCtx * ctx)43 int32_t MODES_GCM_InitHashTable(MODES_CipherGCMCtx *ctx)
44 {
45     if (ctx == NULL) {
46         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
47         return CRYPT_NULL_INPUT;
48     }
49     uint8_t gcmKey[GCM_BLOCKSIZE] = { 0 };
50     int32_t ret = ctx->ciphMeth->encryptBlock(ctx->ciphCtx, gcmKey, gcmKey, GCM_BLOCKSIZE);
51     if (ret != CRYPT_SUCCESS) {
52         BSL_ERR_PUSH_ERROR(ret);
53         return ret;
54     }
55     GcmTableGen4bit(gcmKey, ctx->hTable);
56     ctx->tagLen = GCM_BLOCKSIZE;
57     BSL_SAL_CleanseData(gcmKey, sizeof(gcmKey));
58     return CRYPT_SUCCESS;
59 }
60 
61 // Update the number of usage times.
CheckUseCnt(const MODES_CipherGCMCtx * ctx)62 static int32_t CheckUseCnt(const MODES_CipherGCMCtx *ctx)
63 {
64     // 128, 120, 112, 104, or 96 that is 12 byte - 16 byte
65     if (ctx->cryptCnt == GCM_MAX_INVOCATIONS_TIMES) {
66         BSL_ERR_PUSH_ERROR(CRYPT_MODES_KEYUSE_TOOMANY_TIME);
67         return CRYPT_MODES_KEYUSE_TOOMANY_TIME;
68     }
69     return CRYPT_SUCCESS;
70 }
71 
72 /**
73  * NIST_800-38D-5.2
74  * 1 ≤ len(IV) ≤ 2^64 - 1 (bit)
75  * It is currently restricted to no more than 2^32 - 1 bytes
76  */
MODES_GCM_SetIv(MODES_CipherGCMCtx * ctx,const uint8_t * iv,uint32_t ivLen)77 int32_t MODES_GCM_SetIv(MODES_CipherGCMCtx *ctx, const uint8_t *iv, uint32_t ivLen)
78 {
79     if (iv == NULL || ivLen == 0) {
80         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
81         return CRYPT_NULL_INPUT;
82     }
83     int32_t ret = CheckUseCnt(ctx); // Check the number of usage times.
84     if (ret != CRYPT_SUCCESS) {
85         BSL_ERR_PUSH_ERROR(ret);
86         return ret;
87     }
88     uint32_t i;
89     uint64_t len = (uint64_t)ivLen;
90     // when ivLen == 0, do reinit, no need to refersh iv
91     if (len == 12) { // len(IV ) = 96bit = 12byte
92         const uint8_t ivPad[4] = {0x00, 0x00, 0x00, 0x01};
93         /* Y0 = IV || 0^31 || 1  if len(IV ) = 96 = 12byte */
94         (void)memcpy_s(ctx->iv, GCM_BLOCKSIZE, iv, 12);
95         (void)memcpy_s(ctx->iv + 12, GCM_BLOCKSIZE - 12, ivPad, sizeof(ivPad)); // pad last 4bit(base = 12)
96     } else {
97         /* Y0 = GHASH(H, {}, IV ) otherwise */
98         (void)memset_s(ctx->iv, GCM_BLOCKSIZE, 0, GCM_BLOCKSIZE);
99         const uint8_t *off = iv;
100         uint32_t blockLen = ivLen & GCM_BLOCK_MASK;
101         uint32_t lastLen = ivLen - blockLen;
102         uint8_t tmp[GCM_BLOCKSIZE] = {0};
103         if (blockLen > 0) {
104             GcmHashMultiBlock(ctx->iv, ctx->hTable, off, blockLen);
105             off += blockLen;
106         }
107         if (lastLen > 0) {
108             for (i = 0; i < lastLen; i++) {
109                 tmp[i] = off[i];
110             }
111             GcmHashMultiBlock(ctx->iv, ctx->hTable, tmp, GCM_BLOCKSIZE);
112         }
113         len = (uint64_t)ivLen << 3; // bitLen = byteLen << 3
114         (void)BSL_SAL_CleanseData(tmp, GCM_BLOCKSIZE);
115         Uint64ToBeBytes(len, tmp + 8); // The last 8 bytes store the length of the IV.
116         GcmHashMultiBlock(ctx->iv, ctx->hTable, tmp, GCM_BLOCKSIZE);
117     }
118     /**
119      * NIST_800-38D-7.1
120      * GCTR(J0)
121      */
122     ctx->ciphMeth->encryptBlock(ctx->ciphCtx, ctx->iv, ctx->ek0, GCM_BLOCKSIZE);
123 
124     /**
125      * NIST_800-38D-7.1
126      * INC32
127      * the 32-bit incrementing function is applied to the pre-counter block
128      * to produce the initial counter block for an invocation of the GCTR
129      * function on the plaintext
130      */
131     uint32_t ctr = GET_UINT32_BE(ctx->iv, 12); // Offset of 12 bytes. Use the last four bytes.
132     ctr++;
133     PUT_UINT32_BE(ctr, ctx->iv, 12); // Writeback of offset 12 bytes
134 
135     // Reset information.
136     (void)memset_s(ctx->ghash, GCM_BLOCKSIZE, 0, GCM_BLOCKSIZE);
137     ctx->aadLen = 0;
138     (void)memset_s(ctx->last, GCM_BLOCKSIZE, 0, GCM_BLOCKSIZE);
139     ctx->lastLen = 0;
140     ctx->plaintextLen = 0;
141     (void)memset_s(ctx->remCt, GCM_BLOCKSIZE, 0, GCM_BLOCKSIZE);
142 
143     // Clear sensitive information.
144     BSL_SAL_CleanseData(&ctr, sizeof(uint32_t));
145     return CRYPT_SUCCESS;
146 }
147 
148 /**
149  * NIST_800-38D-5.2
150  * len(AAD) ≤ 2^64 - 1 (bit)
151  * Currently, it is restricted to no more than 2^32 - 1 bytes.
152  */
SetAad(MODES_CipherGCMCtx * ctx,const uint8_t * aad,uint32_t aadLen)153 static int32_t SetAad(MODES_CipherGCMCtx *ctx, const uint8_t *aad, uint32_t aadLen)
154 {
155     if (aad == NULL && aadLen != 0) {
156         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
157         return CRYPT_NULL_INPUT;
158     }
159     const uint8_t *off = aad;
160     uint32_t i;
161     if (ctx->aadLen != 0 || ctx->plaintextLen != 0) { // aad is set
162         BSL_ERR_PUSH_ERROR(CRYPT_MODES_AAD_REPEAT_SET_ERROR);
163         return CRYPT_MODES_AAD_REPEAT_SET_ERROR;
164     }
165     uint32_t blockLen = aadLen & GCM_BLOCK_MASK;
166     uint32_t lastLen = aadLen - blockLen;
167     if (blockLen > 0) {
168         GcmHashMultiBlock(ctx->ghash, ctx->hTable, off, blockLen);
169         off += blockLen;
170     }
171     if (lastLen > 0) {
172         uint8_t temp[GCM_BLOCKSIZE] = {0};
173         for (i = 0; i < lastLen; i++) {
174             temp[i] = off[i];
175         }
176         GcmHashMultiBlock(ctx->ghash, ctx->hTable, temp, GCM_BLOCKSIZE);
177     }
178     ctx->aadLen = aadLen;
179     return CRYPT_SUCCESS;
180 }
181 
182 // Overflow occurs when the encryption length is determined and the encrypted length information is updated.
CryptLenCheckAndRefresh(MODES_CipherGCMCtx * ctx,uint32_t len)183 int32_t CryptLenCheckAndRefresh(MODES_CipherGCMCtx *ctx, uint32_t len)
184 {
185     // The length of len is only 32 bits. This calculation does not cause overflow.
186     uint64_t plaintextLen = ctx->plaintextLen + len;
187     if (plaintextLen > GCM_MAX_COMBINED_LENGTH) {
188         BSL_ERR_PUSH_ERROR(CRYPT_MODES_CRYPTLEN_OVERFLOW);
189         return CRYPT_MODES_CRYPTLEN_OVERFLOW;
190     }
191     ctx->plaintextLen = plaintextLen;
192     return CRYPT_SUCCESS;
193 }
194 
GcmXorInEncrypt(XorCryptData * data,uint32_t len)195 static void GcmXorInEncrypt(XorCryptData *data, uint32_t len)
196 {
197     uint32_t i;
198     for (i = 0; i < len; i++) {
199         data->out[i] = data->in[i] ^ data->ctr[i];
200         data->tag[i] = data->out[i];
201     }
202 }
203 
GcmXorInDecrypt(XorCryptData * data,uint32_t len)204 static void GcmXorInDecrypt(XorCryptData *data, uint32_t len)
205 {
206     uint32_t i;
207     for (i = 0; i < len; i++) {
208         data->tag[i] = data->in[i];
209         data->out[i] = data->in[i] ^ data->ctr[i];
210     }
211 }
212 
213 // Process the remaining data in the last update.
MODES_GCM_LastHandle(MODES_CipherGCMCtx * ctx,const uint8_t * in,uint8_t * out,uint32_t len,bool enc)214 uint32_t MODES_GCM_LastHandle(MODES_CipherGCMCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, bool enc)
215 {
216     uint32_t lastLen = 0;
217     if (ctx->lastLen > 0) {
218         XorCryptData data;
219         lastLen = (ctx->lastLen < len) ? ctx->lastLen : len;
220         data.in = in;
221         data.out = out;
222         data.ctr = &(ctx->last[GCM_BLOCKSIZE - ctx->lastLen]);
223         data.tag = &(ctx->remCt[GCM_BLOCKSIZE - ctx->lastLen]);
224         if (enc) { // ctx->lastLen must be smaller than the GCM_BLOCKSIZE
225             GcmXorInEncrypt(&data, lastLen);
226         } else {
227             GcmXorInDecrypt(&data, lastLen);
228         }
229         // Refresh the remaining length.
230         ctx->lastLen -= lastLen;
231         if (ctx->lastLen == 0) {
232             GcmHashMultiBlock(ctx->ghash, ctx->hTable, ctx->remCt, GCM_BLOCKSIZE);
233         }
234     }
235     return lastLen;
236 }
237 
GcmMultiBlockCrypt(MODES_CipherGCMCtx * ctx,const uint8_t * in,uint8_t * out,uint32_t len,bool enc)238 static void GcmMultiBlockCrypt(MODES_CipherGCMCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, bool enc)
239 {
240     uint32_t blockLen = len;
241     const uint8_t *dataIn = in;
242     uint8_t *dataOut = out;
243     // count information, last 32 bits of the IV, with an offset of 12 bytes (16-4 = 12)
244     uint32_t ctr = GET_UINT32_BE(ctx->iv, 12);
245     if (enc == false) {
246         GcmHashMultiBlock(ctx->ghash, ctx->hTable, in, len);
247     }
248     while (blockLen > 0) {
249         ctx->ciphMeth->encryptBlock(ctx->ciphCtx, ctx->iv, ctx->last, GCM_BLOCKSIZE);
250         DATA64_XOR(dataIn, ctx->last, dataOut, GCM_BLOCKSIZE);
251         /**
252         * NIST_800-38D-7.1
253         * INC32
254         */
255         ctr++;
256         PUT_UINT32_BE(ctr, ctx->iv, 12); // Offset of 12 bytes. Use the last four bytes.
257         // Refresh the remaining length.
258         blockLen -= GCM_BLOCKSIZE;
259         // offset
260         dataIn += GCM_BLOCKSIZE;
261         dataOut += GCM_BLOCKSIZE;
262     }
263     if (enc) {
264         GcmHashMultiBlock(ctx->ghash, ctx->hTable, out, len);
265     }
266     // Clear sensitive information.
267     BSL_SAL_CleanseData(&ctr, sizeof(uint32_t));
268 }
269 
270 // enc: true: the encryption operation, false: the decryption operation
MODES_GCM_Crypt(MODES_CipherGCMCtx * ctx,const uint8_t * in,uint8_t * out,uint32_t len,bool enc)271 static int32_t MODES_GCM_Crypt(MODES_CipherGCMCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, bool enc)
272 {
273     if (ctx == NULL || out == NULL) {
274         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
275         return CRYPT_NULL_INPUT;
276     }
277     if (len != 0 && in == NULL) {
278         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
279         return CRYPT_NULL_INPUT;
280     }
281     int32_t ret = CryptLenCheckAndRefresh(ctx, len);
282     if (ret != CRYPT_SUCCESS) {
283         return ret;
284     }
285     uint32_t lastLen = MODES_GCM_LastHandle(ctx, in, out, len, enc);
286     // Data processing is complete. Exit.
287     if (lastLen == len) {
288         return CRYPT_SUCCESS;
289     }
290 
291     XorCryptData data;
292     data.in = in + lastLen;
293     data.out = out + lastLen;
294     data.ctr = ctx->last;
295     data.tag = ctx->remCt;
296 
297     uint32_t multiBlockLen = (len - lastLen) & GCM_BLOCK_MASK;
298     if (multiBlockLen > 0) {
299         GcmMultiBlockCrypt(ctx, data.in, data.out, multiBlockLen, enc);
300         data.in += multiBlockLen;
301         data.out += multiBlockLen;
302     }
303     uint32_t remLen = len - lastLen - multiBlockLen;
304     if (remLen > 0) {
305         // count information, last 32 bits of the IV, with an offset of 12 bytes (16-4 = 12)
306         uint32_t ctr = GET_UINT32_BE(ctx->iv, 12);
307         (void)ctx->ciphMeth->encryptBlock(ctx->ciphCtx, ctx->iv, ctx->last, GCM_BLOCKSIZE);
308         if (enc) {
309             GcmXorInEncrypt(&data, remLen);
310         } else {
311             GcmXorInDecrypt(&data, remLen);
312         }
313         /**
314          * NIST_800-38D-7.1
315          * INC32
316          */
317         ctr++;
318         PUT_UINT32_BE(ctr, ctx->iv, 12); // Offset of 12 bytes. Use the last four bytes.
319         // Clear sensitive information.
320         BSL_SAL_CleanseData(&ctr, sizeof(uint32_t));
321     }
322     ctx->lastLen = (remLen > 0) ? (GCM_BLOCKSIZE - remLen) : 0;
323 
324     return CRYPT_SUCCESS;
325 }
326 
GcmPad(MODES_CipherGCMCtx * ctx)327 static void GcmPad(MODES_CipherGCMCtx *ctx)
328 {
329     // S = GHASHH (A || 0v || C || 0u || [len(A)]64 || [len(C)]64).
330     if (ctx->lastLen != 0) {
331         uint32_t offset = GCM_BLOCKSIZE - ctx->lastLen;
332         (void)memset_s(ctx->remCt + offset, GCM_BLOCKSIZE - offset, 0, ctx->lastLen);
333         GcmHashMultiBlock(ctx->ghash, ctx->hTable, ctx->remCt, GCM_BLOCKSIZE);
334     }
335     uint64_t aadLen = (uint64_t)(ctx->aadLen) << 3; // bitLen = byteLen << 3
336     uint64_t plaintextLen = ctx->plaintextLen << 3; // bitLen = byteLen << 3
337     uint8_t padBuf[GCM_BLOCKSIZE];
338     Uint64ToBeBytes(aadLen, padBuf);
339     Uint64ToBeBytes(plaintextLen, padBuf + 8); // The last 64 bits (8 bytes) is the length of the ciphertext.
340 
341     GcmHashMultiBlock(ctx->ghash, ctx->hTable, padBuf, GCM_BLOCKSIZE);
342 }
343 
SetTagLen(MODES_CipherGCMCtx * ctx,const uint8_t * val,uint32_t len)344 static int32_t SetTagLen(MODES_CipherGCMCtx *ctx, const uint8_t *val, uint32_t len)
345 {
346     if (val == NULL) {
347         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
348         return CRYPT_NULL_INPUT;
349     }
350     if (len != sizeof(uint32_t)) {
351         BSL_ERR_PUSH_ERROR(CRYPT_MODES_CTRL_TAGLEN_ERROR);
352         return CRYPT_MODES_CTRL_TAGLEN_ERROR;
353     }
354     /**
355      * NIST_800-38D-5.2.1.2
356      * The bit length of the tag, denoted t, is a security parameter, as discussed in Appendix B.
357      * In general, t may be any one of the following five values: 128, 120, 112, 104, or 96. For certain
358      * applications, t may be 64 or 32; guidance for the use of these two tag lengths, including
359      * requirements on the length of the input data and the lifetime of the ciphCtx in these cases,
360      * is given in Appendix C
361      */
362     uint32_t tagLen = *((const uint32_t *)val);
363     // 32bit is 4 bytes, 64bit is 8 bytes, 128, 120, 112, 104, or 96 is 12byte - 16byte
364     if (tagLen == 4 || tagLen == 8 || (tagLen >= 12 && tagLen <= 16)) {
365         ctx->tagLen = (uint8_t)tagLen;
366         return CRYPT_SUCCESS;
367     }
368     BSL_ERR_PUSH_ERROR(CRYPT_MODES_CTRL_TAGLEN_ERROR);
369     return CRYPT_MODES_CTRL_TAGLEN_ERROR;
370 }
371 
GetTag(MODES_CipherGCMCtx * ctx,uint8_t * val,uint32_t len)372 static int32_t GetTag(MODES_CipherGCMCtx *ctx, uint8_t *val, uint32_t len)
373 {
374     if (val == NULL) {
375         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
376         return CRYPT_NULL_INPUT;
377     }
378     if (len != ctx->tagLen) {
379         BSL_ERR_PUSH_ERROR(CRYPT_MODES_TAGLEN_ERROR);
380         return CRYPT_MODES_TAGLEN_ERROR;
381     }
382     ctx->cryptCnt++; // The encryption/decryption process ends. Key usage times + 1
383     GcmPad(ctx);
384     uint32_t i;
385     for (i = 0; i < len; i++) {
386         val[i] = ctx->ghash[i] ^ ctx->ek0[i];
387     }
388     return CRYPT_SUCCESS;
389 }
390 
MODES_GCM_Encrypt(MODES_CipherGCMCtx * ctx,const uint8_t * in,uint8_t * out,uint32_t len)391 int32_t MODES_GCM_Encrypt(MODES_CipherGCMCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len)
392 {
393     return MODES_GCM_Crypt(ctx, in, out, len, true);
394 }
395 
MODES_GCM_Decrypt(MODES_CipherGCMCtx * ctx,const uint8_t * in,uint8_t * out,uint32_t len)396 int32_t MODES_GCM_Decrypt(MODES_CipherGCMCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len)
397 {
398     return MODES_GCM_Crypt(ctx, in, out, len, false);
399 }
400 
MODES_GCM_Ctrl(MODES_GCM_Ctx * modeCtx,int32_t opt,void * val,uint32_t len)401 int32_t MODES_GCM_Ctrl(MODES_GCM_Ctx *modeCtx, int32_t opt, void *val, uint32_t len)
402 {
403     if (modeCtx == NULL) {
404         return CRYPT_NULL_INPUT;
405     }
406     switch (opt) {
407         case CRYPT_CTRL_SET_IV:
408         case CRYPT_CTRL_REINIT_STATUS:
409             return MODES_GCM_SetIv(&modeCtx->gcmCtx, val, len);
410         case CRYPT_CTRL_SET_TAGLEN:
411             return SetTagLen(&modeCtx->gcmCtx, val, len);
412         case CRYPT_CTRL_SET_AAD:
413             return SetAad(&modeCtx->gcmCtx, val, len);
414         case CRYPT_CTRL_GET_TAG:
415             return GetTag(&modeCtx->gcmCtx, val, len);
416         case CRYPT_CTRL_GET_BLOCKSIZE:
417             if (val == NULL || len != sizeof(uint32_t)) {
418                 return CRYPT_INVALID_ARG;
419             }
420             *(int32_t *)val = 1;
421             return CRYPT_SUCCESS;
422         default:
423             BSL_ERR_PUSH_ERROR(CRYPT_MODES_CTRL_TYPE_ERROR);
424             return CRYPT_MODES_CTRL_TYPE_ERROR;
425     }
426 }
427 
MODES_GCM_NewCtx(int32_t algId)428 MODES_GCM_Ctx *MODES_GCM_NewCtx(int32_t algId)
429 {
430     const EAL_SymMethod *method = EAL_GetSymMethod(algId);
431     if (method == NULL) {
432         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
433         return NULL;
434     }
435     MODES_GCM_Ctx *ctx = BSL_SAL_Calloc(1, sizeof(MODES_GCM_Ctx));
436     if (ctx == NULL) {
437         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
438         return ctx;
439     }
440     ctx->algId = algId;
441 
442     ctx->gcmCtx.ciphCtx = BSL_SAL_Calloc(1, method->ctxSize);
443     if (ctx->gcmCtx.ciphCtx  == NULL) {
444         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
445         BSL_SAL_Free(ctx);
446         return NULL;
447     }
448 
449     ctx->gcmCtx.ciphMeth = method;
450     return ctx;
451 }
452 
MODES_GCM_InitCtx(MODES_GCM_Ctx * modeCtx,const uint8_t * key,uint32_t keyLen,const uint8_t * iv,uint32_t ivLen,bool enc)453 int32_t MODES_GCM_InitCtx(MODES_GCM_Ctx *modeCtx, const uint8_t *key, uint32_t keyLen, const uint8_t *iv,
454     uint32_t ivLen, bool enc)
455 {
456     if (modeCtx == NULL) {
457         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
458         return CRYPT_NULL_INPUT;
459     }
460     int32_t ret = MODES_GCM_SetKey(&modeCtx->gcmCtx, key, keyLen);
461     if (ret != CRYPT_SUCCESS) {
462         return ret;
463     }
464 
465     ret = MODES_GCM_SetIv(&modeCtx->gcmCtx, iv, ivLen);
466     if (ret != CRYPT_SUCCESS) {
467         (void)MODES_GCM_DeInitCtx(modeCtx);
468         return ret;
469     }
470     modeCtx->enc = enc;
471     return ret;
472 }
473 
MODES_GCM_Update(MODES_GCM_Ctx * modeCtx,const uint8_t * in,uint32_t inLen,uint8_t * out,uint32_t * outLen)474 int32_t MODES_GCM_Update(MODES_GCM_Ctx *modeCtx, const uint8_t *in, uint32_t inLen, uint8_t *out, uint32_t *outLen)
475 {
476     return MODES_CipherStreamProcess(modeCtx->enc ? MODES_GCM_Encrypt : MODES_GCM_Decrypt, &modeCtx->gcmCtx,
477         in, inLen, out, outLen);
478 }
479 
MODES_GCM_Final(MODES_GCM_Ctx * modeCtx,uint8_t * out,uint32_t * outLen)480 int32_t MODES_GCM_Final(MODES_GCM_Ctx *modeCtx, uint8_t *out, uint32_t *outLen)
481 {
482     (void) modeCtx;
483     (void) out;
484     (void) outLen;
485     return CRYPT_EAL_CIPHER_FINAL_WITH_AEAD_ERROR;
486 }
487 
MODES_GCM_DeInitCtx(MODES_GCM_Ctx * modeCtx)488 int32_t MODES_GCM_DeInitCtx(MODES_GCM_Ctx *modeCtx)
489 {
490     if (modeCtx == NULL) {
491         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
492         return CRYPT_NULL_INPUT;
493     }
494     int32_t algId = modeCtx->algId;
495     void *ciphCtx = modeCtx->gcmCtx.ciphCtx;
496     const EAL_SymMethod *ciphMeth = modeCtx->gcmCtx.ciphMeth;
497     modeCtx->gcmCtx.ciphMeth->cipherDeInitCtx(ciphCtx);
498     BSL_SAL_CleanseData((void *)(&(modeCtx->gcmCtx)), sizeof(MODES_CipherGCMCtx));
499     modeCtx->gcmCtx.ciphCtx = ciphCtx;
500     modeCtx->gcmCtx.ciphMeth = ciphMeth;
501     modeCtx->algId = algId;
502     return CRYPT_SUCCESS;
503 }
504 
MODES_GCM_FreeCtx(MODES_GCM_Ctx * modeCtx)505 void MODES_GCM_FreeCtx(MODES_GCM_Ctx *modeCtx)
506 {
507     if (modeCtx == NULL) {
508         return;
509     }
510     (void)BSL_SAL_ClearFree(modeCtx->gcmCtx.ciphCtx, modeCtx->gcmCtx.ciphMeth->ctxSize);
511     (void)BSL_SAL_CleanseData(modeCtx, sizeof(MODES_GCM_Ctx));
512     BSL_SAL_Free(modeCtx);
513 }
514 
515 
MODES_GCM_InitCtxEx(MODES_GCM_Ctx * modeCtx,const uint8_t * key,uint32_t keyLen,const uint8_t * iv,uint32_t ivLen,void * param,bool enc)516 int32_t MODES_GCM_InitCtxEx(MODES_GCM_Ctx *modeCtx, const uint8_t *key, uint32_t keyLen, const uint8_t *iv,
517     uint32_t ivLen, void *param, bool enc)
518 {
519     (void)param;
520     if (modeCtx == NULL) {
521         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
522         return CRYPT_NULL_INPUT;
523     }
524     switch (modeCtx->algId) {
525         case CRYPT_CIPHER_SM4_GCM:
526 #ifdef HITLS_CRYPTO_SM4
527             return SM4_GCM_InitCtx(modeCtx, key, keyLen, iv, ivLen, enc);
528 #else
529             return CRYPT_EAL_ALG_NOT_SUPPORT;
530 #endif
531         default:
532             return MODES_GCM_InitCtx(modeCtx, key, keyLen, iv, ivLen, enc);
533     }
534 }
535 
MODES_GCM_UpdateEx(MODES_GCM_Ctx * modeCtx,const uint8_t * in,uint32_t inLen,uint8_t * out,uint32_t * outLen)536 int32_t MODES_GCM_UpdateEx(MODES_GCM_Ctx *modeCtx, const uint8_t *in, uint32_t inLen, uint8_t *out, uint32_t *outLen)
537 {
538     if (modeCtx == NULL) {
539         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
540         return CRYPT_NULL_INPUT;
541     }
542     switch (modeCtx->algId) {
543         case CRYPT_CIPHER_AES128_GCM:
544         case CRYPT_CIPHER_AES192_GCM:
545         case CRYPT_CIPHER_AES256_GCM:
546 #ifdef HITLS_CRYPTO_AES
547             return AES_GCM_Update(modeCtx, in, inLen, out, outLen);
548 #else
549             return CRYPT_EAL_ALG_NOT_SUPPORT;
550 #endif
551         case CRYPT_CIPHER_SM4_GCM:
552 #ifdef HITLS_CRYPTO_SM4
553             return SM4_GCM_Update(modeCtx, in, inLen, out, outLen);
554 #else
555             return CRYPT_EAL_ALG_NOT_SUPPORT;
556 #endif
557         default:
558             return MODES_GCM_Update(modeCtx, in, inLen, out, outLen);
559     }
560 }
561 
562 #endif