Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2015-2022 Intel Corporation
3 : : */
4 : :
5 : : #ifndef _QAT_SYM_H_
6 : : #define _QAT_SYM_H_
7 : :
8 : : #include <cryptodev_pmd.h>
9 : : #include <rte_net_crc.h>
10 : :
11 : : #ifdef BUILD_QAT_SYM
12 : : #ifdef RTE_QAT_OPENSSL
13 : : #include <openssl/evp.h>
14 : : #endif
15 : : #include <rte_security_driver.h>
16 : :
17 : : #include "qat_common.h"
18 : : #include "qat_sym_session.h"
19 : : #include "qat_crypto.h"
20 : : #include "qat_logs.h"
21 : :
22 : : #define BYTE_LENGTH 8
23 : : /* bpi is only used for partial blocks of DES and AES
24 : : * so AES block len can be assumed as max len for iv, src and dst
25 : : */
26 : : #define BPI_MAX_ENCR_IV_LEN ICP_QAT_HW_AES_BLK_SZ
27 : :
28 : : /** Intel(R) QAT Symmetric Crypto PMD name */
29 : : #define CRYPTODEV_NAME_QAT_SYM_PMD crypto_qat
30 : :
31 : : /* Internal capabilities */
32 : : #define QAT_SYM_CAP_MIXED_CRYPTO (1 << 0)
33 : : #define QAT_SYM_CAP_CIPHER_CRC (1 << 1)
34 : : #define QAT_SYM_CAP_VALID (1 << 31)
35 : :
36 : : /**
37 : : * Macro to add a sym capability
38 : : * helper function to add an sym capability
39 : : * <n: name> <b: block size> <k: key size> <d: digest size>
40 : : * <a: aad_size> <i: iv_size>
41 : : **/
42 : : #define QAT_SYM_PLAIN_AUTH_CAP(n, b, d) \
43 : : { \
44 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, \
45 : : {.sym = { \
46 : : .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH, \
47 : : {.auth = { \
48 : : .algo = RTE_CRYPTO_AUTH_##n, \
49 : : b, d \
50 : : }, } \
51 : : }, } \
52 : : }
53 : :
54 : : #define QAT_SYM_AUTH_CAP(n, b, k, d, a, i) \
55 : : { \
56 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, \
57 : : {.sym = { \
58 : : .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH, \
59 : : {.auth = { \
60 : : .algo = RTE_CRYPTO_AUTH_##n, \
61 : : b, k, d, a, i \
62 : : }, } \
63 : : }, } \
64 : : }
65 : :
66 : : #define QAT_SYM_AEAD_CAP(n, b, k, d, a, i) \
67 : : { \
68 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, \
69 : : {.sym = { \
70 : : .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD, \
71 : : {.aead = { \
72 : : .algo = RTE_CRYPTO_AEAD_##n, \
73 : : b, k, d, a, i \
74 : : }, } \
75 : : }, } \
76 : : }
77 : :
78 : : #define QAT_SYM_CIPHER_CAP(n, b, k, i) \
79 : : { \
80 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, \
81 : : {.sym = { \
82 : : .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER, \
83 : : {.cipher = { \
84 : : .algo = RTE_CRYPTO_CIPHER_##n, \
85 : : b, k, i \
86 : : }, } \
87 : : }, } \
88 : : }
89 : :
90 : : /*
91 : : * Maximum number of SGL entries
92 : : */
93 : : #define QAT_SYM_SGL_MAX_NUMBER 16
94 : :
95 : : /* Maximum data length for single pass GMAC: 2^14-1 */
96 : : #define QAT_AES_GMAC_SPC_MAX_SIZE 16383
97 : :
98 : : struct qat_sym_session;
99 : :
100 : : struct qat_sym_sgl {
101 : : qat_sgl_hdr;
102 : : struct qat_flat_buf buffers[QAT_SYM_SGL_MAX_NUMBER];
103 : : } __rte_packed __rte_cache_aligned;
104 : :
105 : : struct qat_sym_op_cookie {
106 : : struct qat_sym_sgl qat_sgl_src;
107 : : struct qat_sym_sgl qat_sgl_dst;
108 : : phys_addr_t qat_sgl_src_phys_addr;
109 : : phys_addr_t qat_sgl_dst_phys_addr;
110 : : union {
111 : : /* Used for Single-Pass AES-GMAC only */
112 : : struct {
113 : : struct icp_qat_hw_cipher_algo_blk cd_cipher
114 : : __rte_packed __rte_cache_aligned;
115 : : phys_addr_t cd_phys_addr;
116 : : } spc_gmac;
117 : : } opt;
118 : : uint8_t digest_null[4];
119 : : phys_addr_t digest_null_phys_addr;
120 : : enum rte_crypto_op_status status;
121 : : };
122 : :
123 : : struct qat_sym_dp_ctx {
124 : : struct qat_sym_session *session;
125 : : uint32_t tail;
126 : : uint32_t head;
127 : : uint16_t cached_enqueue;
128 : : uint16_t cached_dequeue;
129 : : };
130 : :
131 : : uint16_t
132 : : qat_sym_enqueue_burst(void *qp, struct rte_crypto_op **ops,
133 : : uint16_t nb_ops);
134 : :
135 : : uint16_t
136 : : qat_sym_dequeue_burst(void *qp, struct rte_crypto_op **ops,
137 : : uint16_t nb_ops);
138 : :
139 : : #ifdef RTE_QAT_OPENSSL
140 : : /** Encrypt a single partial block
141 : : * Depends on openssl libcrypto
142 : : * Uses ECB+XOR to do CFB encryption, same result, more performant
143 : : */
144 : : static inline int
145 : 0 : bpi_cipher_encrypt(uint8_t *src, uint8_t *dst,
146 : : uint8_t *iv, int ivlen, int srclen,
147 : : void *bpi_ctx)
148 : : {
149 : : EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *)bpi_ctx;
150 : : int encrypted_ivlen;
151 : : uint8_t encrypted_iv[BPI_MAX_ENCR_IV_LEN];
152 : : uint8_t *encr = encrypted_iv;
153 : :
154 : : /* ECB method: encrypt the IV, then XOR this with plaintext */
155 [ # # ]: 0 : if (EVP_EncryptUpdate(ctx, encrypted_iv, &encrypted_ivlen, iv, ivlen)
156 : : <= 0)
157 : 0 : goto cipher_encrypt_err;
158 : :
159 [ # # ]: 0 : for (; srclen != 0; --srclen, ++dst, ++src, ++encr)
160 : 0 : *dst = *src ^ *encr;
161 : :
162 : : return 0;
163 : :
164 : : cipher_encrypt_err:
165 : 0 : QAT_DP_LOG(ERR, "libcrypto ECB cipher encrypt failed");
166 : 0 : return -EINVAL;
167 : : }
168 : : #else
169 : : static __rte_always_inline void
170 : : bpi_cipher_ipsec(uint8_t *src, uint8_t *dst, uint8_t *iv, int srclen,
171 : : uint64_t *expkey, IMB_MGR *m, uint8_t docsis_key_len)
172 : : {
173 : : if (docsis_key_len == ICP_QAT_HW_AES_128_KEY_SZ)
174 : : IMB_AES128_CFB_ONE(m, dst, src, (uint64_t *)iv, expkey, srclen);
175 : : else if (docsis_key_len == ICP_QAT_HW_AES_256_KEY_SZ)
176 : : IMB_AES256_CFB_ONE(m, dst, src, (uint64_t *)iv, expkey, srclen);
177 : : else if (docsis_key_len == ICP_QAT_HW_DES_KEY_SZ)
178 : : des_cfb_one(dst, src, (uint64_t *)iv, expkey, srclen);
179 : : }
180 : : #endif
181 : :
182 : : static inline uint32_t
183 : 0 : qat_bpicipher_postprocess(struct qat_sym_session *ctx,
184 : : struct rte_crypto_op *op)
185 : : {
186 : 0 : int block_len = qat_cipher_get_block_size(ctx->qat_cipher_alg);
187 : : struct rte_crypto_sym_op *sym_op = op->sym;
188 [ # # ]: 0 : uint8_t last_block_len = block_len > 0 ?
189 : 0 : sym_op->cipher.data.length % block_len : 0;
190 : :
191 [ # # ]: 0 : if (last_block_len > 0 &&
192 [ # # ]: 0 : ctx->qat_dir == ICP_QAT_HW_CIPHER_ENCRYPT) {
193 : :
194 : : /* Encrypt last block */
195 : : uint8_t *last_block, *dst, *iv;
196 : : uint32_t last_block_offset;
197 : :
198 : 0 : last_block_offset = sym_op->cipher.data.offset +
199 : 0 : sym_op->cipher.data.length - last_block_len;
200 : 0 : last_block = (uint8_t *) rte_pktmbuf_mtod_offset(sym_op->m_src,
201 : : uint8_t *, last_block_offset);
202 : :
203 [ # # ]: 0 : if (unlikely(sym_op->m_dst != NULL))
204 : : /* out-of-place operation (OOP) */
205 : 0 : dst = (uint8_t *) rte_pktmbuf_mtod_offset(sym_op->m_dst,
206 : : uint8_t *, last_block_offset);
207 : : else
208 : : dst = last_block;
209 : :
210 [ # # ]: 0 : if (last_block_len < sym_op->cipher.data.length)
211 : : /* use previous block ciphertext as IV */
212 : 0 : iv = dst - block_len;
213 : : else
214 : : /* runt block, i.e. less than one full block */
215 : 0 : iv = rte_crypto_op_ctod_offset(op, uint8_t *,
216 : : ctx->cipher_iv.offset);
217 : :
218 : : #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
219 : : QAT_DP_HEXDUMP_LOG(DEBUG, "BPI: src before post-process:",
220 : : last_block, last_block_len);
221 : : if (sym_op->m_dst != NULL)
222 : : QAT_DP_HEXDUMP_LOG(DEBUG,
223 : : "BPI: dst before post-process:",
224 : : dst, last_block_len);
225 : : #endif
226 : : #ifdef RTE_QAT_OPENSSL
227 : 0 : bpi_cipher_encrypt(last_block, dst, iv, block_len,
228 : : last_block_len, ctx->bpi_ctx);
229 : : #else
230 : : bpi_cipher_ipsec(last_block, dst, iv, last_block_len, ctx->expkey,
231 : : ctx->mb_mgr, ctx->docsis_key_len);
232 : : #endif
233 : : #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
234 : : QAT_DP_HEXDUMP_LOG(DEBUG, "BPI: src after post-process:",
235 : : last_block, last_block_len);
236 : : if (sym_op->m_dst != NULL)
237 : : QAT_DP_HEXDUMP_LOG(DEBUG,
238 : : "BPI: dst after post-process:",
239 : : dst, last_block_len);
240 : : #endif
241 : : }
242 : 0 : return sym_op->cipher.data.length - last_block_len;
243 : : }
244 : :
245 : : static inline void
246 : 0 : qat_crc_verify(struct qat_sym_session *ctx, struct rte_crypto_op *op)
247 : : {
248 : : struct rte_crypto_sym_op *sym_op = op->sym;
249 : : uint32_t crc_data_ofs, crc_data_len, crc;
250 : : uint8_t *crc_data;
251 : :
252 [ # # ]: 0 : if (ctx->qat_dir == ICP_QAT_HW_CIPHER_DECRYPT &&
253 [ # # ]: 0 : sym_op->auth.data.length != 0) {
254 : :
255 : 0 : crc_data_ofs = sym_op->auth.data.offset;
256 : : crc_data_len = sym_op->auth.data.length;
257 : 0 : crc_data = rte_pktmbuf_mtod_offset(sym_op->m_src, uint8_t *,
258 : : crc_data_ofs);
259 : :
260 : 0 : crc = rte_net_crc_calc(crc_data, crc_data_len,
261 : : RTE_NET_CRC32_ETH);
262 : :
263 [ # # ]: 0 : if (crc != *(uint32_t *)(crc_data + crc_data_len))
264 : 0 : op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
265 : : }
266 : 0 : }
267 : :
268 : : static inline void
269 : 0 : qat_crc_generate(struct qat_sym_session *ctx,
270 : : struct rte_crypto_op *op)
271 : : {
272 : : struct rte_crypto_sym_op *sym_op = op->sym;
273 : : uint32_t *crc, crc_data_len;
274 : : uint8_t *crc_data;
275 : :
276 [ # # ]: 0 : if (ctx->qat_dir == ICP_QAT_HW_CIPHER_ENCRYPT &&
277 [ # # ]: 0 : sym_op->auth.data.length != 0 &&
278 [ # # ]: 0 : sym_op->m_src->nb_segs == 1) {
279 : :
280 : : crc_data_len = sym_op->auth.data.length;
281 : 0 : crc_data = rte_pktmbuf_mtod_offset(sym_op->m_src, uint8_t *,
282 : : sym_op->auth.data.offset);
283 : 0 : crc = (uint32_t *)(crc_data + crc_data_len);
284 : 0 : *crc = rte_net_crc_calc(crc_data, crc_data_len,
285 : : RTE_NET_CRC32_ETH);
286 : : }
287 : 0 : }
288 : :
289 : : static inline void
290 : 0 : qat_sym_preprocess_requests(void **ops, uint16_t nb_ops)
291 : : {
292 : : struct rte_crypto_op *op;
293 : : struct qat_sym_session *ctx;
294 : : uint16_t i;
295 : :
296 [ # # ]: 0 : for (i = 0; i < nb_ops; i++) {
297 : 0 : op = (struct rte_crypto_op *)ops[i];
298 : :
299 [ # # ]: 0 : if (op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
300 : 0 : ctx = SECURITY_GET_SESS_PRIV(op->sym->session);
301 : :
302 : : #ifdef RTE_QAT_OPENSSL
303 [ # # ]: 0 : if (ctx == NULL || ctx->bpi_ctx == NULL)
304 : : #else
305 : : if (ctx == NULL || ctx->mb_mgr == NULL)
306 : : #endif
307 : 0 : continue;
308 : :
309 [ # # ]: 0 : if (ctx->qat_cmd != ICP_QAT_FW_LA_CMD_CIPHER_CRC)
310 : 0 : qat_crc_generate(ctx, op);
311 : : }
312 : : }
313 : 0 : }
314 : :
315 : : static __rte_always_inline int
316 : 0 : qat_sym_process_response(void **op, uint8_t *resp, void *op_cookie,
317 : : uint64_t *dequeue_err_count __rte_unused)
318 : : {
319 : : struct icp_qat_fw_comn_resp *resp_msg =
320 : : (struct icp_qat_fw_comn_resp *)resp;
321 : 0 : struct rte_crypto_op *rx_op = (struct rte_crypto_op *)(uintptr_t)
322 : 0 : (resp_msg->opaque_data);
323 : : struct qat_sym_session *sess;
324 : : uint8_t is_docsis_sec;
325 : : struct qat_sym_op_cookie *cookie = NULL;
326 : :
327 : : #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
328 : : QAT_DP_HEXDUMP_LOG(DEBUG, "qat_response:", (uint8_t *)resp_msg,
329 : : sizeof(struct icp_qat_fw_comn_resp));
330 : : #endif
331 : :
332 [ # # ]: 0 : if (rx_op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
333 : : /*
334 : : * Assuming at this point that if it's a security
335 : : * op, that this is for DOCSIS
336 : : */
337 : 0 : sess = SECURITY_GET_SESS_PRIV(rx_op->sym->session);
338 : : is_docsis_sec = 1;
339 : : } else {
340 : 0 : sess = CRYPTODEV_GET_SYM_SESS_PRIV(rx_op->sym->session);
341 : : is_docsis_sec = 0;
342 : : }
343 : :
344 : 0 : if (ICP_QAT_FW_COMN_STATUS_FLAG_OK !=
345 [ # # ]: 0 : ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(
346 : : resp_msg->comn_hdr.comn_status)) {
347 : :
348 : 0 : rx_op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
349 : : } else {
350 : 0 : rx_op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
351 : :
352 : : #ifdef RTE_QAT_OPENSSL
353 [ # # ]: 0 : if (sess->bpi_ctx) {
354 : : #else
355 : : if (sess->mb_mgr) {
356 : : #endif
357 : 0 : qat_bpicipher_postprocess(sess, rx_op);
358 [ # # # # ]: 0 : if (is_docsis_sec && sess->qat_cmd !=
359 : : ICP_QAT_FW_LA_CMD_CIPHER_CRC)
360 : 0 : qat_crc_verify(sess, rx_op);
361 : : }
362 : : }
363 : :
364 [ # # ]: 0 : if (sess->is_single_pass_gmac) {
365 : : struct qat_sym_op_cookie *cookie =
366 : : (struct qat_sym_op_cookie *) op_cookie;
367 : 0 : memset(cookie->opt.spc_gmac.cd_cipher.key, 0,
368 : 0 : sess->auth_key_length);
369 : : }
370 : :
371 : : cookie = (struct qat_sym_op_cookie *) op_cookie;
372 [ # # ]: 0 : if (cookie->status == RTE_CRYPTO_OP_STATUS_INVALID_ARGS) {
373 : 0 : rx_op->status = cookie->status;
374 : 0 : cookie->status = 0;
375 : : }
376 : :
377 : 0 : *op = (void *)rx_op;
378 : :
379 : : /*
380 : : * return 1 as dequeue op only move on to the next op
381 : : * if one was ready to return to API
382 : : */
383 : 0 : return 1;
384 : : }
385 : :
386 : : int
387 : : qat_sym_configure_dp_ctx(struct rte_cryptodev *dev, uint16_t qp_id,
388 : : struct rte_crypto_raw_dp_ctx *raw_dp_ctx,
389 : : enum rte_crypto_op_sess_type sess_type,
390 : : union rte_cryptodev_session_ctx session_ctx, uint8_t is_update);
391 : :
392 : : int
393 : : qat_sym_get_dp_ctx_size(struct rte_cryptodev *dev);
394 : :
395 : : void
396 : : qat_sym_init_op_cookie(void *cookie);
397 : :
398 : : #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
399 : : static __rte_always_inline void
400 : : qat_sym_debug_log_dump(struct icp_qat_fw_la_bulk_req *qat_req,
401 : : struct qat_sym_session *ctx,
402 : : struct rte_crypto_vec *vec, uint32_t vec_len,
403 : : struct rte_crypto_va_iova_ptr *cipher_iv,
404 : : struct rte_crypto_va_iova_ptr *auth_iv,
405 : : struct rte_crypto_va_iova_ptr *aad,
406 : : struct rte_crypto_va_iova_ptr *digest)
407 : : {
408 : : uint32_t i;
409 : :
410 : : QAT_DP_HEXDUMP_LOG(DEBUG, "qat_req:", qat_req,
411 : : sizeof(struct icp_qat_fw_la_bulk_req));
412 : : for (i = 0; i < vec_len; i++)
413 : : QAT_DP_HEXDUMP_LOG(DEBUG, "src_data:", vec[i].base, vec[i].len);
414 : : if (cipher_iv && ctx->cipher_iv.length > 0)
415 : : QAT_DP_HEXDUMP_LOG(DEBUG, "cipher iv:", cipher_iv->va,
416 : : ctx->cipher_iv.length);
417 : : if (auth_iv && ctx->auth_iv.length > 0)
418 : : QAT_DP_HEXDUMP_LOG(DEBUG, "auth iv:", auth_iv->va,
419 : : ctx->auth_iv.length);
420 : : if (aad && ctx->aad_len > 0)
421 : : QAT_DP_HEXDUMP_LOG(DEBUG, "aad:", aad->va,
422 : : ctx->aad_len);
423 : : if (digest && ctx->digest_length > 0)
424 : : QAT_DP_HEXDUMP_LOG(DEBUG, "digest:", digest->va,
425 : : ctx->digest_length);
426 : : }
427 : : #else
428 : : static __rte_always_inline void
429 : : qat_sym_debug_log_dump(struct icp_qat_fw_la_bulk_req *qat_req __rte_unused,
430 : : struct qat_sym_session *ctx __rte_unused,
431 : : struct rte_crypto_vec *vec __rte_unused,
432 : : uint32_t vec_len __rte_unused,
433 : : struct rte_crypto_va_iova_ptr *cipher_iv __rte_unused,
434 : : struct rte_crypto_va_iova_ptr *auth_iv __rte_unused,
435 : : struct rte_crypto_va_iova_ptr *aad __rte_unused,
436 : : struct rte_crypto_va_iova_ptr *digest __rte_unused)
437 : : {
438 : : }
439 : : #endif
440 : :
441 : : #else
442 : :
443 : : static inline void
444 : : qat_sym_preprocess_requests(void **ops __rte_unused,
445 : : uint16_t nb_ops __rte_unused)
446 : : {
447 : : }
448 : :
449 : : static inline void
450 : : qat_sym_process_response(void **op __rte_unused, uint8_t *resp __rte_unused,
451 : : void *op_cookie __rte_unused)
452 : : {
453 : : }
454 : :
455 : : #endif /* BUILD_QAT_SYM */
456 : : #endif /* _QAT_SYM_H_ */
|