1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3  *
4  * LibTomCrypt is a library that provides various cryptographic
5  * algorithms in a highly modular and flexible manner.
6  *
7  * The library is free for all purposes without any express
8  * guarantee it works.
9  */
10 #include "tomcrypt_private.h"
11 
12 #ifdef LTC_CCM_MODE
13 
14 /**
15   Add nonce data to the CCM state
16   @param ccm       The CCM state
17   @param nonce     The nonce data to add
18   @param noncelen  The length of the nonce
19   @return CRYPT_OK on success
20  */
ccm_add_nonce(ccm_state * ccm,const unsigned char * nonce,unsigned long noncelen)21 int ccm_add_nonce(ccm_state *ccm,
22                   const unsigned char *nonce,     unsigned long noncelen)
23 {
24    unsigned long x, y, len;
25    int           err;
26 
27    LTC_ARGCHK(ccm   != NULL);
28    LTC_ARGCHK(nonce != NULL);
29 
30    /* increase L to match the nonce len */
31    ccm->noncelen = (noncelen > 13) ? 13 : noncelen;
32    if ((15 - ccm->noncelen) > ccm->L) {
33       ccm->L = 15 - ccm->noncelen;
34    }
35 
36    /* decrease noncelen to match L */
37    if ((ccm->noncelen + ccm->L) > 15) {
38       ccm->noncelen = 15 - ccm->L;
39    }
40 
41    /* form B_0 == flags | Nonce N | l(m) */
42    x = 0;
43    ccm->PAD[x++] = (unsigned char)(((ccm->aadlen > 0) ? (1<<6) : 0) |
44                    (((ccm->taglen - 2)>>1)<<3)        |
45                    (ccm->L-1));
46 
47    /* nonce */
48    for (y = 0; y < (16 - (ccm->L + 1)); y++) {
49       ccm->PAD[x++] = nonce[y];
50    }
51 
52    /* store len */
53    len = ccm->ptlen;
54 
55    /* shift len so the upper bytes of len are the contents of the length */
56    for (y = ccm->L; y < 4; y++) {
57       len <<= 8;
58    }
59 
60    /* store l(m) (only store 32-bits) */
61    for (y = 0; ccm->L > 4 && (ccm->L-y)>4; y++) {
62       ccm->PAD[x++] = 0;
63    }
64    for (; y < ccm->L; y++) {
65       ccm->PAD[x++] = (unsigned char)((len >> 24) & 255);
66       len <<= 8;
67    }
68 
69    /* encrypt PAD */
70    if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) {
71       return err;
72    }
73 
74    /* handle header */
75    ccm->x = 0;
76    if (ccm->aadlen > 0) {
77       /* store length */
78       if (ccm->aadlen < ((1UL<<16) - (1UL<<8))) {
79          ccm->PAD[ccm->x++] ^= (ccm->aadlen>>8) & 255;
80          ccm->PAD[ccm->x++] ^= ccm->aadlen & 255;
81       } else {
82          ccm->PAD[ccm->x++] ^= 0xFF;
83          ccm->PAD[ccm->x++] ^= 0xFE;
84          ccm->PAD[ccm->x++] ^= (ccm->aadlen>>24) & 255;
85          ccm->PAD[ccm->x++] ^= (ccm->aadlen>>16) & 255;
86          ccm->PAD[ccm->x++] ^= (ccm->aadlen>>8) & 255;
87          ccm->PAD[ccm->x++] ^= ccm->aadlen & 255;
88       }
89    }
90 
91    /* setup the ctr counter */
92    x = 0;
93 
94    /* flags */
95    ccm->ctr[x++] = (unsigned char)ccm->L-1;
96 
97    /* nonce */
98    for (y = 0; y < (16 - (ccm->L+1)); ++y) {
99       ccm->ctr[x++] = nonce[y];
100    }
101    /* offset */
102    while (x < 16) {
103       ccm->ctr[x++] = 0;
104    }
105 
106    ccm->CTRlen = 16;
107    return CRYPT_OK;
108 }
109 
110 #endif
111 
112 /* ref:         $Format:%D$ */
113 /* git commit:  $Format:%H$ */
114 /* commit time: $Format:%ai$ */
115