1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright(c) 2007-2022 Intel Corporation */ 3 4 /** 5 *************************************************************************** 6 * @file lac_sym_auth_enc.c 7 * 8 * @ingroup LacAuthEnc 9 * 10 * @description 11 * Authenticated encryption specific functionality. 12 * For CCM related code NIST SP 800-38C is followed. 13 * For GCM related code NIST SP 800-38D is followed. 14 ***************************************************************************/ 15 16 /* 17 ******************************************************************************* 18 * Include public/global header files 19 ******************************************************************************* 20 */ 21 22 #include "cpa.h" 23 #include "cpa_cy_sym.h" 24 25 #include "icp_accel_devices.h" 26 #include "icp_adf_init.h" 27 #include "icp_adf_transport.h" 28 #include "icp_adf_debug.h" 29 /* 30 ******************************************************************************* 31 * Include private header files 32 ******************************************************************************* 33 */ 34 #include "lac_log.h" 35 #include "lac_common.h" 36 #include "lac_session.h" 37 #include "lac_sym_auth_enc.h" 38 39 /* These defines describe position of the flag fields 40 * in B0 block for CCM algorithm*/ 41 #define LAC_ALG_CHAIN_CCM_B0_FLAGS_ADATA_SHIFT 6 42 #define LAC_ALG_CHAIN_CCM_B0_FLAGS_T_SHIFT 3 43 44 /* This macro builds flags field to be put in B0 block for CCM algorithm */ 45 #define LAC_ALG_CHAIN_CCM_BUILD_B0_FLAGS(Adata, t, q) \ 46 ((((Adata) > 0 ? 1 : 0) << LAC_ALG_CHAIN_CCM_B0_FLAGS_ADATA_SHIFT) | \ 47 ((((t)-2) >> 1) << LAC_ALG_CHAIN_CCM_B0_FLAGS_T_SHIFT) | ((q)-1)) 48 49 /** 50 * @ingroup LacAuthEnc 51 */ 52 CpaStatus 53 LacSymAlgChain_CheckCCMData(Cpa8U *pAdditionalAuthData, 54 Cpa8U *pIv, 55 Cpa32U messageLenToCipherInBytes, 56 Cpa32U ivLenInBytes) 57 { 58 Cpa8U q = 0; 59 60 LAC_CHECK_NULL_PARAM(pIv); 61 LAC_CHECK_NULL_PARAM(pAdditionalAuthData); 62 63 /* check if n is within permitted range */ 64 if (ivLenInBytes < LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MIN || 65 ivLenInBytes > LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MAX) { 66 LAC_INVALID_PARAM_LOG2("ivLenInBytes for CCM algorithm " 67 "must be between %d and %d inclusive", 68 LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MIN, 69 LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MAX); 70 return CPA_STATUS_INVALID_PARAM; 71 } 72 73 q = LAC_ALG_CHAIN_CCM_NQ_CONST - ivLenInBytes; 74 75 /* Check if q is big enough to hold actual length of message to cipher 76 * if q = 8 -> maxlen = 2^64 always good as 77 * messageLenToCipherInBytes is 32 bits 78 * if q = 7 -> maxlen = 2^56 always good 79 * if q = 6 -> maxlen = 2^48 always good 80 * if q = 5 -> maxlen = 2^40 always good 81 * if q = 4 -> maxlen = 2^32 always good. 82 */ 83 if ((messageLenToCipherInBytes >= (1 << (q * LAC_NUM_BITS_IN_BYTE))) && 84 (q < sizeof(Cpa32U))) { 85 LAC_INVALID_PARAM_LOG( 86 "messageLenToCipherInBytes too long for the given" 87 " ivLenInBytes for CCM algorithm\n"); 88 return CPA_STATUS_INVALID_PARAM; 89 } 90 91 return CPA_STATUS_SUCCESS; 92 } 93 94 95 /** 96 * @ingroup LacAuthEnc 97 */ 98 void 99 LacSymAlgChain_PrepareCCMData(lac_session_desc_t *pSessionDesc, 100 Cpa8U *pAdditionalAuthData, 101 Cpa8U *pIv, 102 Cpa32U messageLenToCipherInBytes, 103 Cpa32U ivLenInBytes) 104 { 105 Cpa8U n = 106 ivLenInBytes; /* assumes ivLenInBytes has been param checked */ 107 Cpa8U q = LAC_ALG_CHAIN_CCM_NQ_CONST - n; 108 Cpa8U lenOfEncodedLen = 0; 109 Cpa16U lenAEncoded = 0; 110 Cpa32U bitStrQ = 0; 111 112 /* populate Ctr0 block - stored in pIv */ 113 pIv[0] = (q - 1); 114 /* bytes 1 to n are already set with nonce by the user */ 115 /* set last q bytes with 0 */ 116 memset(pIv + n + 1, 0, q); 117 118 /* Encode the length of associated data 'a'. As the API limits the 119 * length 120 * of an array pointed by pAdditionalAuthData to be 240 bytes max, the 121 * maximum length of 'a' might be 240 - 16 - 2 = 222. Hence the encoding 122 * below is simplified. */ 123 if (pSessionDesc->aadLenInBytes > 0) { 124 lenOfEncodedLen = sizeof(Cpa16U); 125 lenAEncoded = QAT_UTILS_HOST_TO_NW_16( 126 (Cpa16U)pSessionDesc->aadLenInBytes); 127 } 128 129 /* populate B0 block */ 130 /* first, set the flags field */ 131 pAdditionalAuthData[0] = 132 LAC_ALG_CHAIN_CCM_BUILD_B0_FLAGS(lenOfEncodedLen, 133 pSessionDesc->hashResultSize, 134 q); 135 /* bytes 1 to n are already set with nonce by the user*/ 136 /* put Q in bytes 16-q...15 */ 137 bitStrQ = QAT_UTILS_HOST_TO_NW_32(messageLenToCipherInBytes); 138 139 if (q > sizeof(bitStrQ)) { 140 memset(pAdditionalAuthData + n + 1, 0, q); 141 memcpy(pAdditionalAuthData + n + 1 + (q - sizeof(bitStrQ)), 142 (Cpa8U *)&bitStrQ, 143 sizeof(bitStrQ)); 144 } else { 145 memcpy(pAdditionalAuthData + n + 1, 146 ((Cpa8U *)&bitStrQ) + (sizeof(bitStrQ) - q), 147 q); 148 } 149 150 /* populate B1-Bn blocks */ 151 if (lenAEncoded > 0) { 152 *(Cpa16U 153 *)(&pAdditionalAuthData[1 + LAC_ALG_CHAIN_CCM_NQ_CONST]) = 154 lenAEncoded; 155 /* Next bytes are already set by the user with 156 * the associated data 'a' */ 157 158 /* Check if padding is required */ 159 if (((pSessionDesc->aadLenInBytes + lenOfEncodedLen) % 160 LAC_HASH_AES_CCM_BLOCK_SIZE) != 0) { 161 Cpa8U paddingLen = 0; 162 Cpa8U paddingIndex = 0; 163 164 paddingLen = LAC_HASH_AES_CCM_BLOCK_SIZE - 165 ((pSessionDesc->aadLenInBytes + lenOfEncodedLen) % 166 LAC_HASH_AES_CCM_BLOCK_SIZE); 167 168 paddingIndex = 1 + LAC_ALG_CHAIN_CCM_NQ_CONST; 169 paddingIndex += 170 lenOfEncodedLen + pSessionDesc->aadLenInBytes; 171 172 memset(&pAdditionalAuthData[paddingIndex], 173 0, 174 paddingLen); 175 } 176 } 177 } 178 179 /** 180 * @ingroup LacAuthEnc 181 */ 182 void 183 LacSymAlgChain_PrepareGCMData(lac_session_desc_t *pSessionDesc, 184 Cpa8U *pAdditionalAuthData) 185 { 186 Cpa8U paddingLen = 0; 187 188 if ((pSessionDesc->aadLenInBytes % LAC_HASH_AES_GCM_BLOCK_SIZE) != 0) { 189 paddingLen = LAC_HASH_AES_GCM_BLOCK_SIZE - 190 (pSessionDesc->aadLenInBytes % LAC_HASH_AES_GCM_BLOCK_SIZE); 191 192 memset(&pAdditionalAuthData[pSessionDesc->aadLenInBytes], 193 0, 194 paddingLen); 195 } 196 } 197