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:
parent
cc882d6469
commit
5be562bc5b
@ -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
|
||||||
|
@ -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
|
||||||
-------------
|
-------------
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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__ */
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user