X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fcrypto%2Focteontx2%2Fotx2_cryptodev_sec.c;h=a5db40047d0f10ad161ef614858478e281df8c09;hb=26590b5200bb1d6bdfa931f8615339d049d13881;hp=b80ec7bff2e4fb94c2be6ff0ac1dedba4ece8e6f;hpb=4edede7bc6ee15d2d563c91c5ce47bd7567b1c90;p=dpdk.git diff --git a/drivers/crypto/octeontx2/otx2_cryptodev_sec.c b/drivers/crypto/octeontx2/otx2_cryptodev_sec.c index b80ec7bff2..a5db40047d 100644 --- a/drivers/crypto/octeontx2/otx2_cryptodev_sec.c +++ b/drivers/crypto/octeontx2/otx2_cryptodev_sec.c @@ -25,12 +25,15 @@ ipsec_lp_len_precalc(struct rte_security_ipsec_xform *ipsec, { struct rte_crypto_sym_xform *cipher_xform, *auth_xform; - if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) - lp->partial_len = sizeof(struct rte_ipv4_hdr); - else if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV6) - lp->partial_len = sizeof(struct rte_ipv6_hdr); - else - return -EINVAL; + lp->partial_len = 0; + if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) { + if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) + lp->partial_len = sizeof(struct rte_ipv4_hdr); + else if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV6) + lp->partial_len = sizeof(struct rte_ipv6_hdr); + else + return -EINVAL; + } if (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP) { lp->partial_len += sizeof(struct rte_esp_hdr); @@ -74,6 +77,8 @@ ipsec_lp_len_precalc(struct rte_security_ipsec_xform *ipsec, if (auth_xform->auth.algo == RTE_CRYPTO_AUTH_SHA1_HMAC) lp->partial_len += OTX2_SEC_SHA1_HMAC_LEN; + else if (auth_xform->auth.algo == RTE_CRYPTO_AUTH_SHA256_HMAC) + lp->partial_len += OTX2_SEC_SHA2_HMAC_LEN; else return -EINVAL; @@ -201,6 +206,7 @@ crypto_sec_ipsec_outb_session_create(struct rte_cryptodev *crypto_dev, struct rte_security_session *sec_sess) { struct rte_crypto_sym_xform *auth_xform, *cipher_xform; + struct otx2_ipsec_po_ip_template *template = NULL; const uint8_t *cipher_key, *auth_key; struct otx2_sec_session_ipsec_lp *lp; struct otx2_ipsec_po_sa_ctl *ctl; @@ -210,9 +216,10 @@ crypto_sec_ipsec_outb_session_create(struct rte_cryptodev *crypto_dev, struct otx2_cpt_inst_s inst; struct rte_ipv6_hdr *ip6; struct rte_ipv4_hdr *ip; - int ret; + int ret, ctx_len; 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; @@ -225,10 +232,10 @@ crypto_sec_ipsec_outb_session_create(struct rte_cryptodev *crypto_dev, memset(sa, 0, sizeof(struct otx2_ipsec_po_out_sa)); /* Initialize lookaside ipsec private data */ + lp->mode_type = OTX2_IPSEC_PO_TRANSPORT; lp->ip_id = 0; lp->seq_lo = 1; lp->seq_hi = 0; - lp->tunnel_type = ipsec->tunnel.type; ret = ipsec_po_sa_ctl_set(ipsec, crypto_xform, ctl); if (ret) @@ -238,21 +245,48 @@ crypto_sec_ipsec_outb_session_create(struct rte_cryptodev *crypto_dev, if (ret) return ret; - memcpy(sa->iv.gcm.nonce, &ipsec->salt, 4); - + /* Start ip id from 1 */ + lp->ip_id = 1; + + if (ctl->enc_type == OTX2_IPSEC_PO_SA_ENC_AES_GCM) { + template = &sa->aes_gcm.template; + ctx_len = offsetof(struct otx2_ipsec_po_out_sa, + aes_gcm.template) + sizeof( + sa->aes_gcm.template.ip4); + ctx_len = RTE_ALIGN_CEIL(ctx_len, 8); + lp->ctx_len = ctx_len >> 3; + } else if (ctl->auth_type == + OTX2_IPSEC_PO_SA_AUTH_SHA1) { + template = &sa->sha1.template; + ctx_len = offsetof(struct otx2_ipsec_po_out_sa, + sha1.template) + sizeof( + sa->sha1.template.ip4); + ctx_len = RTE_ALIGN_CEIL(ctx_len, 8); + lp->ctx_len = ctx_len >> 3; + } else if (ctl->auth_type == + OTX2_IPSEC_PO_SA_AUTH_SHA2_256) { + template = &sa->sha2.template; + ctx_len = offsetof(struct otx2_ipsec_po_out_sa, + sha2.template) + sizeof( + sa->sha2.template.ip4); + ctx_len = RTE_ALIGN_CEIL(ctx_len, 8); + lp->ctx_len = ctx_len >> 3; + } else { + return -EINVAL; + } + ip = &template->ip4.ipv4_hdr; if (ipsec->options.udp_encap) { - sa->udp_src = 4500; - sa->udp_dst = 4500; + ip->next_proto_id = IPPROTO_UDP; + template->ip4.udp_src = rte_be_to_cpu_16(4500); + template->ip4.udp_dst = rte_be_to_cpu_16(4500); + } else { + ip->next_proto_id = IPPROTO_ESP; } if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) { - /* Start ip id from 1 */ - lp->ip_id = 1; - if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) { - ip = &sa->template.ipv4_hdr; + lp->mode_type = OTX2_IPSEC_PO_TUNNEL_IPV4; ip->version_ihl = RTE_IPV4_VHL_DEF; - ip->next_proto_id = IPPROTO_ESP; ip->time_to_live = ipsec->tunnel.ipv4.ttl; ip->type_of_service |= (ipsec->tunnel.ipv4.dscp << 2); if (ipsec->tunnel.ipv4.df) @@ -263,7 +297,45 @@ crypto_sec_ipsec_outb_session_create(struct rte_cryptodev *crypto_dev, sizeof(struct in_addr)); } else if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV6) { - ip6 = &sa->template.ipv6_hdr; + + lp->mode_type = OTX2_IPSEC_PO_TUNNEL_IPV6; + if (ctl->enc_type == OTX2_IPSEC_PO_SA_ENC_AES_GCM) { + template = &sa->aes_gcm.template; + ctx_len = offsetof(struct otx2_ipsec_po_out_sa, + aes_gcm.template) + sizeof( + sa->aes_gcm.template.ip6); + ctx_len = RTE_ALIGN_CEIL(ctx_len, 8); + lp->ctx_len = ctx_len >> 3; + } else if (ctl->auth_type == + OTX2_IPSEC_PO_SA_AUTH_SHA1) { + template = &sa->sha1.template; + ctx_len = offsetof(struct otx2_ipsec_po_out_sa, + sha1.template) + sizeof( + sa->sha1.template.ip6); + ctx_len = RTE_ALIGN_CEIL(ctx_len, 8); + lp->ctx_len = ctx_len >> 3; + } else if (ctl->auth_type == + OTX2_IPSEC_PO_SA_AUTH_SHA2_256) { + template = &sa->sha2.template; + ctx_len = offsetof(struct otx2_ipsec_po_out_sa, + sha2.template) + sizeof( + sa->sha2.template.ip6); + ctx_len = RTE_ALIGN_CEIL(ctx_len, 8); + lp->ctx_len = ctx_len >> 3; + } else { + return -EINVAL; + } + + ip6 = &template->ip6.ipv6_hdr; + if (ipsec->options.udp_encap) { + ip6->proto = IPPROTO_UDP; + template->ip6.udp_src = rte_be_to_cpu_16(4500); + template->ip6.udp_dst = rte_be_to_cpu_16(4500); + } else { + ip6->proto = (ipsec->proto == + RTE_SECURITY_IPSEC_SA_PROTO_ESP) ? + IPPROTO_ESP : IPPROTO_AH; + } ip6->vtc_flow = rte_cpu_to_be_32(0x60000000 | ((ipsec->tunnel.ipv6.dscp << RTE_IPV6_HDR_TC_SHIFT) & @@ -272,18 +344,11 @@ crypto_sec_ipsec_outb_session_create(struct rte_cryptodev *crypto_dev, RTE_IPV6_HDR_FL_SHIFT) & RTE_IPV6_HDR_FL_MASK)); ip6->hop_limits = ipsec->tunnel.ipv6.hlimit; - ip6->proto = (ipsec->proto == - RTE_SECURITY_IPSEC_SA_PROTO_ESP) ? - IPPROTO_ESP : IPPROTO_AH; memcpy(&ip6->src_addr, &ipsec->tunnel.ipv6.src_addr, sizeof(struct in6_addr)); memcpy(&ip6->dst_addr, &ipsec->tunnel.ipv6.dst_addr, sizeof(struct in6_addr)); - } else { - return -EINVAL; } - } else { - return -EINVAL; } cipher_xform = crypto_xform; @@ -293,21 +358,20 @@ crypto_sec_ipsec_outb_session_create(struct rte_cryptodev *crypto_dev, auth_key_len = 0; if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) { + if (crypto_xform->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) + memcpy(sa->iv.gcm.nonce, &ipsec->salt, 4); cipher_key = crypto_xform->aead.key.data; cipher_key_len = crypto_xform->aead.key.length; - - lp->ctx_len = sizeof(struct otx2_ipsec_po_out_sa); - lp->ctx_len >>= 3; - RTE_ASSERT(lp->ctx_len == OTX2_IPSEC_PO_AES_GCM_OUTB_CTX_LEN); } else { cipher_key = cipher_xform->cipher.key.data; cipher_key_len = cipher_xform->cipher.key.length; auth_key = auth_xform->auth.key.data; auth_key_len = auth_xform->auth.key.length; - /* TODO: check the ctx len for supporting ALGO */ - lp->ctx_len = sizeof(struct otx2_ipsec_po_out_sa) >> 3; - RTE_ASSERT(lp->ctx_len == OTX2_IPSEC_PO_MAX_OUTB_CTX_LEN); + if (auth_xform->auth.algo == RTE_CRYPTO_AUTH_SHA1_HMAC) + memcpy(sa->sha1.hmac_key, auth_key, auth_key_len); + else if (auth_xform->auth.algo == RTE_CRYPTO_AUTH_SHA256_HMAC) + memcpy(sa->sha2.hmac_key, auth_key, auth_key_len); } if (cipher_key_len != 0) @@ -315,15 +379,11 @@ crypto_sec_ipsec_outb_session_create(struct rte_cryptodev *crypto_dev, else return -EINVAL; - /* Use OPAD & IPAD */ - RTE_SET_USED(auth_key); - RTE_SET_USED(auth_key_len); - inst.u64[7] = 0; inst.egrp = OTX2_CPT_EGRP_SE; inst.cptr = rte_mempool_virt2iova(sa); - lp->ucmd_w3 = inst.u64[7]; + lp->cpt_inst_w7 = inst.u64[7]; lp->ucmd_opcode = (lp->ctx_len << 8) | (OTX2_IPSEC_PO_PROCESS_IPSEC_OUTB); @@ -341,9 +401,9 @@ crypto_sec_ipsec_inb_session_create(struct rte_cryptodev *crypto_dev, struct rte_security_session *sec_sess) { struct rte_crypto_sym_xform *auth_xform, *cipher_xform; + const uint8_t *cipher_key, *auth_key; struct otx2_sec_session_ipsec_lp *lp; struct otx2_ipsec_po_sa_ctl *ctl; - const uint8_t *cipher_key, *auth_key; int cipher_key_len, auth_key_len; struct otx2_ipsec_po_in_sa *sa; struct otx2_sec_session *sess; @@ -351,6 +411,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,18 +423,26 @@ 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) return ret; - lp->tunnel_type = ipsec->tunnel.type; + lp->mode_type = OTX2_IPSEC_PO_TRANSPORT; + auth_xform = crypto_xform; cipher_xform = crypto_xform->next; cipher_key_len = 0; auth_key_len = 0; + if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) + lp->mode_type = (ipsec->tunnel.type == + RTE_SECURITY_IPSEC_TUNNEL_IPV4) ? + OTX2_IPSEC_PO_TUNNEL_IPV4 : + OTX2_IPSEC_PO_TUNNEL_IPV6; + if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) { if (crypto_xform->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) memcpy(sa->iv.gcm.nonce, &ipsec->salt, 4); @@ -389,9 +458,16 @@ crypto_sec_ipsec_inb_session_create(struct rte_cryptodev *crypto_dev, auth_key = auth_xform->auth.key.data; auth_key_len = auth_xform->auth.key.length; - /* TODO: check the ctx len for supporting ALGO */ - lp->ctx_len = sizeof(struct otx2_ipsec_po_in_sa) >> 2; - RTE_ASSERT(lp->ctx_len == OTX2_IPSEC_PO_MAX_INB_CTX_LEN); + if (auth_xform->auth.algo == RTE_CRYPTO_AUTH_SHA1_HMAC) { + memcpy(sa->aes_gcm.hmac_key, auth_key, auth_key_len); + lp->ctx_len = offsetof(struct otx2_ipsec_po_in_sa, + aes_gcm.selector) >> 3; + } else if (auth_xform->auth.algo == + RTE_CRYPTO_AUTH_SHA256_HMAC) { + memcpy(sa->sha2.hmac_key, auth_key, auth_key_len); + lp->ctx_len = offsetof(struct otx2_ipsec_po_in_sa, + sha2.selector) >> 3; + } } if (cipher_key_len != 0) @@ -399,21 +475,35 @@ crypto_sec_ipsec_inb_session_create(struct rte_cryptodev *crypto_dev, else return -EINVAL; - /* Use OPAD & IPAD */ - RTE_SET_USED(auth_key); - RTE_SET_USED(auth_key_len); - inst.u64[7] = 0; inst.egrp = OTX2_CPT_EGRP_SE; inst.cptr = rte_mempool_virt2iova(sa); - lp->ucmd_w3 = inst.u64[7]; + lp->cpt_inst_w7 = inst.u64[7]; lp->ucmd_opcode = (lp->ctx_len << 8) | (OTX2_IPSEC_PO_PROCESS_IPSEC_INB); 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); } @@ -455,6 +545,9 @@ otx2_crypto_sec_session_create(void *device, if (conf->action_type != RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL) return -ENOTSUP; + if (rte_security_dynfield_register() < 0) + return -rte_errno; + if (rte_mempool_get(mempool, (void **)&priv)) { otx2_err("Could not allocate security session private data"); return -ENOMEM; @@ -496,6 +589,8 @@ otx2_crypto_sec_session_destroy(void *device __rte_unused, sess_mp = rte_mempool_from_obj(priv); + memset(priv, 0, sizeof(*priv)); + set_sec_session_private_data(sess, NULL); rte_mempool_put(sess_mp, priv); @@ -514,7 +609,7 @@ otx2_crypto_sec_set_pkt_mdata(void *device __rte_unused, struct rte_mbuf *m, void *params __rte_unused) { /* Set security session as the pkt metadata */ - m->udata64 = (uint64_t)session; + *rte_security_dynfield(m) = (rte_security_dynfield_t)session; return 0; }