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