crypto/octeontx2: support IPsec ESN and anti-replay

Adding ESN and anti-replay support for lookaside IPsec.

Signed-off-by: Tejasree Kondoj <ktejasree@marvell.com>
Acked-by: Anoob Joseph <anoobj@marvell.com>
This commit is contained in:
Tejasree Kondoj 2020-12-18 19:44:10 +05:30 committed by Akhil Goyal
parent cc882d6469
commit 5be562bc5b
7 changed files with 101 additions and 2 deletions

View File

@ -175,4 +175,6 @@ Features supported
* IPv6 * IPv6
* ESP * ESP
* Tunnel mode * Tunnel mode
* ESN
* Anti-replay
* AES-128/192/256-GCM * AES-128/192/256-GCM

View File

@ -76,6 +76,11 @@ New Features
* Added inner UDP/IPv4 support for VXLAN IPv4 GSO. * 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 Removed Items
------------- -------------

View File

@ -14,6 +14,7 @@
#include "otx2_cryptodev_mbox.h" #include "otx2_cryptodev_mbox.h"
#include "otx2_cryptodev_ops.h" #include "otx2_cryptodev_ops.h"
#include "otx2_cryptodev_ops_helper.h" #include "otx2_cryptodev_ops_helper.h"
#include "otx2_ipsec_anti_replay.h"
#include "otx2_ipsec_po_ops.h" #include "otx2_ipsec_po_ops.h"
#include "otx2_mbox.h" #include "otx2_mbox.h"
#include "otx2_sec_idev.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, otx2_cpt_enqueue_sec(struct otx2_cpt_qp *qp, struct rte_crypto_op *op,
struct pending_queue *pend_q) 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_sec_session_ipsec_lp *sess;
struct otx2_ipsec_po_sa_ctl *ctl_wrd; struct otx2_ipsec_po_sa_ctl *ctl_wrd;
struct otx2_ipsec_po_in_sa *sa;
struct otx2_sec_session *priv; struct otx2_sec_session *priv;
struct cpt_request_info *req; struct cpt_request_info *req;
uint64_t seq_in_sa, seq = 0;
uint8_t esn;
int ret; int ret;
priv = get_sec_session_private_data(op->sym->sec_session); priv = get_sec_session_private_data(op->sym->sec_session);
sess = &priv->ipsec.lp; 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) if (ctl_wrd->direction == OTX2_IPSEC_PO_SA_DIRECTION_OUTBOUND)
ret = process_outb_sa(op, sess, &qp->meta_info, (void **)&req); 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); ret = process_inb_sa(op, sess, &qp->meta_info, (void **)&req);
}
if (unlikely(ret)) { if (unlikely(ret)) {
otx2_err("Crypto req : op %p, ret 0x%x", op, 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); 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; return ret;
} }

View File

@ -213,6 +213,7 @@ crypto_sec_ipsec_outb_session_create(struct rte_cryptodev *crypto_dev,
int ret; int ret;
sess = get_sec_session_private_data(sec_sess); sess = get_sec_session_private_data(sec_sess);
sess->ipsec.dir = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
lp = &sess->ipsec.lp; lp = &sess->ipsec.lp;
sa = &lp->out_sa; sa = &lp->out_sa;
@ -351,6 +352,7 @@ crypto_sec_ipsec_inb_session_create(struct rte_cryptodev *crypto_dev,
int ret; int ret;
sess = get_sec_session_private_data(sec_sess); sess = get_sec_session_private_data(sec_sess);
sess->ipsec.dir = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
lp = &sess->ipsec.lp; lp = &sess->ipsec.lp;
sa = &lp->in_sa; 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)); 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); ret = ipsec_po_sa_ctl_set(ipsec, crypto_xform, ctl);
if (ret) if (ret)
@ -414,6 +417,24 @@ crypto_sec_ipsec_inb_session_create(struct rte_cryptodev *crypto_dev,
set_session_misc_attributes(lp, crypto_xform, set_session_misc_attributes(lp, crypto_xform,
auth_xform, cipher_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], return otx2_cpt_enq_sa_write(lp, crypto_dev->data->queue_pairs[0],
OTX2_IPSEC_PO_WRITE_IPSEC_INB); OTX2_IPSEC_PO_WRITE_IPSEC_INB);
} }

View File

@ -204,4 +204,25 @@ cpt_ipsec_ip_antireplay_check(struct otx2_ipsec_fp_in_sa *sa, char *data)
return ret; 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__ */ #endif /* __OTX2_IPSEC_ANTI_REPLAY_H__ */

View File

@ -161,6 +161,11 @@ struct otx2_ipsec_po_in_sa {
uint8_t hmac_key[48]; uint8_t hmac_key[48];
struct otx2_ipsec_po_traffic_selector selector; struct otx2_ipsec_po_traffic_selector selector;
} aes_gcm; } aes_gcm;
union {
struct otx2_ipsec_replay *replay;
uint64_t replay64;
};
uint32_t replay_win_sz;
}; };
struct otx2_ipsec_po_ip_template { struct otx2_ipsec_po_ip_template {

View File

@ -124,6 +124,8 @@ process_outb_sa(struct rte_crypto_op *cop,
req->ist.ei1 = rte_pktmbuf_iova(m_src); req->ist.ei1 = rte_pktmbuf_iova(m_src);
req->ist.ei2 = req->ist.ei1; req->ist.ei2 = req->ist.ei1;
sa->esn_hi = sess->seq_hi;
hdr->seq = rte_cpu_to_be_32(sess->seq_lo); hdr->seq = rte_cpu_to_be_32(sess->seq_lo);
hdr->ip_id = rte_cpu_to_be_32(sess->ip_id); hdr->ip_id = rte_cpu_to_be_32(sess->ip_id);