1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 #ifdef LTC_CCM_MODE
6 
7 /**
8   Process plaintext/ciphertext through CCM
9   @param ccm       The CCM state
10   @param pt        The plaintext
11   @param ptlen     The plaintext length (ciphertext length is the same)
12   @param ct        The ciphertext
13   @param direction Encrypt or Decrypt mode (CCM_ENCRYPT or CCM_DECRYPT)
14   @return CRYPT_OK on success
15  */
ccm_process(ccm_state * ccm,unsigned char * pt,unsigned long ptlen,unsigned char * ct,int direction)16 int ccm_process(ccm_state *ccm,
17                 unsigned char *pt,     unsigned long ptlen,
18                 unsigned char *ct,
19                 int direction)
20 {
21    unsigned char z, b;
22    unsigned long y;
23    int err;
24 
25    LTC_ARGCHK(ccm != NULL);
26 
27    /* Check aad has been correctly added */
28    if (ccm->aadlen != ccm->current_aadlen) {
29       return CRYPT_ERROR;
30    }
31 
32    /* Check we do not process too much data */
33    if (ccm->ptlen < ccm->current_ptlen + ptlen) {
34       return CRYPT_ERROR;
35    }
36    ccm->current_ptlen += ptlen;
37 
38    /* now handle the PT */
39    if (ptlen > 0) {
40       LTC_ARGCHK(pt != NULL);
41       LTC_ARGCHK(ct != NULL);
42 
43       for (y = 0; y < ptlen; y++) {
44          /* increment the ctr? */
45          if (ccm->CTRlen == 16) {
46             for (z = 15; z > 15-ccm->L; z--) {
47                ccm->ctr[z] = (ccm->ctr[z] + 1) & 255;
48                if (ccm->ctr[z]) break;
49             }
50             if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->ctr, ccm->CTRPAD, &ccm->K)) != CRYPT_OK) {
51                return err;
52             }
53             ccm->CTRlen = 0;
54          }
55 
56          /* if we encrypt we add the bytes to the MAC first */
57          if (direction == CCM_ENCRYPT) {
58             b     = pt[y];
59             ct[y] = b ^ ccm->CTRPAD[ccm->CTRlen++];
60          } else {
61             b     = ct[y] ^ ccm->CTRPAD[ccm->CTRlen++];
62             pt[y] = b;
63          }
64 
65          if (ccm->x == 16) {
66             if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) {
67                return err;
68             }
69             ccm->x = 0;
70          }
71          ccm->PAD[ccm->x++] ^= b;
72       }
73    }
74 
75    return CRYPT_OK;
76 }
77 
78 #endif
79