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
38static void
39LacSymQat_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 */
68static sal_qat_resp_handler_func_t
69    respHandlerSymTbl[ICP_QAT_FW_LA_CMD_DELIMITER];
70
71void
72LacSymQat_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
102CpaStatus
103LacSymQat_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
116void
117LacSymQat_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
129void
130LacSymQat_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
183void
184LacSymQat_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
211void
212LacSymQat_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
235CpaBoolean
236LacSymQat_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
327CpaBoolean
328LacSymQat_UseOptimisedContentDesc(lac_session_desc_t *pSession)
329{
330	return CPA_FALSE;
331}
332