From 5be562bc5b787734c7d94467ce745fad3fe0a154 Mon Sep 17 00:00:00 2001 From: Tejasree Kondoj Date: Fri, 18 Dec 2020 19:44:10 +0530 Subject: [PATCH] crypto/octeontx2: support IPsec ESN and anti-replay Adding ESN and anti-replay support for lookaside IPsec. Signed-off-by: Tejasree Kondoj Acked-by: Anoob Joseph --- doc/guides/cryptodevs/octeontx2.rst | 2 + doc/guides/rel_notes/release_21_02.rst | 5 ++ drivers/crypto/octeontx2/otx2_cryptodev_ops.c | 47 ++++++++++++++++++- drivers/crypto/octeontx2/otx2_cryptodev_sec.c | 21 +++++++++ .../crypto/octeontx2/otx2_ipsec_anti_replay.h | 21 +++++++++ drivers/crypto/octeontx2/otx2_ipsec_po.h | 5 ++ drivers/crypto/octeontx2/otx2_ipsec_po_ops.h | 2 + 7 files changed, 101 insertions(+), 2 deletions(-) diff --git a/doc/guides/cryptodevs/octeontx2.rst b/doc/guides/cryptodevs/octeontx2.rst index 0a38b8662e..170f03dd0f 100644 --- a/doc/guides/cryptodevs/octeontx2.rst +++ b/doc/guides/cryptodevs/octeontx2.rst @@ -175,4 +175,6 @@ Features supported * IPv6 * ESP * Tunnel mode +* ESN +* Anti-replay * AES-128/192/256-GCM diff --git a/doc/guides/rel_notes/release_21_02.rst b/doc/guides/rel_notes/release_21_02.rst index be5ea4370c..81ace19403 100644 --- a/doc/guides/rel_notes/release_21_02.rst +++ b/doc/guides/rel_notes/release_21_02.rst @@ -76,6 +76,11 @@ New Features * Added inner UDP/IPv4 support for VXLAN IPv4 GSO. +* **Updated the OCTEON TX2 crypto PMD.** + + * Updated the OCTEON TX2 crypto PMD lookaside protocol offload for IPsec with + ESN and anti-replay support. + Removed Items ------------- diff --git a/drivers/crypto/octeontx2/otx2_cryptodev_ops.c b/drivers/crypto/octeontx2/otx2_cryptodev_ops.c index 5f2ccc0872..16aa7f4a0a 100644 --- a/drivers/crypto/octeontx2/otx2_cryptodev_ops.c +++ b/drivers/crypto/octeontx2/otx2_cryptodev_ops.c @@ -14,6 +14,7 @@ #include "otx2_cryptodev_mbox.h" #include "otx2_cryptodev_ops.h" #include "otx2_cryptodev_ops_helper.h" +#include "otx2_ipsec_anti_replay.h" #include "otx2_ipsec_po_ops.h" #include "otx2_mbox.h" #include "otx2_sec_idev.h" @@ -650,21 +651,55 @@ static __rte_always_inline int __rte_hot otx2_cpt_enqueue_sec(struct otx2_cpt_qp *qp, struct rte_crypto_op *op, struct pending_queue *pend_q) { + uint32_t winsz, esn_low = 0, esn_hi = 0, seql = 0, seqh = 0; + struct rte_mbuf *m_src = op->sym->m_src; struct otx2_sec_session_ipsec_lp *sess; struct otx2_ipsec_po_sa_ctl *ctl_wrd; + struct otx2_ipsec_po_in_sa *sa; struct otx2_sec_session *priv; struct cpt_request_info *req; + uint64_t seq_in_sa, seq = 0; + uint8_t esn; int ret; priv = get_sec_session_private_data(op->sym->sec_session); sess = &priv->ipsec.lp; + sa = &sess->in_sa; - ctl_wrd = &sess->in_sa.ctl; + ctl_wrd = &sa->ctl; + esn = ctl_wrd->esn_en; + winsz = sa->replay_win_sz; if (ctl_wrd->direction == OTX2_IPSEC_PO_SA_DIRECTION_OUTBOUND) ret = process_outb_sa(op, sess, &qp->meta_info, (void **)&req); - else + else { + if (winsz) { + esn_low = rte_be_to_cpu_32(sa->esn_low); + esn_hi = rte_be_to_cpu_32(sa->esn_hi); + seql = *rte_pktmbuf_mtod_offset(m_src, uint32_t *, + sizeof(struct rte_ipv4_hdr) + 4); + seql = rte_be_to_cpu_32(seql); + + if (!esn) + seq = (uint64_t)seql; + else { + seqh = anti_replay_get_seqh(winsz, seql, esn_hi, + esn_low); + seq = ((uint64_t)seqh << 32) | seql; + } + + if (unlikely(seq == 0)) + return IPSEC_ANTI_REPLAY_FAILED; + + ret = anti_replay_check(sa->replay, seq, winsz); + if (unlikely(ret)) { + otx2_err("Anti replay check failed"); + return IPSEC_ANTI_REPLAY_FAILED; + } + } + ret = process_inb_sa(op, sess, &qp->meta_info, (void **)&req); + } if (unlikely(ret)) { otx2_err("Crypto req : op %p, ret 0x%x", op, ret); @@ -673,6 +708,14 @@ otx2_cpt_enqueue_sec(struct otx2_cpt_qp *qp, struct rte_crypto_op *op, ret = otx2_cpt_enqueue_req(qp, pend_q, req, sess->cpt_inst_w7); + if (winsz && esn) { + seq_in_sa = ((uint64_t)esn_hi << 32) | esn_low; + if (seq > seq_in_sa) { + sa->esn_low = rte_cpu_to_be_32(seql); + sa->esn_hi = rte_cpu_to_be_32(seqh); + } + } + return ret; } diff --git a/drivers/crypto/octeontx2/otx2_cryptodev_sec.c b/drivers/crypto/octeontx2/otx2_cryptodev_sec.c index bad9c5ca9f..1f5645f2f1 100644 --- a/drivers/crypto/octeontx2/otx2_cryptodev_sec.c +++ b/drivers/crypto/octeontx2/otx2_cryptodev_sec.c @@ -213,6 +213,7 @@ crypto_sec_ipsec_outb_session_create(struct rte_cryptodev *crypto_dev, int ret; sess = get_sec_session_private_data(sec_sess); + sess->ipsec.dir = RTE_SECURITY_IPSEC_SA_DIR_EGRESS; lp = &sess->ipsec.lp; sa = &lp->out_sa; @@ -351,6 +352,7 @@ crypto_sec_ipsec_inb_session_create(struct rte_cryptodev *crypto_dev, int ret; sess = get_sec_session_private_data(sec_sess); + sess->ipsec.dir = RTE_SECURITY_IPSEC_SA_DIR_INGRESS; lp = &sess->ipsec.lp; sa = &lp->in_sa; @@ -362,6 +364,7 @@ crypto_sec_ipsec_inb_session_create(struct rte_cryptodev *crypto_dev, } memset(sa, 0, sizeof(struct otx2_ipsec_po_in_sa)); + sa->replay_win_sz = ipsec->replay_win_sz; ret = ipsec_po_sa_ctl_set(ipsec, crypto_xform, ctl); if (ret) @@ -414,6 +417,24 @@ crypto_sec_ipsec_inb_session_create(struct rte_cryptodev *crypto_dev, set_session_misc_attributes(lp, crypto_xform, auth_xform, cipher_xform); + if (sa->replay_win_sz) { + if (sa->replay_win_sz > OTX2_IPSEC_MAX_REPLAY_WIN_SZ) { + otx2_err("Replay window size is not supported"); + return -ENOTSUP; + } + sa->replay = rte_zmalloc(NULL, sizeof(struct otx2_ipsec_replay), + 0); + if (sa->replay == NULL) + return -ENOMEM; + + /* Set window bottom to 1, base and top to size of window */ + sa->replay->winb = 1; + sa->replay->wint = sa->replay_win_sz; + sa->replay->base = sa->replay_win_sz; + sa->esn_low = 0; + sa->esn_hi = 0; + } + return otx2_cpt_enq_sa_write(lp, crypto_dev->data->queue_pairs[0], OTX2_IPSEC_PO_WRITE_IPSEC_INB); } diff --git a/drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h b/drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h index d599692a75..b2b1f77284 100644 --- a/drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h +++ b/drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h @@ -204,4 +204,25 @@ cpt_ipsec_ip_antireplay_check(struct otx2_ipsec_fp_in_sa *sa, char *data) return ret; } + +static inline uint32_t +anti_replay_get_seqh(uint32_t winsz, uint32_t seql, + uint32_t esn_hi, uint32_t esn_low) +{ + uint32_t win_low = esn_low - winsz + 1; + + if (esn_low > winsz - 1) { + /* Window is in one sequence number subspace */ + if (seql > win_low) + return esn_hi; + else + return esn_hi + 1; + } else { + /* Window is split across two sequence number subspaces */ + if (seql > win_low) + return esn_hi - 1; + else + return esn_hi; + } +} #endif /* __OTX2_IPSEC_ANTI_REPLAY_H__ */ diff --git a/drivers/crypto/octeontx2/otx2_ipsec_po.h b/drivers/crypto/octeontx2/otx2_ipsec_po.h index da24f6a5d4..6d25e29734 100644 --- a/drivers/crypto/octeontx2/otx2_ipsec_po.h +++ b/drivers/crypto/octeontx2/otx2_ipsec_po.h @@ -161,6 +161,11 @@ struct otx2_ipsec_po_in_sa { uint8_t hmac_key[48]; struct otx2_ipsec_po_traffic_selector selector; } aes_gcm; + union { + struct otx2_ipsec_replay *replay; + uint64_t replay64; + }; + uint32_t replay_win_sz; }; struct otx2_ipsec_po_ip_template { diff --git a/drivers/crypto/octeontx2/otx2_ipsec_po_ops.h b/drivers/crypto/octeontx2/otx2_ipsec_po_ops.h index bc702d5c79..c0c936141d 100644 --- a/drivers/crypto/octeontx2/otx2_ipsec_po_ops.h +++ b/drivers/crypto/octeontx2/otx2_ipsec_po_ops.h @@ -124,6 +124,8 @@ process_outb_sa(struct rte_crypto_op *cop, req->ist.ei1 = rte_pktmbuf_iova(m_src); req->ist.ei2 = req->ist.ei1; + sa->esn_hi = sess->seq_hi; + hdr->seq = rte_cpu_to_be_32(sess->seq_lo); hdr->ip_id = rte_cpu_to_be_32(sess->ip_id); -- 2.20.1