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