1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 
4 /**
5  *****************************************************************************
6  * @file lac_sym_qat.c Interfaces for populating the symmetric qat structures
7  *
8  * @ingroup LacSymQat
9  *
10  *****************************************************************************/
11 
12 /*
13 *******************************************************************************
14 * Include public/global header files
15 *******************************************************************************
16 */
17 #include "cpa.h"
18 
19 /*
20 *******************************************************************************
21 * Include private header files
22 *******************************************************************************
23 */
24 #include "icp_accel_devices.h"
25 #include "icp_adf_cfg.h"
26 #include "lac_log.h"
27 #include "lac_sym.h"
28 #include "lac_sym_qat.h"
29 #include "lac_sal_types_crypto.h"
30 #include "sal_string_parse.h"
31 #include "lac_sym_key.h"
32 #include "lac_sym_qat_hash_defs_lookup.h"
33 #include "lac_sym_qat_constants_table.h"
34 #include "lac_sym_qat_cipher.h"
35 #include "lac_sym_qat_hash.h"
36 
37 #define EMBEDDED_CIPHER_KEY_MAX_SIZE 16
38 static void
39 LacSymQat_SymLogSliceHangError(icp_qat_fw_la_cmd_id_t symCmdId)
40 {
41 	Cpa8U cmdId = symCmdId;
42 
43 	switch (cmdId) {
44 	case ICP_QAT_FW_LA_CMD_CIPHER:
45 	case ICP_QAT_FW_LA_CMD_CIPHER_PRE_COMP:
46 		LAC_LOG_ERROR("slice hang detected on CPM cipher slice.");
47 		break;
48 
49 	case ICP_QAT_FW_LA_CMD_AUTH:
50 	case ICP_QAT_FW_LA_CMD_AUTH_PRE_COMP:
51 		LAC_LOG_ERROR("slice hang detected on CPM auth slice.");
52 		break;
53 
54 	case ICP_QAT_FW_LA_CMD_CIPHER_HASH:
55 	case ICP_QAT_FW_LA_CMD_HASH_CIPHER:
56 	case ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE:
57 	case ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE:
58 	case ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE:
59 	case ICP_QAT_FW_LA_CMD_MGF1:
60 	default:
61 		LAC_LOG_ERROR(
62 		    "slice hang detected on CPM cipher or auth slice.");
63 	}
64 	return;
65 }
66 
67 /* sym crypto response handlers */
68 static sal_qat_resp_handler_func_t
69     respHandlerSymTbl[ICP_QAT_FW_LA_CMD_DELIMITER];
70 
71 void
72 LacSymQat_SymRespHandler(void *pRespMsg)
73 {
74 	Cpa8U lacCmdId = 0;
75 	void *pOpaqueData = NULL;
76 	icp_qat_fw_la_resp_t *pRespMsgFn = NULL;
77 	Cpa8U opStatus = ICP_QAT_FW_COMN_STATUS_FLAG_OK;
78 	Cpa8U comnErr = ERR_CODE_NO_ERROR;
79 
80 	pRespMsgFn = (icp_qat_fw_la_resp_t *)pRespMsg;
81 	LAC_MEM_SHARED_READ_TO_PTR(pRespMsgFn->opaque_data, pOpaqueData);
82 
83 	lacCmdId = pRespMsgFn->comn_resp.cmd_id;
84 	opStatus = pRespMsgFn->comn_resp.comn_status;
85 	comnErr = pRespMsgFn->comn_resp.comn_error.s.comn_err_code;
86 
87 	/* log the slice hang and endpoint push/pull error inside the response
88 	 */
89 	if (ERR_CODE_SSM_ERROR == (Cpa8S)comnErr) {
90 		LacSymQat_SymLogSliceHangError(lacCmdId);
91 	} else if (ERR_CODE_ENDPOINT_ERROR == (Cpa8S)comnErr) {
92 		LAC_LOG_ERROR("The PCIe End Point Push/Pull or"
93 			      " TI/RI Parity error detected.");
94 	}
95 
96 	/* call the response message handler registered for the command ID */
97 	respHandlerSymTbl[lacCmdId]((icp_qat_fw_la_cmd_id_t)lacCmdId,
98 				    pOpaqueData,
99 				    (icp_qat_fw_comn_flags)opStatus);
100 }
101 
102 CpaStatus
103 LacSymQat_Init(CpaInstanceHandle instanceHandle)
104 {
105 	CpaStatus status = CPA_STATUS_SUCCESS;
106 
107 	/* Initialize the SHRAM constants table */
108 	LacSymQat_ConstantsInitLookupTables(instanceHandle);
109 
110 	/* Initialise the Hash lookup table */
111 	status = LacSymQat_HashLookupInit(instanceHandle);
112 
113 	return status;
114 }
115 
116 void
117 LacSymQat_RespHandlerRegister(icp_qat_fw_la_cmd_id_t lacCmdId,
118 			      sal_qat_resp_handler_func_t pCbHandler)
119 {
120 	if (lacCmdId >= ICP_QAT_FW_LA_CMD_DELIMITER) {
121 		QAT_UTILS_LOG("Invalid Command ID\n");
122 		return;
123 	}
124 
125 	/* set the response handler for the command ID */
126 	respHandlerSymTbl[lacCmdId] = pCbHandler;
127 }
128 
129 void
130 LacSymQat_LaPacketCommandFlagSet(Cpa32U qatPacketType,
131 				 icp_qat_fw_la_cmd_id_t laCmdId,
132 				 CpaCySymCipherAlgorithm cipherAlgorithm,
133 				 Cpa16U *pLaCommandFlags,
134 				 Cpa32U ivLenInBytes)
135 {
136 	/* For SM4/Chacha ciphers set command flag as partial none to proceed
137 	 * with stateless processing */
138 	if (LAC_CIPHER_IS_SM4(cipherAlgorithm) ||
139 	    LAC_CIPHER_IS_CHACHA(cipherAlgorithm)) {
140 		ICP_QAT_FW_LA_PARTIAL_SET(*pLaCommandFlags,
141 					  ICP_QAT_FW_LA_PARTIAL_NONE);
142 		return;
143 	}
144 	ICP_QAT_FW_LA_PARTIAL_SET(*pLaCommandFlags, qatPacketType);
145 
146 	/* For ECB-mode ciphers, IV is NULL so update-state flag
147 	 * must be disabled always.
148 	 * For all other ciphers and auth
149 	 * update state is disabled for full packets and final partials */
150 	if ((ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) ||
151 	    (ICP_QAT_FW_LA_PARTIAL_END == qatPacketType) ||
152 	    ((laCmdId != ICP_QAT_FW_LA_CMD_AUTH) &&
153 	     LAC_CIPHER_IS_ECB_MODE(cipherAlgorithm))) {
154 		ICP_QAT_FW_LA_UPDATE_STATE_SET(*pLaCommandFlags,
155 					       ICP_QAT_FW_LA_NO_UPDATE_STATE);
156 	}
157 	/* For first or middle partials set the update state command flag */
158 	else {
159 		ICP_QAT_FW_LA_UPDATE_STATE_SET(*pLaCommandFlags,
160 					       ICP_QAT_FW_LA_UPDATE_STATE);
161 
162 		if (laCmdId == ICP_QAT_FW_LA_CMD_AUTH) {
163 			/* For hash only partial - verify and return auth result
164 			 * are
165 			 * disabled */
166 			ICP_QAT_FW_LA_RET_AUTH_SET(
167 			    *pLaCommandFlags, ICP_QAT_FW_LA_NO_RET_AUTH_RES);
168 
169 			ICP_QAT_FW_LA_CMP_AUTH_SET(
170 			    *pLaCommandFlags, ICP_QAT_FW_LA_NO_CMP_AUTH_RES);
171 		}
172 	}
173 
174 	if ((LAC_CIPHER_IS_GCM(cipherAlgorithm)) &&
175 	    (LAC_CIPHER_IV_SIZE_GCM_12 == ivLenInBytes))
176 
177 	{
178 		ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET(
179 		    *pLaCommandFlags, ICP_QAT_FW_LA_GCM_IV_LEN_12_OCTETS);
180 	}
181 }
182 
183 void
184 LacSymQat_packetTypeGet(CpaCySymPacketType packetType,
185 			CpaCySymPacketType packetState,
186 			Cpa32U *pQatPacketType)
187 {
188 	switch (packetType) {
189 	/* partial */
190 	case CPA_CY_SYM_PACKET_TYPE_PARTIAL:
191 		/* if the previous state was full, then this is the first packet
192 		 */
193 		if (CPA_CY_SYM_PACKET_TYPE_FULL == packetState) {
194 			*pQatPacketType = ICP_QAT_FW_LA_PARTIAL_START;
195 		} else {
196 			*pQatPacketType = ICP_QAT_FW_LA_PARTIAL_MID;
197 		}
198 		break;
199 
200 	/* final partial */
201 	case CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL:
202 		*pQatPacketType = ICP_QAT_FW_LA_PARTIAL_END;
203 		break;
204 
205 	/* full packet - CPA_CY_SYM_PACKET_TYPE_FULL */
206 	default:
207 		*pQatPacketType = ICP_QAT_FW_LA_PARTIAL_NONE;
208 	}
209 }
210 
211 void
212 LacSymQat_LaSetDefaultFlags(icp_qat_fw_serv_specif_flags *laCmdFlags,
213 			    CpaCySymOp symOp)
214 {
215 
216 	ICP_QAT_FW_LA_PARTIAL_SET(*laCmdFlags, ICP_QAT_FW_LA_PARTIAL_NONE);
217 
218 	ICP_QAT_FW_LA_UPDATE_STATE_SET(*laCmdFlags,
219 				       ICP_QAT_FW_LA_NO_UPDATE_STATE);
220 
221 	if (symOp != CPA_CY_SYM_OP_CIPHER) {
222 		ICP_QAT_FW_LA_RET_AUTH_SET(*laCmdFlags,
223 					   ICP_QAT_FW_LA_RET_AUTH_RES);
224 	} else {
225 		ICP_QAT_FW_LA_RET_AUTH_SET(*laCmdFlags,
226 					   ICP_QAT_FW_LA_NO_RET_AUTH_RES);
227 	}
228 
229 	ICP_QAT_FW_LA_CMP_AUTH_SET(*laCmdFlags, ICP_QAT_FW_LA_NO_CMP_AUTH_RES);
230 
231 	ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET(
232 	    *laCmdFlags, ICP_QAT_FW_LA_GCM_IV_LEN_NOT_12_OCTETS);
233 }
234 
235 CpaBoolean
236 LacSymQat_UseSymConstantsTable(lac_session_desc_t *pSession,
237 			       Cpa8U *pCipherOffset,
238 			       Cpa8U *pHashOffset)
239 {
240 
241 	CpaBoolean useOptimisedContentDesc = CPA_FALSE;
242 	CpaBoolean useSHRAMConstants = CPA_FALSE;
243 
244 	*pCipherOffset = 0;
245 	*pHashOffset = 0;
246 
247 	/* for chaining can we use the optimised content descritor */
248 	if (pSession->laCmdId == ICP_QAT_FW_LA_CMD_CIPHER_HASH ||
249 	    pSession->laCmdId == ICP_QAT_FW_LA_CMD_HASH_CIPHER) {
250 		useOptimisedContentDesc =
251 		    LacSymQat_UseOptimisedContentDesc(pSession);
252 	}
253 
254 	/* Cipher-only case or chaining */
255 	if (pSession->laCmdId == ICP_QAT_FW_LA_CMD_CIPHER ||
256 	    useOptimisedContentDesc) {
257 		icp_qat_hw_cipher_algo_t algorithm;
258 		icp_qat_hw_cipher_mode_t mode;
259 		icp_qat_hw_cipher_dir_t dir;
260 		icp_qat_hw_cipher_convert_t key_convert;
261 
262 		if (pSession->cipherKeyLenInBytes >
263 		    sizeof(icp_qat_fw_comn_req_hdr_cd_pars_t)) {
264 			return CPA_FALSE;
265 		}
266 
267 		LacSymQat_CipherGetCfgData(
268 		    pSession, &algorithm, &mode, &dir, &key_convert);
269 
270 		/* Check if cipher config is available in table. */
271 		LacSymQat_ConstantsGetCipherOffset(pSession->pInstance,
272 						   algorithm,
273 						   mode,
274 						   dir,
275 						   key_convert,
276 						   pCipherOffset);
277 		if (*pCipherOffset > 0) {
278 			useSHRAMConstants = CPA_TRUE;
279 		} else {
280 			useSHRAMConstants = CPA_FALSE;
281 		}
282 	}
283 
284 	/* hash only case or when chaining, cipher must be found in SHRAM table
285 	 * for
286 	 * optimised CD case */
287 	if (pSession->laCmdId == ICP_QAT_FW_LA_CMD_AUTH ||
288 	    (useOptimisedContentDesc && useSHRAMConstants)) {
289 		icp_qat_hw_auth_algo_t algorithm;
290 		CpaBoolean nested;
291 
292 		if (pSession->digestVerify) {
293 			return CPA_FALSE;
294 		}
295 
296 		if ((!(useOptimisedContentDesc && useSHRAMConstants)) &&
297 		    (pSession->qatHashMode == ICP_QAT_HW_AUTH_MODE1)) {
298 			/* we can only use the SHA1-mode1 in the SHRAM constants
299 			 * table when
300 			 * we are using the opimised content desc */
301 			return CPA_FALSE;
302 		}
303 
304 		LacSymQat_HashGetCfgData(pSession->pInstance,
305 					 pSession->qatHashMode,
306 					 pSession->hashMode,
307 					 pSession->hashAlgorithm,
308 					 &algorithm,
309 					 &nested);
310 
311 		/* Check if config data is available in table. */
312 		LacSymQat_ConstantsGetAuthOffset(pSession->pInstance,
313 						 algorithm,
314 						 pSession->qatHashMode,
315 						 nested,
316 						 pHashOffset);
317 		if (*pHashOffset > 0) {
318 			useSHRAMConstants = CPA_TRUE;
319 		} else {
320 			useSHRAMConstants = CPA_FALSE;
321 		}
322 	}
323 
324 	return useSHRAMConstants;
325 }
326 
327 CpaBoolean
328 LacSymQat_UseOptimisedContentDesc(lac_session_desc_t *pSession)
329 {
330 	return CPA_FALSE;
331 }
332