xref: /freebsd/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cipher.c (revision 25f09d4a9c358c5452435d299e00c1a1bdafff87)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2025 Intel Corporation */
3 
4 /**
5  ***************************************************************************
6  * @file lac_sym_cipher.c   Cipher
7  *
8  * @ingroup LacCipher
9  *
10  * @description Functions specific to cipher
11  ***************************************************************************/
12 
13 /*
14 *******************************************************************************
15 * Include public/global header files
16 *******************************************************************************
17 */
18 #include "cpa.h"
19 #include "cpa_cy_sym.h"
20 
21 #include "icp_adf_init.h"
22 #include "icp_adf_transport.h"
23 #include "icp_accel_devices.h"
24 #include "icp_adf_debug.h"
25 
26 #include "icp_qat_fw_la.h"
27 
28 /*
29 *******************************************************************************
30 * Include private header files
31 *******************************************************************************
32 */
33 #include "lac_sym_cipher.h"
34 #include "lac_session.h"
35 #include "lac_mem.h"
36 #include "lac_common.h"
37 #include "lac_list.h"
38 #include "lac_sym.h"
39 #include "lac_sym_key.h"
40 #include "lac_sym_qat_hash_defs_lookup.h"
41 #include "lac_sal_types_crypto.h"
42 #include "lac_sal.h"
43 #include "lac_sal_ctrl.h"
44 #include "lac_sym_cipher_defs.h"
45 #include "lac_sym_cipher.h"
46 #include "lac_sym_stats.h"
47 #include "lac_sym.h"
48 #include "lac_sym_qat_cipher.h"
49 #include "lac_log.h"
50 #include "lac_buffer_desc.h"
51 #include "sal_hw_gen.h"
52 
53 /*
54 *******************************************************************************
55 * Static Variables
56 *******************************************************************************
57 */
58 
59 CpaStatus
LacCipher_PerformIvCheck(sal_service_t * pService,lac_sym_bulk_cookie_t * pCbCookie,Cpa32U qatPacketType,Cpa8U ** ppIvBuffer)60 LacCipher_PerformIvCheck(sal_service_t *pService,
61 			 lac_sym_bulk_cookie_t *pCbCookie,
62 			 Cpa32U qatPacketType,
63 			 Cpa8U **ppIvBuffer)
64 {
65 	const CpaCySymOpData *pOpData = pCbCookie->pOpData;
66 	lac_session_desc_t *pSessionDesc =
67 	    LAC_SYM_SESSION_DESC_FROM_CTX_GET(pOpData->sessionCtx);
68 	CpaCySymCipherAlgorithm algorithm = pSessionDesc->cipherAlgorithm;
69 	unsigned ivLenInBytes = 0;
70 
71 	switch (algorithm) {
72 	/* Perform IV check for CTR, CBC, XTS, F8 MODE. */
73 	case CPA_CY_SYM_CIPHER_AES_CTR:
74 	case CPA_CY_SYM_CIPHER_3DES_CTR:
75 	case CPA_CY_SYM_CIPHER_SM4_CTR:
76 	case CPA_CY_SYM_CIPHER_AES_CCM:
77 	case CPA_CY_SYM_CIPHER_AES_GCM:
78 	case CPA_CY_SYM_CIPHER_CHACHA:
79 	case CPA_CY_SYM_CIPHER_AES_CBC:
80 	case CPA_CY_SYM_CIPHER_DES_CBC:
81 	case CPA_CY_SYM_CIPHER_3DES_CBC:
82 	case CPA_CY_SYM_CIPHER_SM4_CBC:
83 	case CPA_CY_SYM_CIPHER_AES_F8:
84 	case CPA_CY_SYM_CIPHER_AES_XTS: {
85 		ivLenInBytes = LacSymQat_CipherIvSizeBytesGet(algorithm);
86 		LAC_CHECK_NULL_PARAM(pOpData->pIv);
87 		if (pOpData->ivLenInBytes != ivLenInBytes) {
88 			if (!(/* GCM with 12 byte IV is OK */
89 			      (LAC_CIPHER_IS_GCM(algorithm) &&
90 			       pOpData->ivLenInBytes ==
91 				   LAC_CIPHER_IV_SIZE_GCM_12) ||
92 			      /* IV len for CCM has been checked before */
93 			      LAC_CIPHER_IS_CCM(algorithm))) {
94 				LAC_INVALID_PARAM_LOG("invalid cipher IV size");
95 				return CPA_STATUS_INVALID_PARAM;
96 			}
97 		}
98 
99 		/* Always copy the user's IV into another cipher state buffer if
100 		 * the request is part of a partial packet sequence
101 		 *      (ensures that pipelined partial requests use same
102 		 * buffer)
103 		 */
104 		if (ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) {
105 			/* Set the value of the ppIvBuffer to that supplied
106 			 * by the user.
107 			 * NOTE: There is no guarantee that this address is
108 			 * aligned on an 8 or 64 Byte address. */
109 			*ppIvBuffer = pOpData->pIv;
110 		} else {
111 			/* For partial packets, we use a per-session buffer to
112 			 * maintain the IV.  This allows us to easily pass the
113 			 * updated IV forward to the next partial in the
114 			 * sequence.  This makes internal buffering of partials
115 			 * easier to implement.
116 			 */
117 			*ppIvBuffer = pSessionDesc->cipherPartialOpState;
118 
119 			/* Ensure that the user's IV buffer gets updated between
120 			 * partial requests so that they may also see the
121 			 * residue from the previous partial.  Not needed for
122 			 * final partials though.
123 			 */
124 			if ((ICP_QAT_FW_LA_PARTIAL_START == qatPacketType) ||
125 			    (ICP_QAT_FW_LA_PARTIAL_MID == qatPacketType)) {
126 				pCbCookie->updateUserIvOnRecieve = CPA_TRUE;
127 
128 				if (ICP_QAT_FW_LA_PARTIAL_START ==
129 				    qatPacketType) {
130 					/* if the previous partial state was
131 					 * full, then this is the first partial
132 					 * in the sequence so we need to copy in
133 					 * the user's IV. But, we have to be
134 					 * very careful here not to overwrite
135 					 * the cipherPartialOpState just yet in
136 					 * case there's a previous partial
137 					 * sequence in flight, so we defer the
138 					 * copy for now.  This will be completed
139 					 * in the LacSymQueue_RequestSend()
140 					 * function.
141 					 */
142 					pCbCookie->updateSessionIvOnSend =
143 					    CPA_TRUE;
144 				}
145 				/* For subsequent partials in a sequence, we'll
146 				 * reuse the IV that was written back by the
147 				 * QAT, using internal request queueing if
148 				 * necessary to ensure that the next partial
149 				 * request isn't issued to the QAT until the
150 				 * previous one completes
151 				 */
152 			}
153 		}
154 	} break;
155 	case CPA_CY_SYM_CIPHER_KASUMI_F8: {
156 		LAC_CHECK_NULL_PARAM(pOpData->pIv);
157 
158 		if (pOpData->ivLenInBytes != LAC_CIPHER_KASUMI_F8_IV_LENGTH) {
159 			LAC_INVALID_PARAM_LOG("invalid cipher IV size");
160 			return CPA_STATUS_INVALID_PARAM;
161 		}
162 
163 		*ppIvBuffer = pOpData->pIv;
164 	} break;
165 	case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: {
166 		LAC_CHECK_NULL_PARAM(pOpData->pIv);
167 		if (pOpData->ivLenInBytes != ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ) {
168 			LAC_INVALID_PARAM_LOG("invalid cipher IV size");
169 			return CPA_STATUS_INVALID_PARAM;
170 		}
171 		*ppIvBuffer = pOpData->pIv;
172 	} break;
173 	case CPA_CY_SYM_CIPHER_ARC4: {
174 		if (ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) {
175 			/* For full packets, the initial ARC4 state is stored in
176 			 * the session descriptor.  Use it directly.
177 			 */
178 			*ppIvBuffer = pSessionDesc->cipherARC4InitialState;
179 		} else {
180 			/* For partial packets, we maintain the running ARC4
181 			 * state in dedicated buffer in the session descriptor
182 			 */
183 			*ppIvBuffer = pSessionDesc->cipherPartialOpState;
184 
185 			if (ICP_QAT_FW_LA_PARTIAL_START == qatPacketType) {
186 				/* if the previous partial state was full, then
187 				 * this is the first partial in the sequence so
188 				 * we need to (re-)initialise the contents of
189 				 * the state buffer using the initial state that
190 				 * is stored in the session descriptor. But, we
191 				 * have to be very careful here not to overwrite
192 				 * the cipherPartialOpState just yet in case
193 				 * there's a previous partial sequence in
194 				 * flight, so we defer the copy for now. This
195 				 * will be completed in the
196 				 * LacSymQueue_RequestSend() function when clear
197 				 * to send.
198 				 */
199 				pCbCookie->updateSessionIvOnSend = CPA_TRUE;
200 			}
201 		}
202 	} break;
203 	case CPA_CY_SYM_CIPHER_ZUC_EEA3: {
204 		LAC_CHECK_NULL_PARAM(pOpData->pIv);
205 		if (pOpData->ivLenInBytes != ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ) {
206 			LAC_INVALID_PARAM_LOG("invalid cipher IV size");
207 			return CPA_STATUS_INVALID_PARAM;
208 		}
209 		*ppIvBuffer = pOpData->pIv;
210 	} break;
211 	default:
212 		*ppIvBuffer = NULL;
213 	}
214 
215 	return CPA_STATUS_SUCCESS;
216 }
217 
218 CpaStatus
LacCipher_SessionSetupDataCheck(const CpaCySymCipherSetupData * pCipherSetupData,Cpa32U capabilitiesMask)219 LacCipher_SessionSetupDataCheck(const CpaCySymCipherSetupData *pCipherSetupData,
220 				Cpa32U capabilitiesMask)
221 {
222 	/* No key required for NULL algorithm */
223 	if (!LAC_CIPHER_IS_NULL(pCipherSetupData->cipherAlgorithm)) {
224 		LAC_CHECK_NULL_PARAM(pCipherSetupData->pCipherKey);
225 
226 		/* Check that algorithm and keys passed in are correct size */
227 		switch (pCipherSetupData->cipherAlgorithm) {
228 		case CPA_CY_SYM_CIPHER_ARC4:
229 			if (pCipherSetupData->cipherKeyLenInBytes >
230 			    ICP_QAT_HW_ARC4_KEY_SZ) {
231 				LAC_INVALID_PARAM_LOG(
232 				    "Invalid ARC4 cipher key length");
233 				return CPA_STATUS_INVALID_PARAM;
234 			}
235 			break;
236 		case CPA_CY_SYM_CIPHER_AES_CCM:
237 			if (!LAC_CIPHER_AES_V2(capabilitiesMask) &&
238 			    pCipherSetupData->cipherKeyLenInBytes !=
239 				ICP_QAT_HW_AES_128_KEY_SZ) {
240 				LAC_INVALID_PARAM_LOG(
241 				    "Invalid AES CCM cipher key length");
242 				return CPA_STATUS_INVALID_PARAM;
243 			}
244 			break;
245 		case CPA_CY_SYM_CIPHER_AES_XTS:
246 			if ((pCipherSetupData->cipherKeyLenInBytes !=
247 			     ICP_QAT_HW_AES_128_XTS_KEY_SZ) &&
248 			    (pCipherSetupData->cipherKeyLenInBytes !=
249 			     ICP_QAT_HW_AES_256_XTS_KEY_SZ) &&
250 			    (pCipherSetupData->cipherKeyLenInBytes !=
251 			     ICP_QAT_HW_UCS_AES_128_XTS_KEY_SZ) &&
252 			    (pCipherSetupData->cipherKeyLenInBytes !=
253 			     ICP_QAT_HW_UCS_AES_256_XTS_KEY_SZ)) {
254 				LAC_INVALID_PARAM_LOG(
255 				    "Invalid AES XTS cipher key length");
256 				return CPA_STATUS_INVALID_PARAM;
257 			}
258 			break;
259 		case CPA_CY_SYM_CIPHER_AES_ECB:
260 		case CPA_CY_SYM_CIPHER_AES_CBC:
261 		case CPA_CY_SYM_CIPHER_AES_CTR:
262 		case CPA_CY_SYM_CIPHER_AES_GCM:
263 			if ((pCipherSetupData->cipherKeyLenInBytes !=
264 			     ICP_QAT_HW_AES_128_KEY_SZ) &&
265 			    (pCipherSetupData->cipherKeyLenInBytes !=
266 			     ICP_QAT_HW_AES_192_KEY_SZ) &&
267 			    (pCipherSetupData->cipherKeyLenInBytes !=
268 			     ICP_QAT_HW_AES_256_KEY_SZ)) {
269 				LAC_INVALID_PARAM_LOG(
270 				    "Invalid AES cipher key length");
271 				return CPA_STATUS_INVALID_PARAM;
272 			}
273 			break;
274 		case CPA_CY_SYM_CIPHER_AES_F8:
275 			if ((pCipherSetupData->cipherKeyLenInBytes !=
276 			     ICP_QAT_HW_AES_128_F8_KEY_SZ) &&
277 			    (pCipherSetupData->cipherKeyLenInBytes !=
278 			     ICP_QAT_HW_AES_192_F8_KEY_SZ) &&
279 			    (pCipherSetupData->cipherKeyLenInBytes !=
280 			     ICP_QAT_HW_AES_256_F8_KEY_SZ)) {
281 				LAC_INVALID_PARAM_LOG(
282 				    "Invalid AES cipher key length");
283 				return CPA_STATUS_INVALID_PARAM;
284 			}
285 			break;
286 		case CPA_CY_SYM_CIPHER_DES_ECB:
287 		case CPA_CY_SYM_CIPHER_DES_CBC:
288 			if (pCipherSetupData->cipherKeyLenInBytes !=
289 			    ICP_QAT_HW_DES_KEY_SZ) {
290 				LAC_INVALID_PARAM_LOG(
291 				    "Invalid DES cipher key length");
292 				return CPA_STATUS_INVALID_PARAM;
293 			}
294 			break;
295 		case CPA_CY_SYM_CIPHER_3DES_ECB:
296 		case CPA_CY_SYM_CIPHER_3DES_CBC:
297 		case CPA_CY_SYM_CIPHER_3DES_CTR:
298 			if (pCipherSetupData->cipherKeyLenInBytes !=
299 			    ICP_QAT_HW_3DES_KEY_SZ) {
300 				LAC_INVALID_PARAM_LOG(
301 				    "Invalid Triple-DES cipher key length");
302 				return CPA_STATUS_INVALID_PARAM;
303 			}
304 			break;
305 		case CPA_CY_SYM_CIPHER_KASUMI_F8:
306 			/* QAT-FW only supports 128 bits Cipher Key size for
307 			 * Kasumi F8 Ref: 3GPP TS 55.216 V6.2.0 */
308 			if (pCipherSetupData->cipherKeyLenInBytes !=
309 			    ICP_QAT_HW_KASUMI_KEY_SZ) {
310 				LAC_INVALID_PARAM_LOG(
311 				    "Invalid Kasumi cipher key length");
312 				return CPA_STATUS_INVALID_PARAM;
313 			}
314 			break;
315 		case CPA_CY_SYM_CIPHER_SNOW3G_UEA2:
316 			/* QAT-FW only supports 256 bits Cipher Key size for
317 			 * Snow_3G */
318 			if (pCipherSetupData->cipherKeyLenInBytes !=
319 			    ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ) {
320 				LAC_INVALID_PARAM_LOG(
321 				    "Invalid Snow_3G cipher key length");
322 				return CPA_STATUS_INVALID_PARAM;
323 			}
324 			break;
325 		case CPA_CY_SYM_CIPHER_ZUC_EEA3:
326 			/* ZUC EEA3 */
327 			if (pCipherSetupData->cipherKeyLenInBytes !=
328 			    ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ) {
329 				LAC_INVALID_PARAM_LOG(
330 				    "Invalid ZUC cipher key length");
331 				return CPA_STATUS_INVALID_PARAM;
332 			}
333 			break;
334 		case CPA_CY_SYM_CIPHER_CHACHA:
335 			if (pCipherSetupData->cipherKeyLenInBytes !=
336 			    ICP_QAT_HW_CHACHAPOLY_KEY_SZ) {
337 				LAC_INVALID_PARAM_LOG(
338 				    "Invalid CHACHAPOLY cipher key length");
339 				return CPA_STATUS_INVALID_PARAM;
340 			}
341 			break;
342 		case CPA_CY_SYM_CIPHER_SM4_ECB:
343 		case CPA_CY_SYM_CIPHER_SM4_CBC:
344 		case CPA_CY_SYM_CIPHER_SM4_CTR:
345 			if (pCipherSetupData->cipherKeyLenInBytes !=
346 			    ICP_QAT_HW_SM4_KEY_SZ) {
347 				LAC_INVALID_PARAM_LOG(
348 				    "Invalid SM4 cipher key length");
349 				return CPA_STATUS_INVALID_PARAM;
350 			}
351 			break;
352 		default:
353 			LAC_INVALID_PARAM_LOG("Invalid cipher algorithm");
354 			return CPA_STATUS_INVALID_PARAM;
355 		}
356 	}
357 	return CPA_STATUS_SUCCESS;
358 }
359 
360 CpaStatus
LacCipher_PerformParamCheck(CpaCySymCipherAlgorithm algorithm,const CpaCySymOpData * pOpData,const Cpa64U packetLen)361 LacCipher_PerformParamCheck(CpaCySymCipherAlgorithm algorithm,
362 			    const CpaCySymOpData *pOpData,
363 			    const Cpa64U packetLen)
364 {
365 	CpaStatus status = CPA_STATUS_SUCCESS;
366 
367 	/* The following check will cover the dstBuffer as well, since
368 	 * the dstBuffer cannot be smaller than the srcBuffer (checked in
369 	 * LacSymPerform_BufferParamCheck() called from LacSym_Perform())
370 	 */
371 	if ((pOpData->messageLenToCipherInBytes +
372 	     pOpData->cryptoStartSrcOffsetInBytes) > packetLen) {
373 		LAC_INVALID_PARAM_LOG("cipher len + offset greater than "
374 				      "srcBuffer packet len");
375 		status = CPA_STATUS_INVALID_PARAM;
376 	} else {
377 		/* Perform algorithm-specific checks */
378 		switch (algorithm) {
379 		case CPA_CY_SYM_CIPHER_ARC4:
380 		case CPA_CY_SYM_CIPHER_AES_CTR:
381 		case CPA_CY_SYM_CIPHER_3DES_CTR:
382 		case CPA_CY_SYM_CIPHER_SM4_CTR:
383 		case CPA_CY_SYM_CIPHER_AES_CCM:
384 		case CPA_CY_SYM_CIPHER_AES_GCM:
385 		case CPA_CY_SYM_CIPHER_CHACHA:
386 		case CPA_CY_SYM_CIPHER_KASUMI_F8:
387 		case CPA_CY_SYM_CIPHER_AES_F8:
388 		case CPA_CY_SYM_CIPHER_SNOW3G_UEA2:
389 		case CPA_CY_SYM_CIPHER_ZUC_EEA3:
390 			/* No action needed */
391 			break;
392 		/*
393 		 * XTS Mode allow for ciphers which are not multiples of
394 		 * the block size.
395 		 */
396 		case CPA_CY_SYM_CIPHER_AES_XTS:
397 			if ((pOpData->packetType ==
398 			     CPA_CY_SYM_PACKET_TYPE_FULL) ||
399 			    (pOpData->packetType ==
400 			     CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL)) {
401 				/*
402 				 * If this is the last of a partial request
403 				 */
404 				if (pOpData->messageLenToCipherInBytes <
405 				    ICP_QAT_HW_AES_BLK_SZ) {
406 					LAC_INVALID_PARAM_LOG(
407 					    "data size must be greater than block"
408 					    " size for last XTS partial or XTS "
409 					    "full packet");
410 					status = CPA_STATUS_INVALID_PARAM;
411 				}
412 			}
413 			break;
414 		default:
415 			/* Mask & check below is based on assumption that block
416 			 * size is a power of 2. If data size is not a multiple
417 			 * of the block size, the "remainder" bits selected by
418 			 * the mask be non-zero
419 			 */
420 			if (pOpData->messageLenToCipherInBytes &
421 			    (LacSymQat_CipherBlockSizeBytesGet(algorithm) -
422 			     1)) {
423 				LAC_INVALID_PARAM_LOG(
424 				    "data size must be block size"
425 				    " multiple");
426 				status = CPA_STATUS_INVALID_PARAM;
427 			}
428 		}
429 	}
430 	return status;
431 }
432 
433 Cpa32U
LacCipher_GetCipherSliceType(sal_crypto_service_t * pService,CpaCySymCipherAlgorithm cipherAlgorithm,CpaCySymHashAlgorithm hashAlgorithm)434 LacCipher_GetCipherSliceType(sal_crypto_service_t *pService,
435 			     CpaCySymCipherAlgorithm cipherAlgorithm,
436 			     CpaCySymHashAlgorithm hashAlgorithm)
437 {
438 	Cpa32U sliceType = ICP_QAT_FW_LA_USE_LEGACY_SLICE_TYPE;
439 	Cpa32U capabilitiesMask =
440 	    pService->generic_service_info.capabilitiesMask;
441 
442 	/* UCS Slice is supported only in Gen4 */
443 	if (isCyGen4x(pService)) {
444 		if (LAC_CIPHER_IS_XTS_MODE(cipherAlgorithm) ||
445 		    LAC_CIPHER_IS_CHACHA(cipherAlgorithm) ||
446 		    LAC_CIPHER_IS_GCM(cipherAlgorithm)) {
447 			sliceType = ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE;
448 		} else if (LAC_CIPHER_IS_CCM(cipherAlgorithm) &&
449 			   LAC_CIPHER_AES_V2(capabilitiesMask)) {
450 			sliceType = ICP_QAT_FW_LA_USE_LEGACY_SLICE_TYPE;
451 		} else if (LAC_CIPHER_IS_AES(cipherAlgorithm) &&
452 			   LAC_CIPHER_IS_CTR_MODE(cipherAlgorithm)) {
453 			sliceType = ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE;
454 		}
455 	}
456 
457 	return sliceType;
458 }
459