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