1/* SPDX-License-Identifier: BSD-3-Clause */
2/* Copyright(c) 2007-2022 Intel Corporation */
3
4/**
5 ***************************************************************************
6 * @file lac_sym_api.c      Implementation of the symmetric API
7 *
8 * @ingroup LacSym
9 *
10 ***************************************************************************/
11
12/*
13*******************************************************************************
14* Include public/global header files
15*******************************************************************************
16*/
17
18#include "cpa.h"
19#include "cpa_cy_sym.h"
20#include "cpa_cy_im.h"
21
22#include "icp_adf_init.h"
23#include "icp_adf_transport.h"
24#include "icp_adf_transport_dp.h"
25#include "icp_accel_devices.h"
26#include "icp_adf_debug.h"
27#include "icp_qat_fw_la.h"
28
29/*
30 ******************************************************************************
31 * Include private header files
32 ******************************************************************************
33 */
34#include "lac_common.h"
35#include "lac_log.h"
36#include "lac_mem.h"
37#include "lac_mem_pools.h"
38#include "lac_list.h"
39#include "lac_sym.h"
40#include "lac_sym_qat.h"
41#include "lac_sal.h"
42#include "lac_sal_ctrl.h"
43#include "lac_session.h"
44#include "lac_sym_cipher.h"
45#include "lac_sym_hash.h"
46#include "lac_sym_alg_chain.h"
47#include "lac_sym_stats.h"
48#include "lac_sym_partial.h"
49#include "lac_sym_qat_hash_defs_lookup.h"
50#include "lac_sym_cb.h"
51#include "lac_buffer_desc.h"
52#include "lac_sync.h"
53#include "lac_hooks.h"
54#include "lac_sal_types_crypto.h"
55#include "sal_service_state.h"
56
57#define IS_EXT_ALG_CHAIN_UNSUPPORTED(cipherAlgorithm,                          \
58				     hashAlgorithm,                            \
59				     extAlgchainSupported)                     \
60	((((CPA_CY_SYM_CIPHER_ZUC_EEA3 == cipherAlgorithm ||                   \
61	    CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == cipherAlgorithm) &&               \
62	   CPA_CY_SYM_HASH_AES_CMAC == hashAlgorithm) ||                       \
63	  ((CPA_CY_SYM_CIPHER_NULL == cipherAlgorithm ||                       \
64	    CPA_CY_SYM_CIPHER_AES_CTR == cipherAlgorithm ||                    \
65	    CPA_CY_SYM_CIPHER_ZUC_EEA3 == cipherAlgorithm) &&                  \
66	   CPA_CY_SYM_HASH_SNOW3G_UIA2 == hashAlgorithm) ||                    \
67	  ((CPA_CY_SYM_CIPHER_NULL == cipherAlgorithm ||                       \
68	    CPA_CY_SYM_CIPHER_AES_CTR == cipherAlgorithm ||                    \
69	    CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == cipherAlgorithm) &&               \
70	   CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlgorithm)) &&                      \
71	 !extAlgchainSupported)
72
73/*** Local functions definitions ***/
74static CpaStatus
75LacSymPerform_BufferParamCheck(const CpaBufferList *const pSrcBuffer,
76			       const CpaBufferList *const pDstBuffer,
77			       const lac_session_desc_t *const pSessionDesc,
78			       const CpaCySymOpData *const pOpData);
79
80void LacDp_WriteRingMsgFull(CpaCySymDpOpData *pRequest,
81			    icp_qat_fw_la_bulk_req_t *pCurrentQatMsg);
82void LacDp_WriteRingMsgOpt(CpaCySymDpOpData *pRequest,
83			   icp_qat_fw_la_bulk_req_t *pCurrentQatMsg);
84void getCtxSize(const CpaCySymSessionSetupData *pSessionSetupData,
85		Cpa32U *pSessionCtxSizeInBytes);
86
87/**
88 *****************************************************************************
89 * @ingroup LacSym
90 *      Generic bufferList callback function.
91 * @description
92 *      This function is used when the API is called in synchronous mode.
93 *      It's assumed the callbackTag holds a lac_sync_op_data_t type
94 *      and when the callback is received, this callback shall set the
95 *      status and opResult element of that cookie structure and
96 *      kick the sid.
97 *      This function may be used directly as a callback function.
98 *
99 * @param[in]  callbackTag       Callback Tag
100 * @param[in]  status            Status of callback
101 * @param[in]  operationType     Operation Type
102 * @param[in]  pOpData           Pointer to the Op Data
103 * @param[out] pDstBuffer        Pointer to destination buffer list
104 * @param[out] opResult          Boolean to indicate the result of the operation
105 *
106 * @return void
107 *
108 *****************************************************************************/
109void
110LacSync_GenBufListVerifyCb(void *pCallbackTag,
111			   CpaStatus status,
112			   CpaCySymOp operationType,
113			   void *pOpData,
114			   CpaBufferList *pDstBuffer,
115			   CpaBoolean opResult)
116{
117	LacSync_GenVerifyWakeupSyncCaller(pCallbackTag, status, opResult);
118}
119
120/*
121*******************************************************************************
122* Define static function definitions
123*******************************************************************************
124*/
125/**
126 * @ingroup LacSym
127 * Function which perform parameter checks on session setup data
128 *
129 * @param[in] CpaInstanceHandle     Instance Handle
130 * @param[in] pSessionSetupData     Pointer to session setup data
131 *
132 * @retval CPA_STATUS_SUCCESS        The operation succeeded
133 * @retval CPA_STATUS_INVALID_PARAM  An invalid parameter value was found
134 */
135static CpaStatus
136LacSymSession_ParamCheck(const CpaInstanceHandle instanceHandle,
137			 const CpaCySymSessionSetupData *pSessionSetupData)
138{
139	/* initialize convenient pointers to cipher and hash contexts */
140	const CpaCySymCipherSetupData *const pCipherSetupData =
141	    (const CpaCySymCipherSetupData *)&pSessionSetupData
142		->cipherSetupData;
143	const CpaCySymHashSetupData *const pHashSetupData =
144	    &pSessionSetupData->hashSetupData;
145
146	CpaCySymCapabilitiesInfo capInfo;
147	CpaCyCapabilitiesInfo cyCapInfo;
148	cpaCySymQueryCapabilities(instanceHandle, &capInfo);
149	SalCtrl_CyQueryCapabilities(instanceHandle, &cyCapInfo);
150
151	/* Ensure cipher algorithm is correct and supported */
152	if ((CPA_CY_SYM_OP_ALGORITHM_CHAINING ==
153	     pSessionSetupData->symOperation) ||
154	    (CPA_CY_SYM_OP_CIPHER == pSessionSetupData->symOperation)) {
155		/* Protect against value of cipher outside the bitmap
156		 * and check if cipher algorithm is correct
157		 */
158		if (pCipherSetupData->cipherAlgorithm >=
159		    CPA_CY_SYM_CIPHER_CAP_BITMAP_SIZE) {
160			LAC_INVALID_PARAM_LOG("cipherAlgorithm");
161			return CPA_STATUS_INVALID_PARAM;
162		}
163		if (!CPA_BITMAP_BIT_TEST(capInfo.ciphers,
164					 pCipherSetupData->cipherAlgorithm)) {
165			LAC_UNSUPPORTED_PARAM_LOG(
166			    "UnSupported cipherAlgorithm");
167			return CPA_STATUS_UNSUPPORTED;
168		}
169	}
170
171	/* Ensure hash algorithm is correct and supported */
172	if ((CPA_CY_SYM_OP_ALGORITHM_CHAINING ==
173	     pSessionSetupData->symOperation) ||
174	    (CPA_CY_SYM_OP_HASH == pSessionSetupData->symOperation)) {
175		/* Protect against value of hash outside the bitmap
176		 * and check if hash algorithm is correct
177		 */
178		if (pHashSetupData->hashAlgorithm >=
179		    CPA_CY_SYM_HASH_CAP_BITMAP_SIZE) {
180			LAC_INVALID_PARAM_LOG("hashAlgorithm");
181			return CPA_STATUS_INVALID_PARAM;
182		}
183		if (!CPA_BITMAP_BIT_TEST(capInfo.hashes,
184					 pHashSetupData->hashAlgorithm)) {
185			LAC_UNSUPPORTED_PARAM_LOG("UnSupported hashAlgorithm");
186			return CPA_STATUS_UNSUPPORTED;
187		}
188	}
189
190	/* ensure CCM, GCM, Kasumi, Snow3G and ZUC cipher and hash algorithms
191	 * are selected together for Algorithm Chaining */
192	if (CPA_CY_SYM_OP_ALGORITHM_CHAINING ==
193	    pSessionSetupData->symOperation) {
194		/* ensure both hash and cipher algorithms are POLY and CHACHA */
195		if (((CPA_CY_SYM_CIPHER_CHACHA ==
196		      pCipherSetupData->cipherAlgorithm) &&
197		     (CPA_CY_SYM_HASH_POLY != pHashSetupData->hashAlgorithm)) ||
198		    ((CPA_CY_SYM_HASH_POLY == pHashSetupData->hashAlgorithm) &&
199		     (CPA_CY_SYM_CIPHER_CHACHA !=
200		      pCipherSetupData->cipherAlgorithm))) {
201			LAC_INVALID_PARAM_LOG(
202			    "Invalid combination of Cipher/Hash "
203			    "Algorithms for CHACHA/POLY");
204			return CPA_STATUS_INVALID_PARAM;
205		}
206
207		/* ensure both hash and cipher algorithms are CCM */
208		if (((CPA_CY_SYM_CIPHER_AES_CCM ==
209		      pCipherSetupData->cipherAlgorithm) &&
210		     (CPA_CY_SYM_HASH_AES_CCM !=
211		      pHashSetupData->hashAlgorithm)) ||
212		    ((CPA_CY_SYM_HASH_AES_CCM ==
213		      pHashSetupData->hashAlgorithm) &&
214		     (CPA_CY_SYM_CIPHER_AES_CCM !=
215		      pCipherSetupData->cipherAlgorithm))) {
216			LAC_INVALID_PARAM_LOG(
217			    "Invalid combination of Cipher/Hash Algorithms for CCM");
218			return CPA_STATUS_INVALID_PARAM;
219		}
220
221		/* ensure both hash and cipher algorithms are GCM/GMAC */
222		if ((CPA_CY_SYM_CIPHER_AES_GCM ==
223			 pCipherSetupData->cipherAlgorithm &&
224		     (CPA_CY_SYM_HASH_AES_GCM !=
225			  pHashSetupData->hashAlgorithm &&
226		      CPA_CY_SYM_HASH_AES_GMAC !=
227			  pHashSetupData->hashAlgorithm)) ||
228		    ((CPA_CY_SYM_HASH_AES_GCM ==
229			  pHashSetupData->hashAlgorithm ||
230		      CPA_CY_SYM_HASH_AES_GMAC ==
231			  pHashSetupData->hashAlgorithm) &&
232		     CPA_CY_SYM_CIPHER_AES_GCM !=
233			 pCipherSetupData->cipherAlgorithm)) {
234			LAC_INVALID_PARAM_LOG(
235			    "Invalid combination of Cipher/Hash Algorithms for GCM");
236			return CPA_STATUS_INVALID_PARAM;
237		}
238
239		/* ensure both hash and cipher algorithms are Kasumi */
240		if (((CPA_CY_SYM_CIPHER_KASUMI_F8 ==
241		      pCipherSetupData->cipherAlgorithm) &&
242		     (CPA_CY_SYM_HASH_KASUMI_F9 !=
243		      pHashSetupData->hashAlgorithm)) ||
244		    ((CPA_CY_SYM_HASH_KASUMI_F9 ==
245		      pHashSetupData->hashAlgorithm) &&
246		     (CPA_CY_SYM_CIPHER_KASUMI_F8 !=
247		      pCipherSetupData->cipherAlgorithm))) {
248			LAC_INVALID_PARAM_LOG(
249			    "Invalid combination of Cipher/Hash Algorithms for Kasumi");
250			return CPA_STATUS_INVALID_PARAM;
251		}
252
253		if (IS_EXT_ALG_CHAIN_UNSUPPORTED(
254			pCipherSetupData->cipherAlgorithm,
255			pHashSetupData->hashAlgorithm,
256			cyCapInfo.extAlgchainSupported)) {
257			LAC_UNSUPPORTED_PARAM_LOG(
258			    "ExtAlgChain feature not supported");
259			return CPA_STATUS_UNSUPPORTED;
260		}
261
262		/* ensure both hash and cipher algorithms are Snow3G */
263		if (((CPA_CY_SYM_CIPHER_SNOW3G_UEA2 ==
264		      pCipherSetupData->cipherAlgorithm) &&
265		     (CPA_CY_SYM_HASH_SNOW3G_UIA2 !=
266		      pHashSetupData->hashAlgorithm)) ||
267		    ((CPA_CY_SYM_HASH_SNOW3G_UIA2 ==
268		      pHashSetupData->hashAlgorithm) &&
269		     (CPA_CY_SYM_CIPHER_SNOW3G_UEA2 !=
270		      pCipherSetupData->cipherAlgorithm))) {
271			LAC_INVALID_PARAM_LOG(
272			    "Invalid combination of Cipher/Hash Algorithms for Snow3G");
273			return CPA_STATUS_INVALID_PARAM;
274		}
275
276		/* ensure both hash and cipher algorithms are ZUC */
277		if (((CPA_CY_SYM_CIPHER_ZUC_EEA3 ==
278		      pCipherSetupData->cipherAlgorithm) &&
279		     (CPA_CY_SYM_HASH_ZUC_EIA3 !=
280		      pHashSetupData->hashAlgorithm)) ||
281		    ((CPA_CY_SYM_HASH_ZUC_EIA3 ==
282		      pHashSetupData->hashAlgorithm) &&
283		     (CPA_CY_SYM_CIPHER_ZUC_EEA3 !=
284		      pCipherSetupData->cipherAlgorithm))) {
285			LAC_INVALID_PARAM_LOG(
286			    "Invalid combination of Cipher/Hash Algorithms for ZUC");
287			return CPA_STATUS_INVALID_PARAM;
288		}
289	}
290	/* not Algorithm Chaining so prevent CCM/GCM being selected */
291	else if (CPA_CY_SYM_OP_CIPHER == pSessionSetupData->symOperation) {
292		/* ensure cipher algorithm is not CCM or GCM */
293		if ((CPA_CY_SYM_CIPHER_AES_CCM ==
294		     pCipherSetupData->cipherAlgorithm) ||
295		    (CPA_CY_SYM_CIPHER_AES_GCM ==
296		     pCipherSetupData->cipherAlgorithm) ||
297		    (CPA_CY_SYM_CIPHER_CHACHA ==
298		     pCipherSetupData->cipherAlgorithm)) {
299			LAC_INVALID_PARAM_LOG(
300			    "Invalid Cipher Algorithm for non-Algorithm "
301			    "Chaining operation");
302			return CPA_STATUS_INVALID_PARAM;
303		}
304	} else if (CPA_CY_SYM_OP_HASH == pSessionSetupData->symOperation) {
305		/* ensure hash algorithm is not CCM or GCM/GMAC */
306		if ((CPA_CY_SYM_HASH_AES_CCM ==
307		     pHashSetupData->hashAlgorithm) ||
308		    (CPA_CY_SYM_HASH_AES_GCM ==
309		     pHashSetupData->hashAlgorithm) ||
310		    (CPA_CY_SYM_HASH_AES_GMAC ==
311		     pHashSetupData->hashAlgorithm) ||
312		    (CPA_CY_SYM_HASH_POLY == pHashSetupData->hashAlgorithm)) {
313			LAC_INVALID_PARAM_LOG(
314			    "Invalid Hash Algorithm for non-Algorithm Chaining operation");
315			return CPA_STATUS_INVALID_PARAM;
316		}
317	}
318	/* Unsupported operation. Return error */
319	else {
320		LAC_INVALID_PARAM_LOG("symOperation");
321		return CPA_STATUS_INVALID_PARAM;
322	}
323
324	/* ensure that cipher direction param is
325	 * valid for cipher and algchain ops */
326	if (CPA_CY_SYM_OP_HASH != pSessionSetupData->symOperation) {
327		if ((pCipherSetupData->cipherDirection !=
328		     CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT) &&
329		    (pCipherSetupData->cipherDirection !=
330		     CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT)) {
331			LAC_INVALID_PARAM_LOG("Invalid Cipher Direction");
332			return CPA_STATUS_INVALID_PARAM;
333		}
334	}
335
336	return CPA_STATUS_SUCCESS;
337}
338
339
340/**
341 * @ingroup LacSym
342 * Function which perform parameter checks on data buffers for symmetric
343 * crypto operations
344 *
345 * @param[in] pSrcBuffer          Pointer to source buffer list
346 * @param[in] pDstBuffer          Pointer to destination buffer list
347 * @param[in] pSessionDesc        Pointer to session descriptor
348 * @param[in] pOpData             Pointer to CryptoSymOpData.
349 *
350 * @retval CPA_STATUS_SUCCESS        The operation succeeded
351 * @retval CPA_STATUS_INVALID_PARAM  An invalid parameter value was found
352 */
353
354static CpaStatus
355LacSymPerform_BufferParamCheck(const CpaBufferList *const pSrcBuffer,
356			       const CpaBufferList *const pDstBuffer,
357			       const lac_session_desc_t *const pSessionDesc,
358			       const CpaCySymOpData *const pOpData)
359{
360	Cpa64U srcBufferLen = 0, dstBufferLen = 0;
361	CpaStatus status = CPA_STATUS_SUCCESS;
362
363	/* verify packet type is in correct range */
364	switch (pOpData->packetType) {
365	case CPA_CY_SYM_PACKET_TYPE_FULL:
366	case CPA_CY_SYM_PACKET_TYPE_PARTIAL:
367	case CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL:
368		break;
369	default: {
370		LAC_INVALID_PARAM_LOG("packetType");
371		return CPA_STATUS_INVALID_PARAM;
372	}
373	}
374
375	if (!((CPA_CY_SYM_OP_CIPHER != pSessionDesc->symOperation &&
376	       CPA_CY_SYM_HASH_MODE_PLAIN == pSessionDesc->hashMode) &&
377	      (0 == pOpData->messageLenToHashInBytes))) {
378		if (IS_ZERO_LENGTH_BUFFER_SUPPORTED(
379			pSessionDesc->cipherAlgorithm,
380			pSessionDesc->hashAlgorithm)) {
381			status = LacBuffDesc_BufferListVerifyNull(
382			    pSrcBuffer, &srcBufferLen, LAC_NO_ALIGNMENT_SHIFT);
383		} else {
384			status = LacBuffDesc_BufferListVerify(
385			    pSrcBuffer, &srcBufferLen, LAC_NO_ALIGNMENT_SHIFT);
386		}
387		if (CPA_STATUS_SUCCESS != status) {
388			LAC_INVALID_PARAM_LOG("Source buffer invalid");
389			return CPA_STATUS_INVALID_PARAM;
390		}
391	} else {
392		/* check MetaData !NULL */
393		if (NULL == pSrcBuffer->pPrivateMetaData) {
394			LAC_INVALID_PARAM_LOG(
395			    "Source buffer MetaData cannot be NULL");
396			return CPA_STATUS_INVALID_PARAM;
397		}
398	}
399
400	/* out of place checks */
401	if (pSrcBuffer != pDstBuffer) {
402		/* exception for this check is zero length hash requests to
403		 * allow */
404		/* for srcBufflen=DstBufferLen=0 */
405		if (!((CPA_CY_SYM_OP_CIPHER != pSessionDesc->symOperation &&
406		       CPA_CY_SYM_HASH_MODE_PLAIN == pSessionDesc->hashMode) &&
407		      (0 == pOpData->messageLenToHashInBytes))) {
408			/* Verify buffer(s) for dest packet & return packet
409			 * length */
410			if (IS_ZERO_LENGTH_BUFFER_SUPPORTED(
411				pSessionDesc->cipherAlgorithm,
412				pSessionDesc->hashAlgorithm)) {
413				status = LacBuffDesc_BufferListVerifyNull(
414				    pDstBuffer,
415				    &dstBufferLen,
416				    LAC_NO_ALIGNMENT_SHIFT);
417			} else {
418				status = LacBuffDesc_BufferListVerify(
419				    pDstBuffer,
420				    &dstBufferLen,
421				    LAC_NO_ALIGNMENT_SHIFT);
422			}
423			if (CPA_STATUS_SUCCESS != status) {
424				LAC_INVALID_PARAM_LOG(
425				    "Destination buffer invalid");
426				return CPA_STATUS_INVALID_PARAM;
427			}
428		} else {
429			/* check MetaData !NULL */
430			if (NULL == pDstBuffer->pPrivateMetaData) {
431				LAC_INVALID_PARAM_LOG(
432				    "Dest buffer MetaData cannot be NULL");
433				return CPA_STATUS_INVALID_PARAM;
434			}
435		}
436		/* Check that src Buffer and dst Buffer Lengths are equal */
437		/* CCM output needs to be longer than input buffer for appending
438		 * tag*/
439		if (srcBufferLen != dstBufferLen &&
440		    pSessionDesc->cipherAlgorithm !=
441			CPA_CY_SYM_CIPHER_AES_CCM) {
442			LAC_INVALID_PARAM_LOG(
443			    "Source and Dest buffer lengths need to be equal ");
444			return CPA_STATUS_INVALID_PARAM;
445		}
446	}
447
448	/* check for partial packet suport for the session operation */
449	if (CPA_CY_SYM_PACKET_TYPE_FULL != pOpData->packetType) {
450		if (CPA_FALSE == pSessionDesc->isPartialSupported) {
451			/* return out here to simplify cleanup */
452			LAC_INVALID_PARAM_LOG(
453			    "Partial packets not supported for operation");
454			return CPA_STATUS_INVALID_PARAM;
455		} else {
456			/* This function checks to see if the partial packet
457			 * sequence is correct */
458			if (CPA_STATUS_SUCCESS !=
459			    LacSym_PartialPacketStateCheck(
460				pOpData->packetType,
461				pSessionDesc->partialState)) {
462				LAC_INVALID_PARAM_LOG("Partial packet Type");
463				return CPA_STATUS_INVALID_PARAM;
464			}
465		}
466	}
467	return CPA_STATUS_SUCCESS;
468}
469
470/** @ingroup LacSym */
471CpaStatus
472cpaCySymInitSession(const CpaInstanceHandle instanceHandle_in,
473		    const CpaCySymCbFunc pSymCb,
474		    const CpaCySymSessionSetupData *pSessionSetupData,
475		    CpaCySymSessionCtx pSessionCtx)
476{
477	CpaStatus status = CPA_STATUS_SUCCESS;
478	CpaInstanceHandle instanceHandle = NULL;
479	sal_service_t *pService = NULL;
480
481	if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
482		instanceHandle =
483		    Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM);
484	} else {
485		instanceHandle = instanceHandle_in;
486	}
487
488	LAC_CHECK_INSTANCE_HANDLE(instanceHandle);
489	SAL_CHECK_INSTANCE_TYPE(instanceHandle,
490				(SAL_SERVICE_TYPE_CRYPTO |
491				 SAL_SERVICE_TYPE_CRYPTO_SYM));
492
493	pService = (sal_service_t *)instanceHandle;
494
495	/* check crypto service is running otherwise return an error */
496	SAL_RUNNING_CHECK(pService);
497
498	status = LacSym_InitSession(instanceHandle,
499				    pSymCb,
500				    pSessionSetupData,
501				    CPA_FALSE, /* isDPSession */
502				    pSessionCtx);
503
504	if (CPA_STATUS_SUCCESS == status) {
505		/* Increment the stats for a session registered successfully */
506		LAC_SYM_STAT_INC(numSessionsInitialized, instanceHandle);
507	} else /* if there was an error */
508	{
509		LAC_SYM_STAT_INC(numSessionErrors, instanceHandle);
510	}
511
512	return status;
513}
514
515CpaStatus
516cpaCySymSessionInUse(CpaCySymSessionCtx pSessionCtx, CpaBoolean *pSessionInUse)
517{
518	CpaStatus status = CPA_STATUS_SUCCESS;
519	lac_session_desc_t *pSessionDesc = NULL;
520
521	LAC_CHECK_NULL_PARAM(pSessionInUse);
522	LAC_CHECK_INSTANCE_HANDLE(pSessionCtx);
523
524	*pSessionInUse = CPA_FALSE;
525
526	pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pSessionCtx);
527
528	/* If there are pending requests */
529	if (pSessionDesc->isDPSession) {
530		if (qatUtilsAtomicGet(&(pSessionDesc->u.pendingDpCbCount)))
531			*pSessionInUse = CPA_TRUE;
532	} else {
533		if (qatUtilsAtomicGet(&(pSessionDesc->u.pendingCbCount)))
534			*pSessionInUse = CPA_TRUE;
535	}
536
537	return status;
538}
539
540CpaStatus
541LacSym_InitSession(const CpaInstanceHandle instanceHandle,
542		   const CpaCySymCbFunc pSymCb,
543		   const CpaCySymSessionSetupData *pSessionSetupData,
544		   const CpaBoolean isDPSession,
545		   CpaCySymSessionCtx pSessionCtx)
546{
547	CpaStatus status = CPA_STATUS_SUCCESS;
548	lac_session_desc_t *pSessionDesc = NULL;
549	Cpa32U sessionCtxSizeInBytes = 0;
550	CpaPhysicalAddr physAddress = 0;
551	CpaPhysicalAddr physAddressAligned = 0;
552	sal_service_t *pService = NULL;
553	const CpaCySymCipherSetupData *pCipherSetupData = NULL;
554	const CpaCySymHashSetupData *pHashSetupData = NULL;
555
556	/* Instance param checking done by calling function */
557
558	LAC_CHECK_NULL_PARAM(pSessionSetupData);
559	LAC_CHECK_NULL_PARAM(pSessionCtx);
560	status = LacSymSession_ParamCheck(instanceHandle, pSessionSetupData);
561	LAC_CHECK_STATUS(status);
562
563	/* set the session priority for QAT AL*/
564	if ((CPA_CY_PRIORITY_HIGH == pSessionSetupData->sessionPriority) ||
565	    (CPA_CY_PRIORITY_NORMAL == pSessionSetupData->sessionPriority)) {
566		// do nothing - clean up this code. use RANGE macro
567	} else {
568		LAC_INVALID_PARAM_LOG("sessionPriority");
569		return CPA_STATUS_INVALID_PARAM;
570	}
571
572
573	pCipherSetupData = &pSessionSetupData->cipherSetupData;
574	pHashSetupData = &pSessionSetupData->hashSetupData;
575
576	pService = (sal_service_t *)instanceHandle;
577
578	/* Re-align the session structure to 64 byte alignment */
579	physAddress =
580	    LAC_OS_VIRT_TO_PHYS_EXTERNAL((*pService),
581					 (Cpa8U *)pSessionCtx + sizeof(void *));
582
583	if (0 == physAddress) {
584		LAC_LOG_ERROR(
585		    "Unable to get the physical address of the session\n");
586		return CPA_STATUS_FAIL;
587	}
588
589	physAddressAligned =
590	    LAC_ALIGN_POW2_ROUNDUP(physAddress, LAC_64BYTE_ALIGNMENT);
591
592	pSessionDesc = (lac_session_desc_t *)
593	    /* Move the session pointer by the physical offset
594	    between aligned and unaligned memory */
595	    ((Cpa8U *)pSessionCtx + sizeof(void *) +
596	     (physAddressAligned - physAddress));
597
598	/* save the aligned pointer in the first bytes (size of unsigned long)
599	 * of the session memory */
600	*((LAC_ARCH_UINT *)pSessionCtx) = (LAC_ARCH_UINT)pSessionDesc;
601
602	/* start off with a clean session */
603	/* Choose Session Context size */
604	getCtxSize(pSessionSetupData, &sessionCtxSizeInBytes);
605	switch (sessionCtxSizeInBytes) {
606	case LAC_SYM_SESSION_D1_SIZE:
607		memset(pSessionDesc, 0, sizeof(lac_session_desc_d1_t));
608		break;
609	case LAC_SYM_SESSION_D2_SIZE:
610		memset(pSessionDesc, 0, sizeof(lac_session_desc_d2_t));
611		break;
612	default:
613		memset(pSessionDesc, 0, sizeof(lac_session_desc_t));
614		break;
615	}
616
617	/* Setup content descriptor info structure
618	 * assumption that content descriptor is the first field in
619	 * in the session descriptor */
620	pSessionDesc->contentDescInfo.pData = (Cpa8U *)pSessionDesc;
621	pSessionDesc->contentDescInfo.hardwareSetupBlockPhys =
622	    physAddressAligned;
623
624	pSessionDesc->contentDescOptimisedInfo.pData =
625	    ((Cpa8U *)pSessionDesc + LAC_SYM_QAT_CONTENT_DESC_MAX_SIZE);
626	pSessionDesc->contentDescOptimisedInfo.hardwareSetupBlockPhys =
627	    (physAddressAligned + LAC_SYM_QAT_CONTENT_DESC_MAX_SIZE);
628
629	/* Set the Common Session Information */
630	pSessionDesc->symOperation = pSessionSetupData->symOperation;
631
632	if (CPA_FALSE == isDPSession) {
633		/* For asynchronous - use the user supplied callback
634		 * for synchronous - use the internal synchronous callback */
635		pSessionDesc->pSymCb = ((void *)NULL != (void *)pSymCb) ?
636			  pSymCb :
637			  LacSync_GenBufListVerifyCb;
638	}
639
640	pSessionDesc->isDPSession = isDPSession;
641	if ((CPA_CY_SYM_HASH_AES_GCM == pHashSetupData->hashAlgorithm) ||
642	    (CPA_CY_SYM_HASH_AES_GMAC == pHashSetupData->hashAlgorithm) ||
643	    (CPA_CY_SYM_HASH_AES_CCM == pHashSetupData->hashAlgorithm) ||
644	    (CPA_CY_SYM_CIPHER_CHACHA == pCipherSetupData->cipherAlgorithm) ||
645	    (CPA_CY_SYM_CIPHER_ARC4 == pCipherSetupData->cipherAlgorithm)) {
646		pSessionDesc->writeRingMsgFunc = LacDp_WriteRingMsgFull;
647	} else {
648		pSessionDesc->writeRingMsgFunc = LacDp_WriteRingMsgOpt;
649	}
650
651	if (CPA_STATUS_SUCCESS == status) {
652		/* Session set up via API call (not internal one) */
653		/* Services such as DRBG call the crypto api as part of their
654		 * service hence the need to for the flag, it is needed to
655		 * distinguish between an internal and external session.
656		 */
657		pSessionDesc->internalSession = CPA_FALSE;
658
659		status = LacAlgChain_SessionInit(instanceHandle,
660						 pSessionSetupData,
661						 pSessionDesc);
662	}
663	return status;
664}
665
666/** @ingroup LacSym */
667CpaStatus
668cpaCySymRemoveSession(const CpaInstanceHandle instanceHandle_in,
669		      CpaCySymSessionCtx pSessionCtx)
670{
671	lac_session_desc_t *pSessionDesc = NULL;
672	CpaStatus status = CPA_STATUS_SUCCESS;
673	CpaInstanceHandle instanceHandle = NULL;
674	Cpa64U numPendingRequests = 0;
675
676
677	if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
678		instanceHandle =
679		    Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM);
680	} else {
681		instanceHandle = instanceHandle_in;
682	}
683
684	LAC_CHECK_INSTANCE_HANDLE(instanceHandle);
685	SAL_CHECK_INSTANCE_TYPE(instanceHandle,
686				(SAL_SERVICE_TYPE_CRYPTO |
687				 SAL_SERVICE_TYPE_CRYPTO_SYM));
688	LAC_CHECK_NULL_PARAM(pSessionCtx);
689
690	/* check crypto service is running otherwise return an error */
691	SAL_RUNNING_CHECK(instanceHandle);
692	pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pSessionCtx);
693
694	LAC_CHECK_NULL_PARAM(pSessionDesc);
695
696	if (CPA_TRUE == pSessionDesc->isDPSession) {
697		/*
698		 * Based on one instance, we can initialize multiple sessions.
699		 * For example, we can initialize the session "X" and session
700		 * "Y" with the same instance "A". If there is no operation
701		 * pending for session "X", we can remove the session "X".
702		 *
703		 * Now we only check the @pSessionDesc->pendingDpCbCount, if it
704		 * becomes zero, we can remove the session.
705		 *
706		 * Why?
707		 *   (1) We increase it in the cpaCySymDpEnqueueOp/
708		 *       cpaCySymDpEnqueueOpBatch.
709		 *   (2) We decrease it in the LacSymCb_ProcessCallback.
710		 *
711		 * If the @pSessionDesc->pendingDpCbCount becomes zero, it means
712		 * there is no operation pending for the session "X" anymore, so
713		 * we can remove this session. Maybe there is still some
714		 * requests left in the instance's ring
715		 * (icp_adf_queueDataToSend() returns true), but the request
716		 * does not belong to "X", it belongs to session "Y".
717		 */
718		numPendingRequests =
719		    qatUtilsAtomicGet(&(pSessionDesc->u.pendingDpCbCount));
720	} else {
721		numPendingRequests =
722		    qatUtilsAtomicGet(&(pSessionDesc->u.pendingCbCount));
723	}
724
725	/* If there are pending requests */
726	if (0 != numPendingRequests) {
727		QAT_UTILS_LOG("There are %llu requests pending\n",
728			      (unsigned long long)numPendingRequests);
729		status = CPA_STATUS_RETRY;
730		if (CPA_TRUE == pSessionDesc->isDPSession) {
731			/* Need to update tail if messages queue on tx hi ring
732			 for data plane api */
733			icp_comms_trans_handle trans_handle =
734			    ((sal_crypto_service_t *)instanceHandle)
735				->trans_handle_sym_tx;
736
737			if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) {
738				/* process the remaining messages in the ring */
739				QAT_UTILS_LOG("Submitting enqueued requests\n");
740				/*
741				 * SalQatMsg_updateQueueTail
742				 */
743				SalQatMsg_updateQueueTail(trans_handle);
744				return status;
745			}
746		}
747	}
748	if (CPA_STATUS_SUCCESS == status) {
749		LAC_SPINLOCK_DESTROY(&pSessionDesc->requestQueueLock);
750		if (CPA_FALSE == pSessionDesc->isDPSession) {
751			LAC_SYM_STAT_INC(numSessionsRemoved, instanceHandle);
752		}
753	} else if (CPA_FALSE == pSessionDesc->isDPSession) {
754		LAC_SYM_STAT_INC(numSessionErrors, instanceHandle);
755	}
756	return status;
757}
758
759/** @ingroup LacSym */
760static CpaStatus
761LacSym_Perform(const CpaInstanceHandle instanceHandle,
762	       void *callbackTag,
763	       const CpaCySymOpData *pOpData,
764	       const CpaBufferList *pSrcBuffer,
765	       CpaBufferList *pDstBuffer,
766	       CpaBoolean *pVerifyResult,
767	       CpaBoolean isAsyncMode)
768{
769	lac_session_desc_t *pSessionDesc = NULL;
770	CpaStatus status = CPA_STATUS_SUCCESS;
771
772	LAC_CHECK_INSTANCE_HANDLE(instanceHandle);
773	SAL_CHECK_INSTANCE_TYPE(instanceHandle,
774				(SAL_SERVICE_TYPE_CRYPTO |
775				 SAL_SERVICE_TYPE_CRYPTO_SYM));
776	/* check crypto service is running otherwise return an error */
777	SAL_RUNNING_CHECK(instanceHandle);
778	LAC_CHECK_NULL_PARAM(pOpData);
779	LAC_CHECK_NULL_PARAM(pOpData->sessionCtx);
780	LAC_CHECK_NULL_PARAM(pSrcBuffer);
781	LAC_CHECK_NULL_PARAM(pDstBuffer);
782
783	pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pOpData->sessionCtx);
784	LAC_CHECK_NULL_PARAM(pSessionDesc);
785
786	/*check whether Payload size is zero for CHACHA-POLY*/
787	if ((CPA_CY_SYM_CIPHER_CHACHA == pSessionDesc->cipherAlgorithm) &&
788	    (CPA_CY_SYM_HASH_POLY == pSessionDesc->hashAlgorithm) &&
789	    (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionDesc->symOperation)) {
790		if (!pOpData->messageLenToCipherInBytes) {
791			LAC_INVALID_PARAM_LOG(
792			    "Invalid messageLenToCipherInBytes for CHACHA-POLY");
793			return CPA_STATUS_INVALID_PARAM;
794		}
795	}
796
797
798	/* If synchronous Operation - Callback function stored in the session
799	 * descriptor so a flag is set in the perform to indicate that
800	 * the perform is being re-called for the synchronous operation */
801	if ((LacSync_GenBufListVerifyCb == pSessionDesc->pSymCb) &&
802	    isAsyncMode == CPA_TRUE) {
803		CpaBoolean opResult = CPA_FALSE;
804		lac_sync_op_data_t *pSyncCallbackData = NULL;
805
806		status = LacSync_CreateSyncCookie(&pSyncCallbackData);
807
808		if (CPA_STATUS_SUCCESS == status) {
809			status = LacSym_Perform(instanceHandle,
810						pSyncCallbackData,
811						pOpData,
812						pSrcBuffer,
813						pDstBuffer,
814						pVerifyResult,
815						CPA_FALSE);
816		} else {
817			/* Failure allocating sync cookie */
818			LAC_SYM_STAT_INC(numSymOpRequestErrors, instanceHandle);
819			return status;
820		}
821
822		if (CPA_STATUS_SUCCESS == status) {
823			CpaStatus syncStatus = CPA_STATUS_SUCCESS;
824			syncStatus = LacSync_WaitForCallback(
825			    pSyncCallbackData,
826			    LAC_SYM_SYNC_CALLBACK_TIMEOUT,
827			    &status,
828			    &opResult);
829			/* If callback doesn't come back */
830			if (CPA_STATUS_SUCCESS != syncStatus) {
831				LAC_SYM_STAT_INC(numSymOpCompletedErrors,
832						 instanceHandle);
833				LAC_LOG_ERROR("Callback timed out");
834				status = syncStatus;
835			}
836		} else {
837			/* As the Request was not sent the Callback will never
838			 * be called, so need to indicate that we're finished
839			 * with cookie so it can be destroyed. */
840			LacSync_SetSyncCookieComplete(pSyncCallbackData);
841		}
842
843		if (CPA_STATUS_SUCCESS == status) {
844			if (NULL != pVerifyResult) {
845				*pVerifyResult = opResult;
846			}
847		}
848
849		LacSync_DestroySyncCookie(&pSyncCallbackData);
850		return status;
851	}
852
853	status =
854	    LacSymPerform_BufferParamCheck((const CpaBufferList *)pSrcBuffer,
855					   pDstBuffer,
856					   pSessionDesc,
857					   pOpData);
858	LAC_CHECK_STATUS(status);
859
860	if ((!pSessionDesc->digestIsAppended) &&
861	    (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionDesc->symOperation)) {
862		/* Check that pDigestResult is not NULL */
863		LAC_CHECK_NULL_PARAM(pOpData->pDigestResult);
864	}
865
866	status = LacAlgChain_Perform(instanceHandle,
867				     pSessionDesc,
868				     callbackTag,
869				     pOpData,
870				     pSrcBuffer,
871				     pDstBuffer,
872				     pVerifyResult);
873
874	if (CPA_STATUS_SUCCESS == status) {
875		/* check for partial packet suport for the session operation */
876		if (CPA_CY_SYM_PACKET_TYPE_FULL != pOpData->packetType) {
877			LacSym_PartialPacketStateUpdate(
878			    pOpData->packetType, &pSessionDesc->partialState);
879		}
880		/* increment #requests stat */
881		LAC_SYM_STAT_INC(numSymOpRequests, instanceHandle);
882	}
883	/* Retry also results in the errors stat been incremented */
884	else {
885		/* increment #errors stat */
886		LAC_SYM_STAT_INC(numSymOpRequestErrors, instanceHandle);
887	}
888	return status;
889}
890
891/** @ingroup LacSym */
892CpaStatus
893cpaCySymPerformOp(const CpaInstanceHandle instanceHandle_in,
894		  void *callbackTag,
895		  const CpaCySymOpData *pOpData,
896		  const CpaBufferList *pSrcBuffer,
897		  CpaBufferList *pDstBuffer,
898		  CpaBoolean *pVerifyResult)
899{
900	CpaInstanceHandle instanceHandle = NULL;
901
902	if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
903		instanceHandle =
904		    Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM);
905	} else {
906		instanceHandle = instanceHandle_in;
907	}
908
909	return LacSym_Perform(instanceHandle,
910			      callbackTag,
911			      pOpData,
912			      pSrcBuffer,
913			      pDstBuffer,
914			      pVerifyResult,
915			      CPA_TRUE);
916}
917
918/** @ingroup LacSym */
919CpaStatus
920cpaCySymQueryStats(const CpaInstanceHandle instanceHandle_in,
921		   struct _CpaCySymStats *pSymStats)
922{
923
924	CpaInstanceHandle instanceHandle = NULL;
925
926
927	if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
928		instanceHandle =
929		    Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM);
930	} else {
931		instanceHandle = instanceHandle_in;
932	}
933
934	LAC_CHECK_INSTANCE_HANDLE(instanceHandle);
935	SAL_CHECK_INSTANCE_TYPE(instanceHandle,
936				(SAL_SERVICE_TYPE_CRYPTO |
937				 SAL_SERVICE_TYPE_CRYPTO_SYM));
938	LAC_CHECK_NULL_PARAM(pSymStats);
939
940	/* check if crypto service is running
941	 * otherwise return an error */
942	SAL_RUNNING_CHECK(instanceHandle);
943
944	/* copy the fields from the internal structure into the api defined
945	 * structure */
946	LacSym_Stats32CopyGet(instanceHandle, pSymStats);
947	return CPA_STATUS_SUCCESS;
948}
949
950/** @ingroup LacSym */
951CpaStatus
952cpaCySymQueryStats64(const CpaInstanceHandle instanceHandle_in,
953		     CpaCySymStats64 *pSymStats)
954{
955
956	CpaInstanceHandle instanceHandle = NULL;
957
958
959	if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
960		instanceHandle =
961		    Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM);
962	} else {
963		instanceHandle = instanceHandle_in;
964	}
965
966	LAC_CHECK_INSTANCE_HANDLE(instanceHandle);
967	SAL_CHECK_INSTANCE_TYPE(instanceHandle,
968				(SAL_SERVICE_TYPE_CRYPTO |
969				 SAL_SERVICE_TYPE_CRYPTO_SYM));
970	LAC_CHECK_NULL_PARAM(pSymStats);
971
972	/* check if crypto service is running
973	 * otherwise return an error */
974	SAL_RUNNING_CHECK(instanceHandle);
975
976	/* copy the fields from the internal structure into the api defined
977	 * structure */
978	LacSym_Stats64CopyGet(instanceHandle, pSymStats);
979
980	return CPA_STATUS_SUCCESS;
981}
982
983/** @ingroup LacSym */
984CpaStatus
985cpaCySymSessionCtxGetSize(const CpaInstanceHandle instanceHandle_in,
986			  const CpaCySymSessionSetupData *pSessionSetupData,
987			  Cpa32U *pSessionCtxSizeInBytes)
988{
989	CpaInstanceHandle instanceHandle = NULL;
990
991	if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
992		instanceHandle =
993		    Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM);
994	} else {
995		instanceHandle = instanceHandle_in;
996	}
997
998	LAC_CHECK_INSTANCE_HANDLE(instanceHandle);
999	SAL_CHECK_INSTANCE_TYPE(instanceHandle,
1000				(SAL_SERVICE_TYPE_CRYPTO |
1001				 SAL_SERVICE_TYPE_CRYPTO_SYM));
1002	LAC_CHECK_NULL_PARAM(pSessionSetupData);
1003	LAC_CHECK_NULL_PARAM(pSessionCtxSizeInBytes);
1004
1005	/* check crypto service is running otherwise return an error */
1006	SAL_RUNNING_CHECK(instanceHandle);
1007	*pSessionCtxSizeInBytes = LAC_SYM_SESSION_SIZE;
1008
1009	return CPA_STATUS_SUCCESS;
1010}
1011
1012/** @ingroup LacSym */
1013CpaStatus
1014cpaCySymSessionCtxGetDynamicSize(
1015    const CpaInstanceHandle instanceHandle_in,
1016    const CpaCySymSessionSetupData *pSessionSetupData,
1017    Cpa32U *pSessionCtxSizeInBytes)
1018{
1019	CpaInstanceHandle instanceHandle = NULL;
1020
1021	if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
1022		instanceHandle =
1023		    Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM);
1024	} else {
1025		instanceHandle = instanceHandle_in;
1026	}
1027
1028	LAC_CHECK_INSTANCE_HANDLE(instanceHandle);
1029	SAL_CHECK_INSTANCE_TYPE(instanceHandle,
1030				(SAL_SERVICE_TYPE_CRYPTO |
1031				 SAL_SERVICE_TYPE_CRYPTO_SYM));
1032	LAC_CHECK_NULL_PARAM(pSessionSetupData);
1033	LAC_CHECK_NULL_PARAM(pSessionCtxSizeInBytes);
1034
1035	/* check crypto service is running otherwise return an error */
1036	SAL_RUNNING_CHECK(instanceHandle);
1037	/* Choose Session Context size */
1038	getCtxSize(pSessionSetupData, pSessionCtxSizeInBytes);
1039
1040
1041	return CPA_STATUS_SUCCESS;
1042}
1043
1044void
1045getCtxSize(const CpaCySymSessionSetupData *pSessionSetupData,
1046	   Cpa32U *pSessionCtxSizeInBytes)
1047{
1048	/* using lac_session_desc_d1_t */
1049	if ((pSessionSetupData->cipherSetupData.cipherAlgorithm !=
1050	     CPA_CY_SYM_CIPHER_ARC4) &&
1051	    (pSessionSetupData->cipherSetupData.cipherAlgorithm !=
1052	     CPA_CY_SYM_CIPHER_SNOW3G_UEA2) &&
1053	    (pSessionSetupData->hashSetupData.hashAlgorithm !=
1054	     CPA_CY_SYM_HASH_SNOW3G_UIA2) &&
1055	    (pSessionSetupData->cipherSetupData.cipherAlgorithm !=
1056	     CPA_CY_SYM_CIPHER_AES_CCM) &&
1057	    (pSessionSetupData->cipherSetupData.cipherAlgorithm !=
1058	     CPA_CY_SYM_CIPHER_AES_GCM) &&
1059	    (pSessionSetupData->hashSetupData.hashMode !=
1060	     CPA_CY_SYM_HASH_MODE_AUTH) &&
1061	    (pSessionSetupData->hashSetupData.hashMode !=
1062	     CPA_CY_SYM_HASH_MODE_NESTED) &&
1063	    (pSessionSetupData->partialsNotRequired == CPA_TRUE)) {
1064		*pSessionCtxSizeInBytes = LAC_SYM_SESSION_D1_SIZE;
1065	}
1066	/* using lac_session_desc_d2_t */
1067	else if (((pSessionSetupData->cipherSetupData.cipherAlgorithm ==
1068		   CPA_CY_SYM_CIPHER_AES_CCM) ||
1069		  (pSessionSetupData->cipherSetupData.cipherAlgorithm ==
1070		   CPA_CY_SYM_CIPHER_AES_GCM)) &&
1071		 (pSessionSetupData->partialsNotRequired == CPA_TRUE)) {
1072		*pSessionCtxSizeInBytes = LAC_SYM_SESSION_D2_SIZE;
1073	}
1074	/* using lac_session_desc_t */
1075	else {
1076		*pSessionCtxSizeInBytes = LAC_SYM_SESSION_SIZE;
1077	}
1078}
1079
1080/**
1081 ******************************************************************************
1082 * @ingroup LacSym
1083 *****************************************************************************/
1084CpaStatus
1085cpaCyBufferListGetMetaSize(const CpaInstanceHandle instanceHandle_in,
1086			   Cpa32U numBuffers,
1087			   Cpa32U *pSizeInBytes)
1088{
1089
1090	CpaInstanceHandle instanceHandle = NULL;
1091
1092	if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
1093		instanceHandle =
1094		    Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM);
1095	} else {
1096		instanceHandle = instanceHandle_in;
1097	}
1098	LAC_CHECK_INSTANCE_HANDLE(instanceHandle);
1099	SAL_CHECK_INSTANCE_TYPE(instanceHandle,
1100				(SAL_SERVICE_TYPE_CRYPTO |
1101				 SAL_SERVICE_TYPE_CRYPTO_SYM));
1102	LAC_CHECK_NULL_PARAM(pSizeInBytes);
1103
1104	/* In the case of zero buffers we still need to allocate one
1105	 * descriptor to pass to the firmware */
1106	if (0 == numBuffers) {
1107		numBuffers = 1;
1108	}
1109
1110	/* Note: icp_buffer_list_desc_t is 8 bytes in size and
1111	 * icp_flat_buffer_desc_t is 16 bytes in size. Therefore if
1112	 * icp_buffer_list_desc_t is aligned
1113	 * so will each icp_flat_buffer_desc_t structure */
1114
1115	*pSizeInBytes = sizeof(icp_buffer_list_desc_t) +
1116	    (sizeof(icp_flat_buffer_desc_t) * numBuffers) +
1117	    ICP_DESCRIPTOR_ALIGNMENT_BYTES;
1118
1119
1120	return CPA_STATUS_SUCCESS;
1121}
1122