• 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_CCM
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 "modes_local.h"
26 #include "ccm_core.h"
27 #include "crypt_modes_ccm.h"
28 #include "crypt_modes.h"
29 
30 
XorInEncrypt(XorCryptData * data,uint32_t len)31 void XorInEncrypt(XorCryptData *data, uint32_t len)
32 {
33     uint32_t i;
34     for (i = 0; i < len; i++) {
35         data->tag[i] ^= data->in[i];
36         data->out[i] = data->in[i] ^ data->ctr[i];
37     }
38 }
39 
XorInEncryptBlock(XorCryptData * data)40 void XorInEncryptBlock(XorCryptData *data)
41 {
42     DATA64_XOR(data->in, data->tag, data->tag, CCM_BLOCKSIZE);
43     DATA64_XOR(data->in, data->ctr, data->out, CCM_BLOCKSIZE);
44 }
45 
XorInDecrypt(XorCryptData * data,uint32_t len)46 void XorInDecrypt(XorCryptData *data, uint32_t len)
47 {
48     uint32_t i;
49     // Decryption
50     for (i = 0; i < len; i++) {
51         data->out[i] = data->in[i] ^ data->ctr[i];
52         data->tag[i] ^= data->out[i];
53     }
54 }
55 
XorInDecryptBlock(XorCryptData * data)56 void XorInDecryptBlock(XorCryptData *data)
57 {
58     DATA64_XOR(data->in, data->ctr, data->out, CCM_BLOCKSIZE);
59     DATA64_XOR(data->out, data->tag, data->tag, CCM_BLOCKSIZE);
60 }
61 
62 // Process the remaining data in the last update.
CcmLastHandle(MODES_CipherCCMCtx * ctx,const uint8_t * in,uint8_t * out,uint32_t len,bool enc)63 static uint32_t CcmLastHandle(MODES_CipherCCMCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, bool enc)
64 {
65     uint32_t lastLen = (ctx->lastLen < len) ? ctx->lastLen : len;
66     if (ctx->lastLen > 0) {
67         XorCryptData data;
68         data.in = in;
69         data.out = out;
70         data.ctr = &(ctx->last[CCM_BLOCKSIZE - ctx->lastLen]);
71         data.tag = &(ctx->tag[CCM_BLOCKSIZE - ctx->lastLen]);
72         if (enc) {
73             XorInEncrypt(&data, lastLen);
74         } else {
75             XorInDecrypt(&data, lastLen);
76         }
77         // Refresh the remaining length.
78         // The judgment of the function entry ensures that lastLen does not exceed ctx->lastLen,
79         // and this forcible transition does not occur truncation.
80         ctx->lastLen -= (uint8_t)lastLen;
81     }
82     return lastLen;
83 }
84 
RefreshNonce(MODES_CipherCCMCtx * ctx)85 static void RefreshNonce(MODES_CipherCCMCtx *ctx)
86 {
87     if ((ctx->nonce[0] & (~0x07)) != 0) {
88         /**
89          * RFC_3610-2.3
90          * Bit Number   Contents
91          * ----------   ----------------------
92          * 7            Reserved (always zero)
93          * 6            Reserved (always zero)
94          * 5 ... 3      Zero
95          * 2 ... 0      L'
96          */
97         ctx->nonce[0] &= 0x07;
98 
99         /**
100          * RFC_3610-2.3
101          * Octet Number   Contents
102          * ------------   ---------
103          * 0              Flags
104          * 1 ... 15-L     Nonce N
105          * 16-L ... 15    Counter i
106          */
107         uint8_t i;
108         uint8_t l = ctx->nonce[0] + 1;
109         for (i = 1; i < l; i++) {
110             ctx->nonce[CCM_BLOCKSIZE - 1 - i] = 0;
111         }
112         /**
113          * RFC_3610-2.3
114          * The message is encrypted by XORing the octets of message m with the
115          * first l(m) octets of the concatenation of S_1, S_2, S_3, ... .  Note
116          * that S_0 is not used to encrypt the message.
117          */
118         ctx->nonce[CCM_BLOCKSIZE - 1] = 1;
119     }
120 }
121 
TagInit(MODES_CipherCCMCtx * ctx)122 static int32_t TagInit(MODES_CipherCCMCtx *ctx)
123 {
124     if (ctx->tagInit == 0) {
125         int32_t ret = ctx->ciphMeth->encryptBlock(ctx->ciphCtx, ctx->nonce, ctx->tag, CCM_BLOCKSIZE);
126         if (ret != CRYPT_SUCCESS) {
127             BSL_ERR_PUSH_ERROR(ret);
128             return ret;
129         }
130         ctx->tagInit = 1;
131     }
132     return CRYPT_SUCCESS;
133 }
134 
CcmBlocks(MODES_CipherCCMCtx * ctx,const uint8_t * in,uint8_t * out,uint32_t len,bool enc)135 static int32_t CcmBlocks(MODES_CipherCCMCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, bool enc)
136 {
137     XorCryptData data;
138     data.in = in;
139     data.out = out;
140     data.ctr = ctx->last;
141     data.tag = ctx->tag;
142 
143     uint8_t countLen = (ctx->nonce[0] & 0x07) + 1;
144     uint32_t dataLen = len;
145     void (*xorBlock)(XorCryptData *data) = enc ? XorInEncryptBlock : XorInDecryptBlock;
146     void (*xor)(XorCryptData *data, uint32_t len) = enc ? XorInEncrypt : XorInDecrypt;
147     while (dataLen >= CCM_BLOCKSIZE) { // process the integer multiple of 16bytes data
148         (void)ctx->ciphMeth->encryptBlock(ctx->ciphCtx, ctx->nonce, ctx->last, CCM_BLOCKSIZE);
149         xorBlock(&data);
150         (void)ctx->ciphMeth->encryptBlock(ctx->ciphCtx, ctx->tag, ctx->tag, CCM_BLOCKSIZE);
151         MODE_IncCounter(ctx->nonce + CCM_BLOCKSIZE - countLen, countLen); // counter +1
152         dataLen -= CCM_BLOCKSIZE;
153         data.in += CCM_BLOCKSIZE;
154         data.out += CCM_BLOCKSIZE;
155     }
156     if (dataLen > 0) { // process the integer multiple of 16bytes data
157         (void)ctx->ciphMeth->encryptBlock(ctx->ciphCtx, ctx->nonce, ctx->last, CCM_BLOCKSIZE);
158         xor(&data, dataLen);
159         MODE_IncCounter(ctx->nonce + CCM_BLOCKSIZE - countLen, countLen); // counter +1
160     }
161     return CRYPT_SUCCESS;
162 }
163 
164 // Enc: true for encryption and false for decryption.
CcmCrypt(MODES_CipherCCMCtx * ctx,const uint8_t * in,uint8_t * out,uint32_t len,bool enc,const CcmCore func)165 int32_t CcmCrypt(MODES_CipherCCMCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, bool enc, const CcmCore func)
166 {
167     if (ctx == NULL || ctx->ciphCtx == NULL || in == NULL || out == NULL || len == 0) {
168         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
169         return CRYPT_NULL_INPUT;
170     }
171 
172     if (len > ctx->msgLen) {
173         // The message length is exceeded.
174         BSL_ERR_PUSH_ERROR(CRYPT_MODES_MSGLEN_OVERFLOW);
175         return CRYPT_MODES_MSGLEN_OVERFLOW;
176     }
177     int32_t ret = TagInit(ctx);
178     if (ret != CRYPT_SUCCESS) {
179         BSL_ERR_PUSH_ERROR(ret);
180         return ret;
181     }
182     // Determine whether to start encryption and update the nonce information.
183     RefreshNonce(ctx);
184 
185     uint32_t lastLen = CcmLastHandle(ctx, in, out, len, enc);
186     if (lastLen != 0 && ctx->lastLen == 0) {
187         ret = ctx->ciphMeth->encryptBlock(ctx->ciphCtx, ctx->tag, ctx->tag, CCM_BLOCKSIZE);
188         if (ret != CRYPT_SUCCESS) {
189             BSL_ERR_PUSH_ERROR(ret);
190             return ret;
191         }
192     }
193     // Data processing is complete and exits in advance.
194     if (lastLen == len) {
195         ctx->msgLen -= len; // Refresh the remaining length.
196         return CRYPT_SUCCESS;
197     }
198 
199     uint32_t tmpLen = len - lastLen;
200     ret = func(ctx, in + lastLen, out + lastLen, tmpLen, enc);
201     if (ret != CRYPT_SUCCESS) {
202         // Returned by the internal function. No redundant push err is required.
203         return ret;
204     }
205     ctx->lastLen = (CCM_BLOCKSIZE - (tmpLen % CCM_BLOCKSIZE)) % CCM_BLOCKSIZE;
206     ctx->msgLen -= len; // Refresh the remaining length.
207     return CRYPT_SUCCESS;
208 }
209 
MODES_CCM_Encrypt(MODES_CipherCCMCtx * ctx,const uint8_t * in,uint8_t * out,uint32_t len)210 int32_t MODES_CCM_Encrypt(MODES_CipherCCMCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len)
211 {
212     return CcmCrypt(ctx, in, out, len, true, CcmBlocks);
213 }
214 
MODES_CCM_Decrypt(MODES_CipherCCMCtx * ctx,const uint8_t * in,uint8_t * out,uint32_t len)215 int32_t MODES_CCM_Decrypt(MODES_CipherCCMCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len)
216 {
217     return CcmCrypt(ctx, in, out, len, false, CcmBlocks);
218 }
219 
220 // 7 <= ivLen <= 13
SetIv(MODES_CipherCCMCtx * ctx,const void * val,uint32_t len)221 static int32_t SetIv(MODES_CipherCCMCtx *ctx, const void *val, uint32_t len)
222 {
223     if (val == NULL) {
224         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
225         return CRYPT_NULL_INPUT;
226     }
227     /**
228      * RFC_3610-2
229      * Valid values of L range between 2 octets and 8 octets
230      */
231     // L = 15 - ivLen that is 7 <= ivLen <= 13
232     if (len < 7 || len > 13) {
233         BSL_ERR_PUSH_ERROR(CRYPT_MODES_IVLEN_ERROR);
234         return CRYPT_MODES_IVLEN_ERROR;
235     }
236     // The previous judgment limits the size of iv to [7, 13]. Therefore, forcible conversion does not cause truncation.
237     uint8_t l = CCM_BLOCKSIZE - 1 - (uint8_t)len;
238 
239     // Clear data.
240     void *ciphCtx = ctx->ciphCtx; // Handle used by the method
241     const EAL_SymMethod *ciphMeth = ctx->ciphMeth; // algorithm method
242     uint8_t tagLen = ctx->tagLen;
243     (void)memset_s(ctx, sizeof(MODES_CipherCCMCtx), 0, sizeof(MODES_CipherCCMCtx));
244     ctx->ciphCtx = ciphCtx;
245     ctx->ciphMeth = ciphMeth;
246     ctx->tagLen = tagLen;
247 
248     uint8_t m = (ctx->tagLen - 2) / 2; // M' = (M - 2)/2
249     ctx->nonce[0] = (uint8_t)((l - 1) & 0x7); // set L
250     ctx->nonce[0] |= (m << 3); // set M. The default value of TagLen is 16bytes. (bit2 bit3 bit4) indicating the tagLen
251     (void)memcpy_s(ctx->nonce + 1, CCM_BLOCKSIZE - 1, val, len);
252 
253     return CRYPT_SUCCESS;
254 }
255 
256 // The input data is the uint64_t.
SetMsgLen(MODES_CipherCCMCtx * ctx,const void * val,uint32_t len)257 static int32_t SetMsgLen(MODES_CipherCCMCtx *ctx, const void *val, uint32_t len)
258 {
259     if (val == NULL) {
260         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
261         return CRYPT_NULL_INPUT;
262     }
263     if (len != sizeof(uint64_t)) {
264         BSL_ERR_PUSH_ERROR(CRYPT_MODES_CTRL_MSGLEN_ERROR);
265         return CRYPT_MODES_CTRL_MSGLEN_ERROR;
266     }
267     if ((ctx->nonce[0] & 0x40) != 0) {
268         // If aad has been set, msgLen cannot be set.
269         BSL_ERR_PUSH_ERROR(CRYPT_MODES_AAD_IS_SET_ERROR);
270         return CRYPT_MODES_AAD_IS_SET_ERROR;
271     }
272     const uint64_t msgLen = *(const uint64_t *)val;
273     uint8_t l = (ctx->nonce[0] & 0x7) + 1;
274     /**
275      * RFC_3610-7
276      * octet aligned message of arbitrary length, up to 2^(8*L) octets,
277      * and octet aligned arbitrary additional authenticated data, up to
278      * 2^64 octets
279      */
280     if (l < 8 && msgLen >= ((uint64_t)1 << (8 * l))) { // When l is 8, the condition must be met.
281         BSL_ERR_PUSH_ERROR(CRYPT_MODES_CTRL_MSGLEN_ERROR);
282         return CRYPT_MODES_CTRL_MSGLEN_ERROR;
283     }
284     uint8_t i;
285     /**
286      * RFC_3610-2.3
287      * Octet Number   Contents
288      * ------------   ---------
289      * 0              Flags
290      * 1 ... 15-L     Nonce N
291      * 16-L ... 15    Counter i
292      */
293     uint8_t bytes[sizeof(uint64_t)];
294     Uint64ToBeBytes(msgLen, bytes);
295     for (i = 0; i < l; i++) {
296         ctx->nonce[CCM_BLOCKSIZE - 1 - i] = bytes[8 - 1 - i]; // 8 bit msgLen information
297     }
298     ctx->msgLen = msgLen;
299     return CRYPT_SUCCESS;
300 }
301 
SetTagLen(MODES_CipherCCMCtx * ctx,const void * val,uint32_t len)302 static int32_t SetTagLen(MODES_CipherCCMCtx *ctx, const void *val, uint32_t len)
303 {
304     if (val == NULL) {
305         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
306         return CRYPT_NULL_INPUT;
307     }
308     if (len != sizeof(uint32_t)) {
309         BSL_ERR_PUSH_ERROR(CRYPT_MODES_CTRL_TAGLEN_ERROR);
310         return CRYPT_MODES_CTRL_TAGLEN_ERROR;
311     }
312     if ((ctx->nonce[0] & 0x40) != 0) {
313         // If aad has been set, tagLen cannot be set.
314         BSL_ERR_PUSH_ERROR(CRYPT_MODES_AAD_IS_SET_ERROR);
315         return CRYPT_MODES_AAD_IS_SET_ERROR;
316     }
317     /**
318      * RFC_3610-2
319      * Valid values are 4, 6, 8, 10, 12, 14, and 16 octets
320      */
321     uint32_t tagLen = *((const uint32_t *)val);
322     // 4 <= tagLen <= 16 and tagLen is an even number.
323     if (tagLen > 16 || tagLen < 4 || ((tagLen & 0x01) != 0)) {
324         BSL_ERR_PUSH_ERROR(CRYPT_MODES_CTRL_TAGLEN_ERROR);
325         return CRYPT_MODES_CTRL_TAGLEN_ERROR;
326     }
327     ctx->tagLen = (uint8_t)tagLen;
328     uint8_t m = (ctx->tagLen - 2) / 2; // M' = (M - 2)/2
329     ctx->nonce[0] &= ~(0x7 << 3); // Clear 3|4|5 three bits
330     ctx->nonce[0] |= (m << 3); // Set M
331     return CRYPT_SUCCESS;
332 }
333 
XorAadLen(MODES_CipherCCMCtx * ctx,uint32_t aadLen)334 static uint32_t XorAadLen(MODES_CipherCCMCtx *ctx, uint32_t aadLen)
335 {
336     /**
337      * RFC_3610-2.2
338      * First two octets   Followed by       Comment
339      * -----------------  ----------------  -------------------------------
340      * 0x0000             Nothing           Reserved
341      * 0x0001 ... 0xFEFF  Nothing           For 0 < l(a) < (2^16 - 2^8)
342      * 0xFF00 ... 0xFFFD  Nothing           Reserved
343      * 0xFFFE             4 octets of l(a)  For (2^16 - 2^8) <= l(a) < 2^32
344      * 0xFFFF             8 octets of l(a)  For 2^32 <= l(a) < 2^64
345      */
346     uint32_t record; /* In order to record aadlen */
347     // For 0 < l(a) < (2^16 - 2^8)
348     if (aadLen < (((size_t)1 << 16) - ((size_t)1 << 8))) {
349         /* 0 < l(a) < (2^16 - 2^8) */
350         record = 2;          /* 2 octets */
351         ctx->tag[1] ^= (uint8_t)aadLen;
352         ctx->tag[0] ^= (uint8_t)(aadLen >> 8); // 1byte = 8bit
353     } else {
354         /* (2^16 - 2^8) <= l(a) < 2^32 */
355         record = 6;          /* 6 octets */
356         ctx->tag[5] ^= (uint8_t)aadLen;  // base offset = 5
357         ctx->tag[4] ^= (uint8_t)(aadLen >> 8); // 1byte(off 5 -> 4) == 8bit
358         ctx->tag[3] ^= (uint8_t)(aadLen >> 16); // 2byte(off 5 -> 3) == 16bit
359         ctx->tag[2] ^= (uint8_t)(aadLen >> 24); // 3byte(off 5 -> 2) == 24bit
360         ctx->tag[1] ^= 0xfe;
361         ctx->tag[0] ^= 0xff;
362     }
363     return record;
364 }
365 
366 // 0 < aadLen < 2^32
SetAad(MODES_CipherCCMCtx * ctx,const void * val,uint32_t len)367 static int32_t SetAad(MODES_CipherCCMCtx *ctx, const void *val, uint32_t len)
368 {
369     if ((ctx->nonce[0] & 0x40) != 0 || ctx->tagInit != 0) {
370         // If aad has been set, the setting cannot be repeated.
371         BSL_ERR_PUSH_ERROR(CRYPT_MODES_AAD_REPEAT_SET_ERROR);
372         return CRYPT_MODES_AAD_REPEAT_SET_ERROR;
373     }
374     if (len == 0) { // If AAD is 0, returned directly.
375         return CRYPT_SUCCESS;
376     }
377     if (val == NULL) {
378         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
379         return CRYPT_NULL_INPUT;
380     }
381     // bit6 Adata
382     ctx->nonce[0] |= 0x40;
383     // X_1 := E( K, B_0 )
384     int32_t ret = ctx->ciphMeth->encryptBlock(ctx->ciphCtx, ctx->nonce, ctx->tag, CCM_BLOCKSIZE);
385     if (ret != CRYPT_SUCCESS) {
386         BSL_ERR_PUSH_ERROR(ret);
387         return ret;
388     }
389     ctx->tagInit = 1;
390 
391     uint32_t i;
392     uint32_t aadLen = len;
393     uint32_t record = XorAadLen(ctx, aadLen);
394     const uint8_t *aad = val;
395     uint32_t use = CCM_BLOCKSIZE - record;
396     use = (use < aadLen) ? use : aadLen;
397     for (i = 0; i < use; i++) {
398         ctx->tag[i + record] ^= aad[i];
399     }
400     aad += use;
401     aadLen -= use;
402     ret = ctx->ciphMeth->encryptBlock(ctx->ciphCtx, ctx->tag, ctx->tag, CCM_BLOCKSIZE);
403     if (ret != CRYPT_SUCCESS) {
404         BSL_ERR_PUSH_ERROR(ret);
405         return ret;
406     }
407 
408     while (aadLen > 0) {
409         uint32_t blockLen = (aadLen < CCM_BLOCKSIZE) ? aadLen : CCM_BLOCKSIZE;
410         for (i = 0; i < blockLen; i++) {
411             ctx->tag[i] ^= aad[i];
412         }
413         aad += blockLen;
414         aadLen -= blockLen;
415         ret = ctx->ciphMeth->encryptBlock(ctx->ciphCtx, ctx->tag, ctx->tag, CCM_BLOCKSIZE);
416         if (ret != CRYPT_SUCCESS) {
417             BSL_ERR_PUSH_ERROR(ret);
418             return ret;
419         }
420     }
421     return CRYPT_SUCCESS;
422 }
423 
CtrTagCalc(MODES_CipherCCMCtx * ctx)424 static int32_t CtrTagCalc(MODES_CipherCCMCtx *ctx)
425 {
426     /**
427      * RFC_3610-2.3
428      * The authentication value U is computed by encrypting T with the ciphCtx
429      * stream block S_0 and truncating it to the desired length.
430      */
431     ctx->nonce[0] &= 0x07; // update the nonce
432     uint8_t l = (ctx->nonce[0] & 0x07) + 1;
433     (void)memset_s(ctx->nonce + CCM_BLOCKSIZE - l, l, 0, l);
434     int32_t ret = ctx->ciphMeth->encryptBlock(ctx->ciphCtx, ctx->nonce, ctx->nonce, CCM_BLOCKSIZE);
435     if (ret != CRYPT_SUCCESS) {
436         BSL_ERR_PUSH_ERROR(ret);
437     }
438     return ret;
439 }
440 
GetTag(MODES_CipherCCMCtx * ctx,void * val,uint32_t len)441 static int32_t GetTag(MODES_CipherCCMCtx *ctx, void *val, uint32_t len)
442 {
443     if (val == NULL) {
444         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
445         return CRYPT_NULL_INPUT;
446     }
447     if (len != ctx->tagLen) {
448         BSL_ERR_PUSH_ERROR(CRYPT_MODES_TAGLEN_ERROR);
449         return CRYPT_MODES_TAGLEN_ERROR;
450     }
451     if (ctx->msgLen != 0) {
452         BSL_ERR_PUSH_ERROR(CRYPT_MODES_MSGLEN_LEFT_ERROR);
453         return CRYPT_MODES_MSGLEN_LEFT_ERROR;
454     }
455     int32_t ret = TagInit(ctx);
456     if (ret != CRYPT_SUCCESS) {
457         BSL_ERR_PUSH_ERROR(ret);
458         return ret;
459     }
460     ret = CtrTagCalc(ctx);
461     if (ret != CRYPT_SUCCESS) {
462         // An error is reported by the internal function, and no redundant pushErr is required.
463         return ret;
464     }
465     if (ctx->lastLen != 0) {
466         ret = ctx->ciphMeth->encryptBlock(ctx->ciphCtx, ctx->tag, ctx->tag, CCM_BLOCKSIZE);
467         if (ret != CRYPT_SUCCESS) {
468             BSL_ERR_PUSH_ERROR(ret);
469             return ret;
470         }
471     }
472     uint32_t i;
473     uint8_t *tag = val;
474     /**
475      * RFC_3610-2.3
476      * U := T XOR first-M-bytes( S_0 )
477      */
478     for (i = 0; i < len; i++) {
479         tag[i] = ctx->tag[i] ^ ctx->nonce[i];
480     }
481     return CRYPT_SUCCESS;
482 }
483 
MODES_CCM_Ctrl(MODES_CCM_Ctx * modeCtx,int32_t opt,void * val,uint32_t len)484 int32_t MODES_CCM_Ctrl(MODES_CCM_Ctx *modeCtx, int32_t opt, void *val, uint32_t len)
485 {
486     if (modeCtx == NULL) {
487         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
488         return CRYPT_NULL_INPUT;
489     }
490     switch (opt) {
491         case CRYPT_CTRL_SET_IV:
492         case CRYPT_CTRL_REINIT_STATUS:
493             return SetIv(&modeCtx->ccmCtx, val, len);
494         case CRYPT_CTRL_GET_BLOCKSIZE:
495             if (val == NULL || len != sizeof(uint32_t)) {
496                 BSL_ERR_PUSH_ERROR(CRYPT_MODE_ERR_INPUT_LEN);
497                 return CRYPT_MODE_ERR_INPUT_LEN;
498             }
499             *(int32_t *)val = 1;
500             return CRYPT_SUCCESS;
501         case CRYPT_CTRL_SET_TAGLEN:
502             return SetTagLen(&modeCtx->ccmCtx, val, len);
503         case CRYPT_CTRL_SET_MSGLEN:
504             return SetMsgLen(&modeCtx->ccmCtx, val, len);
505         case CRYPT_CTRL_SET_AAD:
506             return SetAad(&modeCtx->ccmCtx, val, len);
507         case CRYPT_CTRL_GET_TAG:
508             return GetTag(&modeCtx->ccmCtx, val, len);
509         default:
510             BSL_ERR_PUSH_ERROR(CRYPT_MODES_CTRL_TYPE_ERROR);
511             return CRYPT_MODES_CTRL_TYPE_ERROR;
512     }
513 }
514 
MODES_CCM_NewCtx(int32_t algId)515 MODES_CCM_Ctx *MODES_CCM_NewCtx(int32_t algId)
516 {
517     const EAL_SymMethod *method = EAL_GetSymMethod(algId);
518     if (method == NULL) {
519         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
520         return NULL;
521     }
522     MODES_CCM_Ctx *ctx = BSL_SAL_Calloc(1, sizeof(MODES_CCM_Ctx));
523     if (ctx == NULL) {
524         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
525         return ctx;
526     }
527     ctx->algId = algId;
528     ctx->ccmCtx.ciphCtx = BSL_SAL_Calloc(1, method->ctxSize);
529     if (ctx->ccmCtx.ciphCtx  == NULL) {
530         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
531         BSL_SAL_Free(ctx);
532         return NULL;
533     }
534 
535     ctx->ccmCtx.ciphMeth = method;
536     return ctx;
537 }
538 
MODES_CCM_InitCtx(MODES_CCM_Ctx * modeCtx,const uint8_t * key,uint32_t keyLen,const uint8_t * iv,uint32_t ivLen,void * param,bool enc)539 int32_t MODES_CCM_InitCtx(MODES_CCM_Ctx *modeCtx, const uint8_t *key, uint32_t keyLen, const uint8_t *iv,
540     uint32_t ivLen, void *param, bool enc)
541 {
542     (void)param;
543     if (modeCtx == NULL) {
544         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
545         return CRYPT_NULL_INPUT;
546     }
547 
548     int32_t ret = modeCtx->ccmCtx.ciphMeth->setEncryptKey(modeCtx->ccmCtx.ciphCtx, key, keyLen);
549     if (ret != CRYPT_SUCCESS) {
550         BSL_ERR_PUSH_ERROR(ret);
551         return ret;
552     }
553     modeCtx->ccmCtx.tagLen = 16; // 16 default tag len, set iv need
554     ret = SetIv(&modeCtx->ccmCtx, iv, ivLen);
555     if (ret != CRYPT_SUCCESS) {
556         modeCtx->ccmCtx.ciphMeth->cipherDeInitCtx(modeCtx->ccmCtx.ciphCtx);
557         BSL_ERR_PUSH_ERROR(ret);
558         return ret;
559     }
560     modeCtx->enc = enc;
561     return ret;
562 }
563 
MODES_CCM_Update(MODES_CCM_Ctx * modeCtx,const uint8_t * in,uint32_t inLen,uint8_t * out,uint32_t * outLen)564 int32_t MODES_CCM_Update(MODES_CCM_Ctx *modeCtx, const uint8_t *in, uint32_t inLen, uint8_t *out, uint32_t *outLen)
565 {
566     return MODES_CipherStreamProcess(modeCtx->enc ? MODES_CCM_Encrypt : MODES_CCM_Decrypt, &modeCtx->ccmCtx,
567         in, inLen, out, outLen);
568 }
569 
MODES_CCM_Final(MODES_CCM_Ctx * modeCtx,uint8_t * out,uint32_t * outLen)570 int32_t MODES_CCM_Final(MODES_CCM_Ctx *modeCtx, uint8_t *out, uint32_t *outLen)
571 {
572     (void) modeCtx;
573     (void) out;
574     (void) outLen;
575     return CRYPT_EAL_CIPHER_FINAL_WITH_AEAD_ERROR;
576 }
577 
MODES_CCM_DeInitCtx(MODES_CCM_Ctx * modeCtx)578 int32_t MODES_CCM_DeInitCtx(MODES_CCM_Ctx *modeCtx)
579 {
580     if (modeCtx == NULL) {
581         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
582         return CRYPT_NULL_INPUT;
583     }
584     const EAL_SymMethod *ciphMeth = modeCtx->ccmCtx.ciphMeth;
585     void *ciphCtx = modeCtx->ccmCtx.ciphCtx;
586     modeCtx->ccmCtx.ciphMeth->cipherDeInitCtx(modeCtx->ccmCtx.ciphCtx);
587     BSL_SAL_CleanseData(&modeCtx->ccmCtx, sizeof(MODES_CipherCCMCtx));
588     modeCtx->ccmCtx.ciphMeth = ciphMeth;
589     modeCtx->ccmCtx.ciphCtx = ciphCtx;
590     return CRYPT_SUCCESS;
591 }
592 
MODES_CCM_FreeCtx(MODES_CCM_Ctx * modeCtx)593 void MODES_CCM_FreeCtx(MODES_CCM_Ctx *modeCtx)
594 {
595     if (modeCtx == NULL) {
596         return;
597     }
598     modeCtx->ccmCtx.ciphMeth->cipherDeInitCtx(modeCtx->ccmCtx.ciphCtx);
599     BSL_SAL_FREE(modeCtx->ccmCtx.ciphCtx);
600     BSL_SAL_CleanseData(&modeCtx->ccmCtx, sizeof(MODES_CipherCCMCtx));
601     BSL_SAL_FREE(modeCtx);
602 }
603 
604 
MODES_CCM_UpdateEx(MODES_CCM_Ctx * modeCtx,const uint8_t * in,uint32_t inLen,uint8_t * out,uint32_t * outLen)605 int32_t MODES_CCM_UpdateEx(MODES_CCM_Ctx *modeCtx, const uint8_t *in, uint32_t inLen, uint8_t *out, uint32_t *outLen)
606 {
607     if (modeCtx == NULL) {
608         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
609         return CRYPT_NULL_INPUT;
610     }
611     switch (modeCtx->algId) {
612         case CRYPT_CIPHER_AES128_CCM:
613         case CRYPT_CIPHER_AES192_CCM:
614         case CRYPT_CIPHER_AES256_CCM:
615 #ifdef HITLS_CRYPTO_AES
616             return AES_CCM_Update(modeCtx, in, inLen, out, outLen);
617 #else
618             return CRYPT_EAL_ALG_NOT_SUPPORT;
619 #endif
620         default:
621             return MODES_CCM_Update(modeCtx, in, inLen, out, outLen);
622     }
623 }
624 
625 #endif