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