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)14int 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