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   Add nonce data to the CCM state
9   @param ccm       The CCM state
10   @param nonce     The nonce data to add
11   @param noncelen  The length of the nonce
12   @return CRYPT_OK on success
13  */
ccm_add_nonce(ccm_state * ccm,const unsigned char * nonce,unsigned long noncelen)14 int ccm_add_nonce(ccm_state *ccm,
15                   const unsigned char *nonce,     unsigned long noncelen)
16 {
17    unsigned long x, y, len;
18    int           err;
19 
20    LTC_ARGCHK(ccm   != NULL);
21    LTC_ARGCHK(nonce != NULL);
22 
23    /* increase L to match the nonce len */
24    ccm->noncelen = (noncelen > 13) ? 13 : noncelen;
25    if ((15 - ccm->noncelen) > ccm->L) {
26       ccm->L = 15 - ccm->noncelen;
27    }
28    if (ccm->L > 8) {
29       return CRYPT_INVALID_ARG;
30    }
31 
32    /* decrease noncelen to match L */
33    if ((ccm->noncelen + ccm->L) > 15) {
34       ccm->noncelen = 15 - ccm->L;
35    }
36 
37    /* form B_0 == flags | Nonce N | l(m) */
38    x = 0;
39    ccm->PAD[x++] = (unsigned char)(((ccm->aadlen > 0) ? (1<<6) : 0) |
40                    (((ccm->taglen - 2)>>1)<<3)        |
41                    (ccm->L-1));
42 
43    /* nonce */
44    for (y = 0; y < 15 - ccm->L; y++) {
45       ccm->PAD[x++] = nonce[y];
46    }
47 
48    /* store len */
49    len = ccm->ptlen;
50 
51    /* shift len so the upper bytes of len are the contents of the length */
52    for (y = ccm->L; y < 4; y++) {
53       len <<= 8;
54    }
55 
56    /* store l(m) (only store 32-bits) */
57    for (y = 0; ccm->L > 4 && (ccm->L-y)>4; y++) {
58       ccm->PAD[x++] = 0;
59    }
60    for (; y < ccm->L; y++) {
61       ccm->PAD[x++] = (unsigned char)((len >> 24) & 255);
62       len <<= 8;
63    }
64 
65    /* encrypt PAD */
66    if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) {
67       return err;
68    }
69 
70    /* handle header */
71    ccm->x = 0;
72    if (ccm->aadlen > 0) {
73       /* store length */
74       if (ccm->aadlen < ((1UL<<16) - (1UL<<8))) {
75          ccm->PAD[ccm->x++] ^= (ccm->aadlen>>8) & 255;
76          ccm->PAD[ccm->x++] ^= ccm->aadlen & 255;
77       } else {
78          ccm->PAD[ccm->x++] ^= 0xFF;
79          ccm->PAD[ccm->x++] ^= 0xFE;
80          ccm->PAD[ccm->x++] ^= (ccm->aadlen>>24) & 255;
81          ccm->PAD[ccm->x++] ^= (ccm->aadlen>>16) & 255;
82          ccm->PAD[ccm->x++] ^= (ccm->aadlen>>8) & 255;
83          ccm->PAD[ccm->x++] ^= ccm->aadlen & 255;
84       }
85    }
86 
87    /* setup the ctr counter */
88    x = 0;
89 
90    /* flags */
91    ccm->ctr[x++] = (unsigned char)ccm->L-1;
92 
93    /* nonce */
94    for (y = 0; y < (16 - (ccm->L+1)); ++y) {
95       ccm->ctr[x++] = nonce[y];
96    }
97    /* offset */
98    while (x < 16) {
99       ccm->ctr[x++] = 0;
100    }
101 
102    ccm->CTRlen = 16;
103    return CRYPT_OK;
104 }
105 
106 #endif
107