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 = rte_pktmbuf_mtod_offset(sym_op->m_src, uint8_t *,
201 : : last_block_offset);
202 : :
203 [ # # ]: 0 : if (unlikely(sym_op->m_dst != NULL))
204 : : /* out-of-place operation (OOP) */
205 : 0 : dst = rte_pktmbuf_mtod_offset(sym_op->m_dst,
206 : : uint8_t *,
207 : : last_block_offset);
208 : : else
209 : : dst = last_block;
210 : :
211 [ # # ]: 0 : if (last_block_len < sym_op->cipher.data.length)
212 : : /* use previous block ciphertext as IV */
213 : 0 : iv = dst - block_len;
214 : : else
215 : : /* runt block, i.e. less than one full block */
216 : 0 : iv = rte_crypto_op_ctod_offset(op, uint8_t *,
217 : : ctx->cipher_iv.offset);
218 : :
219 : : #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
220 : : QAT_DP_HEXDUMP_LOG(DEBUG, "BPI: src before post-process:",
221 : : last_block, last_block_len);
222 : : if (sym_op->m_dst != NULL)
223 : : QAT_DP_HEXDUMP_LOG(DEBUG,
224 : : "BPI: dst before post-process:",
225 : : dst, last_block_len);
226 : : #endif
227 : : #ifdef RTE_QAT_OPENSSL
228 : 0 : bpi_cipher_encrypt(last_block, dst, iv, block_len,
229 : : last_block_len, ctx->bpi_ctx);
230 : : #else
231 : : bpi_cipher_ipsec(last_block, dst, iv, last_block_len, ctx->expkey,
232 : : ctx->mb_mgr, ctx->docsis_key_len);
233 : : #endif
234 : : #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
235 : : QAT_DP_HEXDUMP_LOG(DEBUG, "BPI: src after post-process:",
236 : : last_block, last_block_len);
237 : : if (sym_op->m_dst != NULL)
238 : : QAT_DP_HEXDUMP_LOG(DEBUG,
239 : : "BPI: dst after post-process:",
240 : : dst, last_block_len);
241 : : #endif
242 : : }
243 : 0 : return sym_op->cipher.data.length - last_block_len;
244 : : }
245 : :
246 : : static inline void
247 : 0 : qat_crc_verify(struct qat_sym_session *ctx, struct rte_crypto_op *op)
248 : : {
249 : : struct rte_crypto_sym_op *sym_op = op->sym;
250 : : uint32_t crc_data_ofs, crc_data_len, crc;
251 : : uint8_t *crc_data;
252 : :
253 [ # # ]: 0 : if (ctx->qat_dir == ICP_QAT_HW_CIPHER_DECRYPT &&
254 [ # # ]: 0 : sym_op->auth.data.length != 0) {
255 : :
256 : 0 : crc_data_ofs = sym_op->auth.data.offset;
257 : : crc_data_len = sym_op->auth.data.length;
258 : 0 : crc_data = rte_pktmbuf_mtod_offset(sym_op->m_src, uint8_t *,
259 : : crc_data_ofs);
260 : :
261 : 0 : crc = rte_net_crc_calc(crc_data, crc_data_len,
262 : : RTE_NET_CRC32_ETH);
263 : :
264 [ # # ]: 0 : if (crc != *(uint32_t *)(crc_data + crc_data_len))
265 : 0 : op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
266 : : }
267 : 0 : }
268 : :
269 : : static inline void
270 : 0 : qat_crc_generate(struct qat_sym_session *ctx,
271 : : struct rte_crypto_op *op)
272 : : {
273 : : struct rte_crypto_sym_op *sym_op = op->sym;
274 : : uint32_t *crc, crc_data_len;
275 : : uint8_t *crc_data;
276 : :
277 [ # # ]: 0 : if (ctx->qat_dir == ICP_QAT_HW_CIPHER_ENCRYPT &&
278 [ # # ]: 0 : sym_op->auth.data.length != 0 &&
279 [ # # ]: 0 : sym_op->m_src->nb_segs == 1) {
280 : :
281 : : crc_data_len = sym_op->auth.data.length;
282 : 0 : crc_data = rte_pktmbuf_mtod_offset(sym_op->m_src, uint8_t *,
283 : : sym_op->auth.data.offset);
284 : 0 : crc = (uint32_t *)(crc_data + crc_data_len);
285 : 0 : *crc = rte_net_crc_calc(crc_data, crc_data_len,
286 : : RTE_NET_CRC32_ETH);
287 : : }
288 : 0 : }
289 : :
290 : : static inline void
291 : 0 : qat_sym_preprocess_requests(void **ops, uint16_t nb_ops)
292 : : {
293 : : struct rte_crypto_op *op;
294 : : struct qat_sym_session *ctx;
295 : : uint16_t i;
296 : :
297 [ # # ]: 0 : for (i = 0; i < nb_ops; i++) {
298 : 0 : op = (struct rte_crypto_op *)ops[i];
299 : :
300 [ # # ]: 0 : if (op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
301 : 0 : ctx = SECURITY_GET_SESS_PRIV(op->sym->session);
302 : :
303 : : #ifdef RTE_QAT_OPENSSL
304 [ # # ]: 0 : if (ctx == NULL || ctx->bpi_ctx == NULL)
305 : : #else
306 : : if (ctx == NULL || ctx->mb_mgr == NULL)
307 : : #endif
308 : 0 : continue;
309 : :
310 [ # # ]: 0 : if (ctx->qat_cmd != ICP_QAT_FW_LA_CMD_CIPHER_CRC)
311 : 0 : qat_crc_generate(ctx, op);
312 : : }
313 : : }
314 : 0 : }
315 : :
316 : : static __rte_always_inline int
317 : 0 : qat_sym_process_response(void **op, uint8_t *resp, void *op_cookie,
318 : : uint64_t *dequeue_err_count __rte_unused)
319 : : {
320 : : struct icp_qat_fw_comn_resp *resp_msg =
321 : : (struct icp_qat_fw_comn_resp *)resp;
322 : 0 : struct rte_crypto_op *rx_op = (struct rte_crypto_op *)(uintptr_t)
323 : 0 : (resp_msg->opaque_data);
324 : : struct qat_sym_session *sess;
325 : : uint8_t is_docsis_sec;
326 : : struct qat_sym_op_cookie *cookie = NULL;
327 : :
328 : : #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
329 : : QAT_DP_HEXDUMP_LOG(DEBUG, "qat_response:", (uint8_t *)resp_msg,
330 : : sizeof(struct icp_qat_fw_comn_resp));
331 : : #endif
332 : :
333 [ # # ]: 0 : if (rx_op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
334 : : /*
335 : : * Assuming at this point that if it's a security
336 : : * op, that this is for DOCSIS
337 : : */
338 : 0 : sess = SECURITY_GET_SESS_PRIV(rx_op->sym->session);
339 : : is_docsis_sec = 1;
340 : : } else {
341 : 0 : sess = CRYPTODEV_GET_SYM_SESS_PRIV(rx_op->sym->session);
342 : : is_docsis_sec = 0;
343 : : }
344 : :
345 : 0 : if (ICP_QAT_FW_COMN_STATUS_FLAG_OK !=
346 [ # # ]: 0 : ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(
347 : : resp_msg->comn_hdr.comn_status)) {
348 : :
349 : 0 : rx_op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
350 : : } else {
351 : 0 : rx_op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
352 : :
353 : : #ifdef RTE_QAT_OPENSSL
354 [ # # ]: 0 : if (sess->bpi_ctx) {
355 : : #else
356 : : if (sess->mb_mgr) {
357 : : #endif
358 : 0 : qat_bpicipher_postprocess(sess, rx_op);
359 [ # # # # ]: 0 : if (is_docsis_sec && sess->qat_cmd !=
360 : : ICP_QAT_FW_LA_CMD_CIPHER_CRC)
361 : 0 : qat_crc_verify(sess, rx_op);
362 : : }
363 : : }
364 : :
365 [ # # ]: 0 : if (sess->is_single_pass_gmac) {
366 : : struct qat_sym_op_cookie *cookie =
367 : : (struct qat_sym_op_cookie *) op_cookie;
368 : 0 : memset(cookie->opt.spc_gmac.cd_cipher.key, 0,
369 : 0 : sess->auth_key_length);
370 : : }
371 : :
372 : : cookie = (struct qat_sym_op_cookie *) op_cookie;
373 [ # # ]: 0 : if (cookie->status == RTE_CRYPTO_OP_STATUS_INVALID_ARGS) {
374 : 0 : rx_op->status = cookie->status;
375 : 0 : cookie->status = 0;
376 : : }
377 : :
378 : 0 : *op = (void *)rx_op;
379 : :
380 : : /*
381 : : * return 1 as dequeue op only move on to the next op
382 : : * if one was ready to return to API
383 : : */
384 : 0 : return 1;
385 : : }
386 : :
387 : : int
388 : : qat_sym_configure_dp_ctx(struct rte_cryptodev *dev, uint16_t qp_id,
389 : : struct rte_crypto_raw_dp_ctx *raw_dp_ctx,
390 : : enum rte_crypto_op_sess_type sess_type,
391 : : union rte_cryptodev_session_ctx session_ctx, uint8_t is_update);
392 : :
393 : : int
394 : : qat_sym_get_dp_ctx_size(struct rte_cryptodev *dev);
395 : :
396 : : void
397 : : qat_sym_init_op_cookie(void *cookie);
398 : :
399 : : #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
400 : : static __rte_always_inline void
401 : : qat_sym_debug_log_dump(struct icp_qat_fw_la_bulk_req *qat_req,
402 : : struct qat_sym_session *ctx,
403 : : struct rte_crypto_vec *vec, uint32_t vec_len,
404 : : struct rte_crypto_va_iova_ptr *cipher_iv,
405 : : struct rte_crypto_va_iova_ptr *auth_iv,
406 : : struct rte_crypto_va_iova_ptr *aad,
407 : : struct rte_crypto_va_iova_ptr *digest)
408 : : {
409 : : uint32_t i;
410 : :
411 : : QAT_DP_HEXDUMP_LOG(DEBUG, "qat_req:", qat_req,
412 : : sizeof(struct icp_qat_fw_la_bulk_req));
413 : : for (i = 0; i < vec_len; i++)
414 : : QAT_DP_HEXDUMP_LOG(DEBUG, "src_data:", vec[i].base, vec[i].len);
415 : : if (cipher_iv && ctx->cipher_iv.length > 0)
416 : : QAT_DP_HEXDUMP_LOG(DEBUG, "cipher iv:", cipher_iv->va,
417 : : ctx->cipher_iv.length);
418 : : if (auth_iv && ctx->auth_iv.length > 0)
419 : : QAT_DP_HEXDUMP_LOG(DEBUG, "auth iv:", auth_iv->va,
420 : : ctx->auth_iv.length);
421 : : if (aad && ctx->aad_len > 0)
422 : : QAT_DP_HEXDUMP_LOG(DEBUG, "aad:", aad->va,
423 : : ctx->aad_len);
424 : : if (digest && ctx->digest_length > 0)
425 : : QAT_DP_HEXDUMP_LOG(DEBUG, "digest:", digest->va,
426 : : ctx->digest_length);
427 : : }
428 : : #else
429 : : static __rte_always_inline void
430 : : qat_sym_debug_log_dump(struct icp_qat_fw_la_bulk_req *qat_req __rte_unused,
431 : : struct qat_sym_session *ctx __rte_unused,
432 : : struct rte_crypto_vec *vec __rte_unused,
433 : : uint32_t vec_len __rte_unused,
434 : : struct rte_crypto_va_iova_ptr *cipher_iv __rte_unused,
435 : : struct rte_crypto_va_iova_ptr *auth_iv __rte_unused,
436 : : struct rte_crypto_va_iova_ptr *aad __rte_unused,
437 : : struct rte_crypto_va_iova_ptr *digest __rte_unused)
438 : : {
439 : : }
440 : : #endif
441 : :
442 : : #else
443 : :
444 : : static inline void
445 : : qat_sym_preprocess_requests(void **ops __rte_unused,
446 : : uint16_t nb_ops __rte_unused)
447 : : {
448 : : }
449 : :
450 : : static inline void
451 : : qat_sym_process_response(void **op __rte_unused, uint8_t *resp __rte_unused,
452 : : void *op_cookie __rte_unused)
453 : : {
454 : : }
455 : :
456 : : #endif /* BUILD_QAT_SYM */
457 : : #endif /* _QAT_SYM_H_ */
|