1/* SPDX-License-Identifier: BSD-3-Clause */
2/* Copyright(c) 2007-2022 Intel Corporation */
3
4/**
5 ***************************************************************************
6 * @file lac_sym_hash.c
7 *
8 * @ingroup LacHash
9 *
10 * Hash specific functionality
11 ***************************************************************************/
12
13/*
14*******************************************************************************
15* Include public/global header files
16*******************************************************************************
17*/
18
19#include "cpa.h"
20#include "cpa_cy_sym.h"
21
22#include "icp_accel_devices.h"
23#include "icp_adf_debug.h"
24
25/*
26*******************************************************************************
27* Include private header files
28*******************************************************************************
29*/
30
31#include "lac_common.h"
32#include "lac_mem.h"
33#include "lac_sym.h"
34#include "lac_session.h"
35#include "lac_sym_hash.h"
36#include "lac_log.h"
37#include "lac_sym_qat_hash.h"
38#include "lac_sym_qat_hash_defs_lookup.h"
39#include "lac_sym_cb.h"
40#include "lac_sync.h"
41
42#define LAC_HASH_ALG_MODE_NOT_SUPPORTED(alg, mode)                             \
43	((((CPA_CY_SYM_HASH_KASUMI_F9 == (alg)) ||                             \
44	   (CPA_CY_SYM_HASH_SNOW3G_UIA2 == (alg)) ||                           \
45	   (CPA_CY_SYM_HASH_AES_XCBC == (alg)) ||                              \
46	   (CPA_CY_SYM_HASH_AES_CCM == (alg)) ||                               \
47	   (CPA_CY_SYM_HASH_AES_GCM == (alg)) ||                               \
48	   (CPA_CY_SYM_HASH_AES_GMAC == (alg)) ||                              \
49	   (CPA_CY_SYM_HASH_AES_CMAC == (alg)) ||                              \
50	   (CPA_CY_SYM_HASH_ZUC_EIA3 == (alg))) &&                             \
51	  (CPA_CY_SYM_HASH_MODE_AUTH != (mode))) ||                            \
52	 ((LAC_HASH_IS_SHA3(alg)) && (CPA_CY_SYM_HASH_MODE_NESTED == (mode))))
53/**< Macro to check for valid algorithm-mode combination */
54
55void LacSync_GenBufListVerifyCb(void *pCallbackTag,
56				CpaStatus status,
57				CpaCySymOp operationType,
58				void *pOpData,
59				CpaBufferList *pDstBuffer,
60				CpaBoolean opResult);
61
62/**
63 * @ingroup LacHash
64 * This callback function will be invoked whenever a synchronous
65 * hash precompute operation completes.  It will set the wait
66 * queue flag for the synchronous operation.
67 *
68 * @param[in] pCallbackTag  Opaque value provided by user. This will
69 *                         be a pointer to a wait queue flag.
70 *
71 * @retval
72 *     None
73 *
74 */
75static void
76LacHash_SyncPrecomputeDoneCb(void *pCallbackTag)
77{
78	LacSync_GenWakeupSyncCaller(pCallbackTag, CPA_STATUS_SUCCESS);
79}
80
81/** @ingroup LacHash */
82CpaStatus
83LacHash_StatePrefixAadBufferInit(
84    sal_service_t *pService,
85    const CpaCySymHashSetupData *pHashSetupData,
86    icp_qat_la_bulk_req_ftr_t *pReq,
87    icp_qat_hw_auth_mode_t qatHashMode,
88    Cpa8U *pHashStateBuffer,
89    lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo)
90{
91	/* set up the hash state prefix buffer info structure */
92	pHashStateBufferInfo->pData = pHashStateBuffer;
93
94	pHashStateBufferInfo->pDataPhys = LAC_MEM_CAST_PTR_TO_UINT64(
95	    LAC_OS_VIRT_TO_PHYS_EXTERNAL((*pService), pHashStateBuffer));
96
97	if (pHashStateBufferInfo->pDataPhys == 0) {
98		LAC_LOG_ERROR("Unable to get the physical address of "
99			      "the hash state buffer\n");
100		return CPA_STATUS_FAIL;
101	}
102
103	LacSymQat_HashStatePrefixAadBufferSizeGet(pReq, pHashStateBufferInfo);
104
105	/* Prefix data gets copied to the hash state buffer for nested mode */
106	if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) {
107		LacSymQat_HashStatePrefixAadBufferPopulate(
108		    pHashStateBufferInfo,
109		    pReq,
110		    pHashSetupData->nestedModeSetupData.pInnerPrefixData,
111		    (Cpa8U)pHashSetupData->nestedModeSetupData
112			.innerPrefixLenInBytes,
113		    pHashSetupData->nestedModeSetupData.pOuterPrefixData,
114		    (Cpa8U)pHashSetupData->nestedModeSetupData
115			.outerPrefixLenInBytes);
116	}
117	/* For mode2 HMAC the key gets copied into both the inner and
118	 * outer prefix fields */
119	else if (IS_HASH_MODE_2_AUTH(qatHashMode, pHashSetupData->hashMode)) {
120		LacSymQat_HashStatePrefixAadBufferPopulate(
121		    pHashStateBufferInfo,
122		    pReq,
123		    pHashSetupData->authModeSetupData.authKey,
124		    (Cpa8U)pHashSetupData->authModeSetupData.authKeyLenInBytes,
125		    pHashSetupData->authModeSetupData.authKey,
126		    (Cpa8U)pHashSetupData->authModeSetupData.authKeyLenInBytes);
127	}
128	/* else do nothing for the other cases */
129	return CPA_STATUS_SUCCESS;
130}
131
132/** @ingroup LacHash */
133CpaStatus
134LacHash_PrecomputeDataCreate(const CpaInstanceHandle instanceHandle,
135			     CpaCySymSessionSetupData *pSessionSetup,
136			     lac_hash_precompute_done_cb_t callbackFn,
137			     void *pCallbackTag,
138			     Cpa8U *pWorkingBuffer,
139			     Cpa8U *pState1,
140			     Cpa8U *pState2)
141{
142	CpaStatus status = CPA_STATUS_SUCCESS;
143	Cpa8U *pAuthKey = NULL;
144	Cpa32U authKeyLenInBytes = 0;
145	CpaCySymHashAlgorithm hashAlgorithm =
146	    pSessionSetup->hashSetupData.hashAlgorithm;
147	CpaCySymHashAuthModeSetupData *pAuthModeSetupData =
148	    &pSessionSetup->hashSetupData.authModeSetupData;
149
150	/* synchronous operation */
151	if (NULL == callbackFn) {
152		lac_sync_op_data_t *pSyncCallbackData = NULL;
153
154		status = LacSync_CreateSyncCookie(&pSyncCallbackData);
155
156		if (CPA_STATUS_SUCCESS == status) {
157			status = LacHash_PrecomputeDataCreate(
158			    instanceHandle,
159			    pSessionSetup,
160			    LacHash_SyncPrecomputeDoneCb,
161			    /* wait queue condition from sync cookie */
162			    pSyncCallbackData,
163			    pWorkingBuffer,
164			    pState1,
165			    pState2);
166		} else {
167			return status;
168		}
169
170		if (CPA_STATUS_SUCCESS == status) {
171			CpaStatus syncStatus = CPA_STATUS_SUCCESS;
172
173			syncStatus = LacSync_WaitForCallback(
174			    pSyncCallbackData,
175			    LAC_SYM_SYNC_CALLBACK_TIMEOUT,
176			    &status,
177			    NULL);
178
179			/* If callback doesn't come back */
180			if (CPA_STATUS_SUCCESS != syncStatus) {
181				QAT_UTILS_LOG(
182				    "callback functions for precomputes did not return\n");
183				status = syncStatus;
184			}
185		} else {
186			/* As the Request was not sent the Callback will never
187			 * be called, so need to indicate that we're finished
188			 * with cookie so it can be destroyed. */
189			LacSync_SetSyncCookieComplete(pSyncCallbackData);
190		}
191		LacSync_DestroySyncCookie(&pSyncCallbackData);
192
193		return status;
194	}
195
196	/* set up convenience pointers */
197	pAuthKey = pAuthModeSetupData->authKey;
198	authKeyLenInBytes = pAuthModeSetupData->authKeyLenInBytes;
199
200	/* Pre-compute data state pointers must already be set up
201	 * by LacSymQat_HashSetupBlockInit()
202	 */
203
204	/* state1 is not allocated for AES XCBC/CCM/GCM/Kasumi/UIA2
205	 * so for these algorithms set state2 only */
206	if (CPA_CY_SYM_HASH_AES_XCBC == hashAlgorithm) {
207		status = LacSymHash_AesECBPreCompute(instanceHandle,
208						     hashAlgorithm,
209						     authKeyLenInBytes,
210						     pAuthKey,
211						     pWorkingBuffer,
212						     pState2,
213						     callbackFn,
214						     pCallbackTag);
215	} else if (CPA_CY_SYM_HASH_AES_CMAC == hashAlgorithm) {
216		/* First, copy the original key to pState2 */
217		memcpy(pState2, pAuthKey, authKeyLenInBytes);
218		/* Then precompute */
219		status = LacSymHash_AesECBPreCompute(instanceHandle,
220						     hashAlgorithm,
221						     authKeyLenInBytes,
222						     pAuthKey,
223						     pWorkingBuffer,
224						     pState2,
225						     callbackFn,
226						     pCallbackTag);
227	} else if (CPA_CY_SYM_HASH_AES_CCM == hashAlgorithm) {
228		/*
229		 * The Inner Hash Initial State2 block is 32 bytes long.
230		 * Therefore, for keys bigger than 128 bits (16 bytes),
231		 * there is no space for 16 zeroes.
232		 */
233		if (pSessionSetup->cipherSetupData.cipherKeyLenInBytes ==
234		    ICP_QAT_HW_AES_128_KEY_SZ) {
235			/*
236			 * The Inner Hash Initial State2 block must contain K
237			 * (the cipher key) and 16 zeroes which will be replaced
238			 * with EK(Ctr0) by the QAT-ME.
239			 */
240
241			/* write the auth key which for CCM is equivalent to
242			 * cipher key
243			 */
244			memcpy(
245			    pState2,
246			    pSessionSetup->cipherSetupData.pCipherKey,
247			    pSessionSetup->cipherSetupData.cipherKeyLenInBytes);
248
249			/* initialize remaining buffer space to all zeroes */
250			LAC_OS_BZERO(pState2 +
251					 pSessionSetup->cipherSetupData
252					     .cipherKeyLenInBytes,
253				     ICP_QAT_HW_AES_CCM_CBC_E_CTR0_SZ);
254		}
255
256		/* There is no request sent to the QAT for this operation,
257		 * so just invoke the user's callback directly to signal
258		 * completion of the precompute
259		 */
260		callbackFn(pCallbackTag);
261	} else if (CPA_CY_SYM_HASH_AES_GCM == hashAlgorithm ||
262		   CPA_CY_SYM_HASH_AES_GMAC == hashAlgorithm) {
263		/*
264		 * The Inner Hash Initial State2 block contains the following
265		 *      H (the Galois Hash Multiplier)
266		 *      len(A) (the length of A), (length before padding)
267		 *      16 zeroes which will be replaced with EK(Ctr0) by the
268		 * QAT.
269		 */
270
271		/* Memset state2 to 0 */
272		LAC_OS_BZERO(pState2,
273			     ICP_QAT_HW_GALOIS_H_SZ +
274				 ICP_QAT_HW_GALOIS_LEN_A_SZ +
275				 ICP_QAT_HW_GALOIS_E_CTR0_SZ);
276
277		/* write H (the Galois Hash Multiplier) where H = E(K, 0...0)
278		 * This will only write bytes 0-15 of pState2
279		 */
280		status = LacSymHash_AesECBPreCompute(
281		    instanceHandle,
282		    hashAlgorithm,
283		    pSessionSetup->cipherSetupData.cipherKeyLenInBytes,
284		    pSessionSetup->cipherSetupData.pCipherKey,
285		    pWorkingBuffer,
286		    pState2,
287		    callbackFn,
288		    pCallbackTag);
289
290		if (CPA_STATUS_SUCCESS == status) {
291			/* write len(A) (the length of A) into bytes 16-19 of
292			 * pState2 in big-endian format. This field is 8 bytes
293			 */
294			*(Cpa32U *)&pState2[ICP_QAT_HW_GALOIS_H_SZ] =
295			    LAC_MEM_WR_32(pAuthModeSetupData->aadLenInBytes);
296		}
297	} else if (CPA_CY_SYM_HASH_KASUMI_F9 == hashAlgorithm) {
298		Cpa32U wordIndex = 0;
299		Cpa32U *pTempKey = (Cpa32U *)(pState2 + authKeyLenInBytes);
300		/*
301		 * The Inner Hash Initial State2 block must contain IK
302		 * (Initialisation Key), followed by IK XOR-ed with KM
303		 * (Key Modifier): IK||(IK^KM).
304		 */
305
306		/* write the auth key */
307		memcpy(pState2, pAuthKey, authKeyLenInBytes);
308		/* initialise temp key with auth key */
309		memcpy(pTempKey, pAuthKey, authKeyLenInBytes);
310
311		/* XOR Key with KASUMI F9 key modifier at 4 bytes level */
312		for (wordIndex = 0;
313		     wordIndex < LAC_BYTES_TO_LONGWORDS(authKeyLenInBytes);
314		     wordIndex++) {
315			pTempKey[wordIndex] ^=
316			    LAC_HASH_KASUMI_F9_KEY_MODIFIER_4_BYTES;
317		}
318		/* There is no request sent to the QAT for this operation,
319		 * so just invoke the user's callback directly to signal
320		 * completion of the precompute
321		 */
322		callbackFn(pCallbackTag);
323	} else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == hashAlgorithm) {
324		/*
325		 * The Inner Hash Initial State2 should be all zeros
326		 */
327		LAC_OS_BZERO(pState2, ICP_QAT_HW_SNOW_3G_UIA2_STATE2_SZ);
328
329		/* There is no request sent to the QAT for this operation,
330		 * so just invoke the user's callback directly to signal
331		 * completion of the precompute
332		 */
333		callbackFn(pCallbackTag);
334	} else if (CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlgorithm) {
335		/*
336		 * The Inner Hash Initial State2 should contain the key
337		 * and zero the rest of the state.
338		 */
339		LAC_OS_BZERO(pState2, ICP_QAT_HW_ZUC_3G_EIA3_STATE2_SZ);
340		memcpy(pState2, pAuthKey, authKeyLenInBytes);
341
342		/* There is no request sent to the QAT for this operation,
343		 * so just invoke the user's callback directly to signal
344		 * completion of the precompute
345		 */
346		callbackFn(pCallbackTag);
347	} else if (CPA_CY_SYM_HASH_POLY == hashAlgorithm) {
348		/* There is no request sent to the QAT for this operation,
349		 * so just invoke the user's callback directly to signal
350		 * completion of the precompute
351		 */
352		callbackFn(pCallbackTag);
353	} else /* For Hmac Precomputes */
354	{
355		status = LacSymHash_HmacPreComputes(instanceHandle,
356						    hashAlgorithm,
357						    authKeyLenInBytes,
358						    pAuthKey,
359						    pWorkingBuffer,
360						    pState1,
361						    pState2,
362						    callbackFn,
363						    pCallbackTag);
364	}
365
366	return status;
367}
368
369
370/** @ingroup LacHash */
371CpaStatus
372LacHash_HashContextCheck(CpaInstanceHandle instanceHandle,
373			 const CpaCySymHashSetupData *pHashSetupData)
374{
375	lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL;
376	lac_sym_qat_hash_alg_info_t *pOuterHashAlgInfo = NULL;
377	CpaCySymCapabilitiesInfo capInfo;
378
379	/*Protect against value of hash outside the bitmap*/
380	if (pHashSetupData->hashAlgorithm >= CPA_CY_SYM_HASH_CAP_BITMAP_SIZE) {
381		LAC_INVALID_PARAM_LOG("hashAlgorithm");
382		return CPA_STATUS_INVALID_PARAM;
383	}
384
385	cpaCySymQueryCapabilities(instanceHandle, &capInfo);
386	if (!CPA_BITMAP_BIT_TEST(capInfo.hashes,
387				 pHashSetupData->hashAlgorithm) &&
388	    pHashSetupData->hashAlgorithm != CPA_CY_SYM_HASH_AES_CBC_MAC) {
389		LAC_INVALID_PARAM_LOG("hashAlgorithm");
390		return CPA_STATUS_INVALID_PARAM;
391	}
392
393	switch (pHashSetupData->hashMode) {
394	case CPA_CY_SYM_HASH_MODE_PLAIN:
395	case CPA_CY_SYM_HASH_MODE_AUTH:
396	case CPA_CY_SYM_HASH_MODE_NESTED:
397		break;
398
399	default: {
400		LAC_INVALID_PARAM_LOG("hashMode");
401		return CPA_STATUS_INVALID_PARAM;
402	}
403	}
404
405	if (LAC_HASH_ALG_MODE_NOT_SUPPORTED(pHashSetupData->hashAlgorithm,
406					    pHashSetupData->hashMode)) {
407		LAC_UNSUPPORTED_PARAM_LOG(
408		    "hashAlgorithm and hashMode combination");
409		return CPA_STATUS_UNSUPPORTED;
410	}
411
412	LacSymQat_HashAlgLookupGet(instanceHandle,
413				   pHashSetupData->hashAlgorithm,
414				   &pHashAlgInfo);
415
416	/* note: nested hash mode checks digest length against outer algorithm
417	 */
418	if ((CPA_CY_SYM_HASH_MODE_PLAIN == pHashSetupData->hashMode) ||
419	    (CPA_CY_SYM_HASH_MODE_AUTH == pHashSetupData->hashMode)) {
420		/* Check Digest Length is permitted by the algorithm  */
421		if ((0 == pHashSetupData->digestResultLenInBytes) ||
422		    (pHashSetupData->digestResultLenInBytes >
423		     pHashAlgInfo->digestLength)) {
424			LAC_INVALID_PARAM_LOG("digestResultLenInBytes");
425			return CPA_STATUS_INVALID_PARAM;
426		}
427	}
428
429	if (CPA_CY_SYM_HASH_MODE_AUTH == pHashSetupData->hashMode) {
430		if (CPA_CY_SYM_HASH_AES_GCM == pHashSetupData->hashAlgorithm ||
431		    CPA_CY_SYM_HASH_AES_GMAC == pHashSetupData->hashAlgorithm) {
432			Cpa32U aadDataSize = 0;
433
434			/* RFC 4106: Implementations MUST support a full-length
435			 * 16-octet ICV, and MAY support 8 or 12 octet ICVs, and
436			 * MUST NOT support other ICV lengths. */
437			if ((pHashSetupData->digestResultLenInBytes !=
438			     LAC_HASH_AES_GCM_ICV_SIZE_8) &&
439			    (pHashSetupData->digestResultLenInBytes !=
440			     LAC_HASH_AES_GCM_ICV_SIZE_12) &&
441			    (pHashSetupData->digestResultLenInBytes !=
442			     LAC_HASH_AES_GCM_ICV_SIZE_16)) {
443				LAC_INVALID_PARAM_LOG("digestResultLenInBytes");
444				return CPA_STATUS_INVALID_PARAM;
445			}
446
447			/* ensure aadLen is within maximum limit imposed by QAT
448			 */
449			aadDataSize =
450			    pHashSetupData->authModeSetupData.aadLenInBytes;
451
452			/* round the aad size to the multiple of GCM hash block
453			 * size. */
454			aadDataSize =
455			    LAC_ALIGN_POW2_ROUNDUP(aadDataSize,
456						   LAC_HASH_AES_GCM_BLOCK_SIZE);
457
458			if (aadDataSize > ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX &&
459			    CPA_CY_SYM_HASH_AES_GMAC !=
460				pHashSetupData->hashAlgorithm) {
461				LAC_INVALID_PARAM_LOG("aadLenInBytes");
462				return CPA_STATUS_INVALID_PARAM;
463			}
464		} else if (CPA_CY_SYM_HASH_AES_CCM ==
465			   pHashSetupData->hashAlgorithm) {
466			Cpa32U aadDataSize = 0;
467
468			/* RFC 3610: Valid values are 4, 6, 8, 10, 12, 14, and
469			 * 16 octets */
470			if ((pHashSetupData->digestResultLenInBytes >=
471			     LAC_HASH_AES_CCM_ICV_SIZE_MIN) &&
472			    (pHashSetupData->digestResultLenInBytes <=
473			     LAC_HASH_AES_CCM_ICV_SIZE_MAX)) {
474				if ((pHashSetupData->digestResultLenInBytes &
475				     0x01) != 0) {
476					LAC_INVALID_PARAM_LOG(
477					    "digestResultLenInBytes must be a multiple of 2");
478					return CPA_STATUS_INVALID_PARAM;
479				}
480			} else {
481				LAC_INVALID_PARAM_LOG("digestResultLenInBytes");
482				return CPA_STATUS_INVALID_PARAM;
483			}
484
485			/* ensure aadLen is within maximum limit imposed by QAT
486			 */
487			/* at the beginning of the buffer there is B0 block */
488			aadDataSize = LAC_HASH_AES_CCM_BLOCK_SIZE;
489
490			/* then, if there is some 'a' data, the buffer will
491			 * store encoded length of 'a' and 'a' itself */
492			if (pHashSetupData->authModeSetupData.aadLenInBytes >
493			    0) {
494				/* as the QAT API puts the requirement on the
495				 * pAdditionalAuthData not to be bigger than 240
496				 * bytes then we just need 2 bytes to store
497				 * encoded length of 'a' */
498				aadDataSize += sizeof(Cpa16U);
499				aadDataSize += pHashSetupData->authModeSetupData
500						   .aadLenInBytes;
501			}
502
503			/* round the aad size to the multiple of CCM block
504			 * size.*/
505			aadDataSize =
506			    LAC_ALIGN_POW2_ROUNDUP(aadDataSize,
507						   LAC_HASH_AES_CCM_BLOCK_SIZE);
508			if (aadDataSize > ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX) {
509				LAC_INVALID_PARAM_LOG("aadLenInBytes");
510				return CPA_STATUS_INVALID_PARAM;
511			}
512		} else if (CPA_CY_SYM_HASH_KASUMI_F9 ==
513			   pHashSetupData->hashAlgorithm) {
514			/* QAT-FW only supports 128 bit Integrity Key size for
515			 * Kasumi f9
516			 *  Ref: 3GPP TS 35.201 version 7.0.0 Release 7 */
517			if (pHashSetupData->authModeSetupData
518				.authKeyLenInBytes !=
519			    ICP_QAT_HW_KASUMI_KEY_SZ) {
520				LAC_INVALID_PARAM_LOG("authKeyLenInBytes");
521				return CPA_STATUS_INVALID_PARAM;
522			}
523		} else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 ==
524			   pHashSetupData->hashAlgorithm) {
525
526			/* QAT-FW only supports 128 bits Integrity Key size for
527			 * Snow3g */
528			if (pHashSetupData->authModeSetupData
529				.authKeyLenInBytes !=
530			    ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ) {
531				LAC_INVALID_PARAM_LOG("authKeyLenInBytes");
532				return CPA_STATUS_INVALID_PARAM;
533			}
534			/* For Snow3g hash aad field contains IV - it needs to
535			 * be 16 bytes long
536			 */
537			if (pHashSetupData->authModeSetupData.aadLenInBytes !=
538			    ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ) {
539				LAC_INVALID_PARAM_LOG("aadLenInBytes");
540				return CPA_STATUS_INVALID_PARAM;
541			}
542		} else if (CPA_CY_SYM_HASH_AES_XCBC ==
543			       pHashSetupData->hashAlgorithm ||
544			   CPA_CY_SYM_HASH_AES_CMAC ==
545			       pHashSetupData->hashAlgorithm ||
546			   CPA_CY_SYM_HASH_AES_CBC_MAC ==
547			       pHashSetupData->hashAlgorithm) {
548			/* ensure auth key len is valid (128-bit keys supported)
549			 */
550			if ((pHashSetupData->authModeSetupData
551				 .authKeyLenInBytes !=
552			     ICP_QAT_HW_AES_128_KEY_SZ)) {
553				LAC_INVALID_PARAM_LOG("authKeyLenInBytes");
554				return CPA_STATUS_INVALID_PARAM;
555			}
556		} else if (CPA_CY_SYM_HASH_ZUC_EIA3 ==
557			   pHashSetupData->hashAlgorithm) {
558
559			/* QAT-FW only supports 128 bits Integrity Key size for
560			 * ZUC */
561			if (pHashSetupData->authModeSetupData
562				.authKeyLenInBytes !=
563			    ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ) {
564				LAC_INVALID_PARAM_LOG("authKeyLenInBytes");
565				return CPA_STATUS_INVALID_PARAM;
566			}
567			/* For ZUC EIA3 hash aad field contains IV - it needs to
568			 * be 16 bytes long
569			 */
570			if (pHashSetupData->authModeSetupData.aadLenInBytes !=
571			    ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ) {
572				LAC_INVALID_PARAM_LOG("aadLenInBytes");
573				return CPA_STATUS_INVALID_PARAM;
574			}
575		} else if (CPA_CY_SYM_HASH_POLY ==
576			   pHashSetupData->hashAlgorithm) {
577			if (pHashSetupData->digestResultLenInBytes !=
578			    ICP_QAT_HW_SPC_CTR_SZ) {
579				LAC_INVALID_PARAM_LOG("Digest Length for CCP");
580				return CPA_STATUS_INVALID_PARAM;
581			}
582			if (pHashSetupData->authModeSetupData.aadLenInBytes >
583			    ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX) {
584				LAC_INVALID_PARAM_LOG("AAD Length for CCP");
585				return CPA_STATUS_INVALID_PARAM;
586			}
587		} else {
588			/* The key size must be less than or equal the block
589			 * length */
590			if (pHashSetupData->authModeSetupData
591				.authKeyLenInBytes >
592			    pHashAlgInfo->blockLength) {
593				LAC_INVALID_PARAM_LOG("authKeyLenInBytes");
594				return CPA_STATUS_INVALID_PARAM;
595			}
596		}
597
598		/* when the key size is greater than 0 check pointer is not null
599		 */
600		if (CPA_CY_SYM_HASH_AES_CCM != pHashSetupData->hashAlgorithm &&
601		    CPA_CY_SYM_HASH_AES_GCM != pHashSetupData->hashAlgorithm &&
602		    pHashSetupData->authModeSetupData.authKeyLenInBytes > 0) {
603			LAC_CHECK_NULL_PARAM(
604			    pHashSetupData->authModeSetupData.authKey);
605		}
606	} else if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) {
607		if (!CPA_BITMAP_BIT_TEST(capInfo.hashes,
608					 pHashSetupData->nestedModeSetupData
609					     .outerHashAlgorithm)) {
610			LAC_INVALID_PARAM_LOG("outerHashAlgorithm");
611			return CPA_STATUS_INVALID_PARAM;
612		}
613
614		if (LAC_HASH_ALG_MODE_NOT_SUPPORTED(
615			pHashSetupData->nestedModeSetupData.outerHashAlgorithm,
616			pHashSetupData->hashMode)) {
617			LAC_INVALID_PARAM_LOG(
618			    "outerHashAlgorithm and hashMode combination");
619			return CPA_STATUS_INVALID_PARAM;
620		}
621
622		LacSymQat_HashAlgLookupGet(
623		    instanceHandle,
624		    pHashSetupData->nestedModeSetupData.outerHashAlgorithm,
625		    &pOuterHashAlgInfo);
626
627		/* Check Digest Length is permitted by the algorithm  */
628		if ((0 == pHashSetupData->digestResultLenInBytes) ||
629		    (pHashSetupData->digestResultLenInBytes >
630		     pOuterHashAlgInfo->digestLength)) {
631			LAC_INVALID_PARAM_LOG("digestResultLenInBytes");
632			return CPA_STATUS_INVALID_PARAM;
633		}
634
635		if (pHashSetupData->nestedModeSetupData.innerPrefixLenInBytes >
636		    LAC_MAX_INNER_OUTER_PREFIX_SIZE_BYTES) {
637			LAC_INVALID_PARAM_LOG("innerPrefixLenInBytes");
638			return CPA_STATUS_INVALID_PARAM;
639		}
640
641		if (pHashSetupData->nestedModeSetupData.innerPrefixLenInBytes >
642		    0) {
643			LAC_CHECK_NULL_PARAM(pHashSetupData->nestedModeSetupData
644						 .pInnerPrefixData);
645		}
646
647		if (pHashSetupData->nestedModeSetupData.outerPrefixLenInBytes >
648		    LAC_MAX_INNER_OUTER_PREFIX_SIZE_BYTES) {
649			LAC_INVALID_PARAM_LOG("outerPrefixLenInBytes");
650			return CPA_STATUS_INVALID_PARAM;
651		}
652
653		if (pHashSetupData->nestedModeSetupData.outerPrefixLenInBytes >
654		    0) {
655			LAC_CHECK_NULL_PARAM(pHashSetupData->nestedModeSetupData
656						 .pOuterPrefixData);
657		}
658	}
659
660	return CPA_STATUS_SUCCESS;
661}
662
663/** @ingroup LacHash */
664CpaStatus
665LacHash_PerformParamCheck(CpaInstanceHandle instanceHandle,
666			  lac_session_desc_t *pSessionDesc,
667			  const CpaCySymOpData *pOpData,
668			  Cpa64U srcPktSize,
669			  const CpaBoolean *pVerifyResult)
670{
671	CpaStatus status = CPA_STATUS_SUCCESS;
672	lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL;
673	CpaBoolean digestIsAppended = pSessionDesc->digestIsAppended;
674	CpaBoolean digestVerify = pSessionDesc->digestVerify;
675	CpaCySymOp symOperation = pSessionDesc->symOperation;
676	CpaCySymHashAlgorithm hashAlgorithm = pSessionDesc->hashAlgorithm;
677
678	/* digestVerify and digestIsAppended on Hash-Only operation not
679	 * supported */
680	if (digestIsAppended && digestVerify &&
681	    (CPA_CY_SYM_OP_HASH == symOperation)) {
682		LAC_INVALID_PARAM_LOG(
683		    "digestVerify and digestIsAppended set "
684		    "on Hash-Only operation is not supported");
685		return CPA_STATUS_INVALID_PARAM;
686	}
687
688	/* check the digest result pointer */
689	if ((CPA_CY_SYM_PACKET_TYPE_PARTIAL != pOpData->packetType) &&
690	    !digestIsAppended && (NULL == pOpData->pDigestResult)) {
691		LAC_INVALID_PARAM_LOG("pDigestResult is NULL");
692		return CPA_STATUS_INVALID_PARAM;
693	}
694
695	/*
696	 * Check if the pVerifyResult pointer is not null for hash operation
697	 * when the packet is the last one and user has set verifyDigest flag
698	 * Also, this is only needed for symchronous operation, so check if the
699	 * callback pointer is the internal synchronous one rather than a user-
700	 * supplied one.
701	 */
702	if ((CPA_TRUE == digestVerify) &&
703	    (CPA_CY_SYM_PACKET_TYPE_PARTIAL != pOpData->packetType) &&
704	    (LacSync_GenBufListVerifyCb == pSessionDesc->pSymCb)) {
705		if (NULL == pVerifyResult) {
706			LAC_INVALID_PARAM_LOG(
707			    "Null pointer pVerifyResult for hash op");
708			return CPA_STATUS_INVALID_PARAM;
709		}
710	}
711
712	/* verify start offset + messageLenToDigest is inside the source packet.
713	 * this also verifies that the start offset is inside the packet
714	 * Note: digest is specified as a pointer therefore it can be
715	 * written anywhere so we cannot check for this been inside a buffer
716	 * CCM/GCM specify the auth region using just the cipher params as this
717	 * region is the same for auth and cipher. It is not checked here */
718	if ((CPA_CY_SYM_HASH_AES_CCM == hashAlgorithm) ||
719	    (CPA_CY_SYM_HASH_AES_GCM == hashAlgorithm)) {
720		/* ensure AAD data pointer is non-NULL if AAD len > 0 */
721		if ((pSessionDesc->aadLenInBytes > 0) &&
722		    (NULL == pOpData->pAdditionalAuthData)) {
723			LAC_INVALID_PARAM_LOG("pAdditionalAuthData is NULL");
724			return CPA_STATUS_INVALID_PARAM;
725		}
726	} else {
727		if ((pOpData->hashStartSrcOffsetInBytes +
728		     pOpData->messageLenToHashInBytes) > srcPktSize) {
729			LAC_INVALID_PARAM_LOG(
730			    "hashStartSrcOffsetInBytes + "
731			    "messageLenToHashInBytes > Src Buffer Packet Length");
732			return CPA_STATUS_INVALID_PARAM;
733		}
734	}
735
736	/* For Snow3g & ZUC hash pAdditionalAuthData field
737	 * of OpData should contain IV */
738	if ((CPA_CY_SYM_HASH_SNOW3G_UIA2 == hashAlgorithm) ||
739	    (CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlgorithm)) {
740		if (NULL == pOpData->pAdditionalAuthData) {
741			LAC_INVALID_PARAM_LOG("pAdditionalAuthData is NULL");
742			return CPA_STATUS_INVALID_PARAM;
743		}
744	}
745
746	/* partial packets need to be multiples of the algorithm block size in
747	 * hash only mode (except for final partial packet) */
748	if ((CPA_CY_SYM_PACKET_TYPE_PARTIAL == pOpData->packetType) &&
749	    (CPA_CY_SYM_OP_HASH == symOperation)) {
750		LacSymQat_HashAlgLookupGet(instanceHandle,
751					   hashAlgorithm,
752					   &pHashAlgInfo);
753
754		/* check if the message is a multiple of the block size. */
755		if ((pOpData->messageLenToHashInBytes %
756		     pHashAlgInfo->blockLength) != 0) {
757			LAC_INVALID_PARAM_LOG(
758			    "messageLenToHashInBytes not block size");
759			return CPA_STATUS_INVALID_PARAM;
760		}
761	}
762
763	return status;
764}
765
766