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 
55 void 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  */
75 static void
76 LacHash_SyncPrecomputeDoneCb(void *pCallbackTag)
77 {
78 	LacSync_GenWakeupSyncCaller(pCallbackTag, CPA_STATUS_SUCCESS);
79 }
80 
81 /** @ingroup LacHash */
82 CpaStatus
83 LacHash_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 */
133 CpaStatus
134 LacHash_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 */
371 CpaStatus
372 LacHash_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 */
664 CpaStatus
665 LacHash_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