Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
0002 /* Copyright (C) 2019 Netronome Systems, Inc. */
0003 
0004 #include <linux/bitfield.h>
0005 #include <linux/ipv6.h>
0006 #include <linux/skbuff.h>
0007 #include <linux/string.h>
0008 #include <net/inet6_hashtables.h>
0009 #include <net/tls.h>
0010 
0011 #include "../ccm.h"
0012 #include "../nfp_net.h"
0013 #include "crypto.h"
0014 #include "fw.h"
0015 
0016 #define NFP_NET_TLS_CCM_MBOX_OPS_MASK       \
0017     (BIT(NFP_CCM_TYPE_CRYPTO_RESET) |   \
0018      BIT(NFP_CCM_TYPE_CRYPTO_ADD) |     \
0019      BIT(NFP_CCM_TYPE_CRYPTO_DEL) |     \
0020      BIT(NFP_CCM_TYPE_CRYPTO_UPDATE))
0021 
0022 #define NFP_NET_TLS_OPCODE_MASK_RX          \
0023     BIT(NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_DEC)
0024 
0025 #define NFP_NET_TLS_OPCODE_MASK_TX          \
0026     BIT(NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_ENC)
0027 
0028 #define NFP_NET_TLS_OPCODE_MASK                     \
0029     (NFP_NET_TLS_OPCODE_MASK_RX | NFP_NET_TLS_OPCODE_MASK_TX)
0030 
0031 static void nfp_net_crypto_set_op(struct nfp_net *nn, u8 opcode, bool on)
0032 {
0033     u32 off, val;
0034 
0035     off = nn->tlv_caps.crypto_enable_off + round_down(opcode / 8, 4);
0036 
0037     val = nn_readl(nn, off);
0038     if (on)
0039         val |= BIT(opcode & 31);
0040     else
0041         val &= ~BIT(opcode & 31);
0042     nn_writel(nn, off, val);
0043 }
0044 
0045 static bool
0046 __nfp_net_tls_conn_cnt_changed(struct nfp_net *nn, int add,
0047                    enum tls_offload_ctx_dir direction)
0048 {
0049     u8 opcode;
0050     int cnt;
0051 
0052     if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
0053         opcode = NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_ENC;
0054         nn->ktls_tx_conn_cnt += add;
0055         cnt = nn->ktls_tx_conn_cnt;
0056         nn->dp.ktls_tx = !!nn->ktls_tx_conn_cnt;
0057     } else {
0058         opcode = NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_DEC;
0059         nn->ktls_rx_conn_cnt += add;
0060         cnt = nn->ktls_rx_conn_cnt;
0061     }
0062 
0063     /* Care only about 0 -> 1 and 1 -> 0 transitions */
0064     if (cnt > 1)
0065         return false;
0066 
0067     nfp_net_crypto_set_op(nn, opcode, cnt);
0068     return true;
0069 }
0070 
0071 static int
0072 nfp_net_tls_conn_cnt_changed(struct nfp_net *nn, int add,
0073                  enum tls_offload_ctx_dir direction)
0074 {
0075     int ret = 0;
0076 
0077     /* Use the BAR lock to protect the connection counts */
0078     nn_ctrl_bar_lock(nn);
0079     if (__nfp_net_tls_conn_cnt_changed(nn, add, direction)) {
0080         ret = __nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_CRYPTO);
0081         /* Undo the cnt adjustment if failed */
0082         if (ret)
0083             __nfp_net_tls_conn_cnt_changed(nn, -add, direction);
0084     }
0085     nn_ctrl_bar_unlock(nn);
0086 
0087     return ret;
0088 }
0089 
0090 static int
0091 nfp_net_tls_conn_add(struct nfp_net *nn, enum tls_offload_ctx_dir direction)
0092 {
0093     return nfp_net_tls_conn_cnt_changed(nn, 1, direction);
0094 }
0095 
0096 static int
0097 nfp_net_tls_conn_remove(struct nfp_net *nn, enum tls_offload_ctx_dir direction)
0098 {
0099     return nfp_net_tls_conn_cnt_changed(nn, -1, direction);
0100 }
0101 
0102 static struct sk_buff *
0103 nfp_net_tls_alloc_simple(struct nfp_net *nn, size_t req_sz, gfp_t flags)
0104 {
0105     return nfp_ccm_mbox_msg_alloc(nn, req_sz,
0106                       sizeof(struct nfp_crypto_reply_simple),
0107                       flags);
0108 }
0109 
0110 static int
0111 nfp_net_tls_communicate_simple(struct nfp_net *nn, struct sk_buff *skb,
0112                    const char *name, enum nfp_ccm_type type)
0113 {
0114     struct nfp_crypto_reply_simple *reply;
0115     int err;
0116 
0117     err = __nfp_ccm_mbox_communicate(nn, skb, type,
0118                      sizeof(*reply), sizeof(*reply),
0119                      type == NFP_CCM_TYPE_CRYPTO_DEL);
0120     if (err) {
0121         nn_dp_warn(&nn->dp, "failed to %s TLS: %d\n", name, err);
0122         return err;
0123     }
0124 
0125     reply = (void *)skb->data;
0126     err = -be32_to_cpu(reply->error);
0127     if (err)
0128         nn_dp_warn(&nn->dp, "failed to %s TLS, fw replied: %d\n",
0129                name, err);
0130     dev_consume_skb_any(skb);
0131 
0132     return err;
0133 }
0134 
0135 static void nfp_net_tls_del_fw(struct nfp_net *nn, __be32 *fw_handle)
0136 {
0137     struct nfp_crypto_req_del *req;
0138     struct sk_buff *skb;
0139 
0140     skb = nfp_net_tls_alloc_simple(nn, sizeof(*req), GFP_KERNEL);
0141     if (!skb)
0142         return;
0143 
0144     req = (void *)skb->data;
0145     req->ep_id = 0;
0146     memcpy(req->handle, fw_handle, sizeof(req->handle));
0147 
0148     nfp_net_tls_communicate_simple(nn, skb, "delete",
0149                        NFP_CCM_TYPE_CRYPTO_DEL);
0150 }
0151 
0152 static void
0153 nfp_net_tls_set_ipver_vlan(struct nfp_crypto_req_add_front *front, u8 ipver)
0154 {
0155     front->ipver_vlan = cpu_to_be16(FIELD_PREP(NFP_NET_TLS_IPVER, ipver) |
0156                     FIELD_PREP(NFP_NET_TLS_VLAN,
0157                            NFP_NET_TLS_VLAN_UNUSED));
0158 }
0159 
0160 static void
0161 nfp_net_tls_assign_conn_id(struct nfp_net *nn,
0162                struct nfp_crypto_req_add_front *front)
0163 {
0164     u32 len;
0165     u64 id;
0166 
0167     id = atomic64_inc_return(&nn->ktls_conn_id_gen);
0168     len = front->key_len - NFP_NET_TLS_NON_ADDR_KEY_LEN;
0169 
0170     memcpy(front->l3_addrs, &id, sizeof(id));
0171     memset(front->l3_addrs + sizeof(id), 0, len - sizeof(id));
0172 }
0173 
0174 static struct nfp_crypto_req_add_back *
0175 nfp_net_tls_set_ipv4(struct nfp_net *nn, struct nfp_crypto_req_add_v4 *req,
0176              struct sock *sk, int direction)
0177 {
0178     struct inet_sock *inet = inet_sk(sk);
0179 
0180     req->front.key_len += sizeof(__be32) * 2;
0181 
0182     if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
0183         nfp_net_tls_assign_conn_id(nn, &req->front);
0184     } else {
0185         req->src_ip = inet->inet_daddr;
0186         req->dst_ip = inet->inet_saddr;
0187     }
0188 
0189     return &req->back;
0190 }
0191 
0192 static struct nfp_crypto_req_add_back *
0193 nfp_net_tls_set_ipv6(struct nfp_net *nn, struct nfp_crypto_req_add_v6 *req,
0194              struct sock *sk, int direction)
0195 {
0196 #if IS_ENABLED(CONFIG_IPV6)
0197     struct ipv6_pinfo *np = inet6_sk(sk);
0198 
0199     req->front.key_len += sizeof(struct in6_addr) * 2;
0200 
0201     if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
0202         nfp_net_tls_assign_conn_id(nn, &req->front);
0203     } else {
0204         memcpy(req->src_ip, &sk->sk_v6_daddr, sizeof(req->src_ip));
0205         memcpy(req->dst_ip, &np->saddr, sizeof(req->dst_ip));
0206     }
0207 
0208 #endif
0209     return &req->back;
0210 }
0211 
0212 static void
0213 nfp_net_tls_set_l4(struct nfp_crypto_req_add_front *front,
0214            struct nfp_crypto_req_add_back *back, struct sock *sk,
0215            int direction)
0216 {
0217     struct inet_sock *inet = inet_sk(sk);
0218 
0219     front->l4_proto = IPPROTO_TCP;
0220 
0221     if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
0222         back->src_port = 0;
0223         back->dst_port = 0;
0224     } else {
0225         back->src_port = inet->inet_dport;
0226         back->dst_port = inet->inet_sport;
0227     }
0228 }
0229 
0230 static u8 nfp_tls_1_2_dir_to_opcode(enum tls_offload_ctx_dir direction)
0231 {
0232     switch (direction) {
0233     case TLS_OFFLOAD_CTX_DIR_TX:
0234         return NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_ENC;
0235     case TLS_OFFLOAD_CTX_DIR_RX:
0236         return NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_DEC;
0237     default:
0238         WARN_ON_ONCE(1);
0239         return 0;
0240     }
0241 }
0242 
0243 static bool
0244 nfp_net_cipher_supported(struct nfp_net *nn, u16 cipher_type,
0245              enum tls_offload_ctx_dir direction)
0246 {
0247     u8 bit;
0248 
0249     switch (cipher_type) {
0250     case TLS_CIPHER_AES_GCM_128:
0251         if (direction == TLS_OFFLOAD_CTX_DIR_TX)
0252             bit = NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_ENC;
0253         else
0254             bit = NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_DEC;
0255         break;
0256     default:
0257         return false;
0258     }
0259 
0260     return nn->tlv_caps.crypto_ops & BIT(bit);
0261 }
0262 
0263 static int
0264 nfp_net_tls_add(struct net_device *netdev, struct sock *sk,
0265         enum tls_offload_ctx_dir direction,
0266         struct tls_crypto_info *crypto_info,
0267         u32 start_offload_tcp_sn)
0268 {
0269     struct tls12_crypto_info_aes_gcm_128 *tls_ci;
0270     struct nfp_net *nn = netdev_priv(netdev);
0271     struct nfp_crypto_req_add_front *front;
0272     struct nfp_net_tls_offload_ctx *ntls;
0273     struct nfp_crypto_req_add_back *back;
0274     struct nfp_crypto_reply_add *reply;
0275     struct sk_buff *skb;
0276     size_t req_sz;
0277     void *req;
0278     bool ipv6;
0279     int err;
0280 
0281     BUILD_BUG_ON(sizeof(struct nfp_net_tls_offload_ctx) >
0282              TLS_DRIVER_STATE_SIZE_TX);
0283     BUILD_BUG_ON(offsetof(struct nfp_net_tls_offload_ctx, rx_end) >
0284              TLS_DRIVER_STATE_SIZE_RX);
0285 
0286     if (!nfp_net_cipher_supported(nn, crypto_info->cipher_type, direction))
0287         return -EOPNOTSUPP;
0288 
0289     switch (sk->sk_family) {
0290 #if IS_ENABLED(CONFIG_IPV6)
0291     case AF_INET6:
0292         if (ipv6_only_sock(sk) ||
0293             ipv6_addr_type(&sk->sk_v6_daddr) != IPV6_ADDR_MAPPED) {
0294             req_sz = sizeof(struct nfp_crypto_req_add_v6);
0295             ipv6 = true;
0296             break;
0297         }
0298         fallthrough;
0299 #endif
0300     case AF_INET:
0301         req_sz = sizeof(struct nfp_crypto_req_add_v4);
0302         ipv6 = false;
0303         break;
0304     default:
0305         return -EOPNOTSUPP;
0306     }
0307 
0308     err = nfp_net_tls_conn_add(nn, direction);
0309     if (err)
0310         return err;
0311 
0312     skb = nfp_ccm_mbox_msg_alloc(nn, req_sz, sizeof(*reply), GFP_KERNEL);
0313     if (!skb) {
0314         err = -ENOMEM;
0315         goto err_conn_remove;
0316     }
0317 
0318     front = (void *)skb->data;
0319     front->ep_id = 0;
0320     front->key_len = NFP_NET_TLS_NON_ADDR_KEY_LEN;
0321     front->opcode = nfp_tls_1_2_dir_to_opcode(direction);
0322     memset(front->resv, 0, sizeof(front->resv));
0323 
0324     nfp_net_tls_set_ipver_vlan(front, ipv6 ? 6 : 4);
0325 
0326     req = (void *)skb->data;
0327     if (ipv6)
0328         back = nfp_net_tls_set_ipv6(nn, req, sk, direction);
0329     else
0330         back = nfp_net_tls_set_ipv4(nn, req, sk, direction);
0331 
0332     nfp_net_tls_set_l4(front, back, sk, direction);
0333 
0334     back->counter = 0;
0335     back->tcp_seq = cpu_to_be32(start_offload_tcp_sn);
0336 
0337     tls_ci = (struct tls12_crypto_info_aes_gcm_128 *)crypto_info;
0338     memcpy(back->key, tls_ci->key, TLS_CIPHER_AES_GCM_128_KEY_SIZE);
0339     memset(&back->key[TLS_CIPHER_AES_GCM_128_KEY_SIZE / 4], 0,
0340            sizeof(back->key) - TLS_CIPHER_AES_GCM_128_KEY_SIZE);
0341     memcpy(back->iv, tls_ci->iv, TLS_CIPHER_AES_GCM_128_IV_SIZE);
0342     memcpy(&back->salt, tls_ci->salt, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
0343     memcpy(back->rec_no, tls_ci->rec_seq, sizeof(tls_ci->rec_seq));
0344 
0345     /* Get an extra ref on the skb so we can wipe the key after */
0346     skb_get(skb);
0347 
0348     err = nfp_ccm_mbox_communicate(nn, skb, NFP_CCM_TYPE_CRYPTO_ADD,
0349                        sizeof(*reply), sizeof(*reply));
0350     reply = (void *)skb->data;
0351 
0352     /* We depend on CCM MBOX code not reallocating skb we sent
0353      * so we can clear the key material out of the memory.
0354      */
0355     if (!WARN_ON_ONCE((u8 *)back < skb->head ||
0356               (u8 *)back > skb_end_pointer(skb)) &&
0357         !WARN_ON_ONCE((u8 *)&reply[1] > (u8 *)back))
0358         memzero_explicit(back, sizeof(*back));
0359     dev_consume_skb_any(skb); /* the extra ref from skb_get() above */
0360 
0361     if (err) {
0362         nn_dp_warn(&nn->dp, "failed to add TLS: %d (%d)\n",
0363                err, direction == TLS_OFFLOAD_CTX_DIR_TX);
0364         /* communicate frees skb on error */
0365         goto err_conn_remove;
0366     }
0367 
0368     err = -be32_to_cpu(reply->error);
0369     if (err) {
0370         if (err == -ENOSPC) {
0371             if (!atomic_fetch_inc(&nn->ktls_no_space))
0372                 nn_info(nn, "HW TLS table full\n");
0373         } else {
0374             nn_dp_warn(&nn->dp,
0375                    "failed to add TLS, FW replied: %d\n", err);
0376         }
0377         goto err_free_skb;
0378     }
0379 
0380     if (!reply->handle[0] && !reply->handle[1]) {
0381         nn_dp_warn(&nn->dp, "FW returned NULL handle\n");
0382         err = -EINVAL;
0383         goto err_fw_remove;
0384     }
0385 
0386     ntls = tls_driver_ctx(sk, direction);
0387     memcpy(ntls->fw_handle, reply->handle, sizeof(ntls->fw_handle));
0388     if (direction == TLS_OFFLOAD_CTX_DIR_TX)
0389         ntls->next_seq = start_offload_tcp_sn;
0390     dev_consume_skb_any(skb);
0391 
0392     if (direction == TLS_OFFLOAD_CTX_DIR_TX)
0393         return 0;
0394 
0395     if (!nn->tlv_caps.tls_resync_ss)
0396         tls_offload_rx_resync_set_type(sk, TLS_OFFLOAD_SYNC_TYPE_CORE_NEXT_HINT);
0397 
0398     return 0;
0399 
0400 err_fw_remove:
0401     nfp_net_tls_del_fw(nn, reply->handle);
0402 err_free_skb:
0403     dev_consume_skb_any(skb);
0404 err_conn_remove:
0405     nfp_net_tls_conn_remove(nn, direction);
0406     return err;
0407 }
0408 
0409 static void
0410 nfp_net_tls_del(struct net_device *netdev, struct tls_context *tls_ctx,
0411         enum tls_offload_ctx_dir direction)
0412 {
0413     struct nfp_net *nn = netdev_priv(netdev);
0414     struct nfp_net_tls_offload_ctx *ntls;
0415 
0416     nfp_net_tls_conn_remove(nn, direction);
0417 
0418     ntls = __tls_driver_ctx(tls_ctx, direction);
0419     nfp_net_tls_del_fw(nn, ntls->fw_handle);
0420 }
0421 
0422 static int
0423 nfp_net_tls_resync(struct net_device *netdev, struct sock *sk, u32 seq,
0424            u8 *rcd_sn, enum tls_offload_ctx_dir direction)
0425 {
0426     struct nfp_net *nn = netdev_priv(netdev);
0427     struct nfp_net_tls_offload_ctx *ntls;
0428     struct nfp_crypto_req_update *req;
0429     enum nfp_ccm_type type;
0430     struct sk_buff *skb;
0431     gfp_t flags;
0432     int err;
0433 
0434     flags = direction == TLS_OFFLOAD_CTX_DIR_TX ? GFP_KERNEL : GFP_ATOMIC;
0435     skb = nfp_net_tls_alloc_simple(nn, sizeof(*req), flags);
0436     if (!skb)
0437         return -ENOMEM;
0438 
0439     ntls = tls_driver_ctx(sk, direction);
0440     req = (void *)skb->data;
0441     req->ep_id = 0;
0442     req->opcode = nfp_tls_1_2_dir_to_opcode(direction);
0443     memset(req->resv, 0, sizeof(req->resv));
0444     memcpy(req->handle, ntls->fw_handle, sizeof(ntls->fw_handle));
0445     req->tcp_seq = cpu_to_be32(seq);
0446     memcpy(req->rec_no, rcd_sn, sizeof(req->rec_no));
0447 
0448     type = NFP_CCM_TYPE_CRYPTO_UPDATE;
0449     if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
0450         err = nfp_net_tls_communicate_simple(nn, skb, "sync", type);
0451         if (err)
0452             return err;
0453         ntls->next_seq = seq;
0454     } else {
0455         if (nn->tlv_caps.tls_resync_ss)
0456             type = NFP_CCM_TYPE_CRYPTO_RESYNC;
0457         nfp_ccm_mbox_post(nn, skb, type,
0458                   sizeof(struct nfp_crypto_reply_simple));
0459         atomic_inc(&nn->ktls_rx_resync_sent);
0460     }
0461 
0462     return 0;
0463 }
0464 
0465 static const struct tlsdev_ops nfp_net_tls_ops = {
0466     .tls_dev_add = nfp_net_tls_add,
0467     .tls_dev_del = nfp_net_tls_del,
0468     .tls_dev_resync = nfp_net_tls_resync,
0469 };
0470 
0471 int nfp_net_tls_rx_resync_req(struct net_device *netdev,
0472                   struct nfp_net_tls_resync_req *req,
0473                   void *pkt, unsigned int pkt_len)
0474 {
0475     struct nfp_net *nn = netdev_priv(netdev);
0476     struct nfp_net_tls_offload_ctx *ntls;
0477     struct ipv6hdr *ipv6h;
0478     struct tcphdr *th;
0479     struct iphdr *iph;
0480     struct sock *sk;
0481     __be32 tcp_seq;
0482     int err;
0483 
0484     iph = pkt + req->l3_offset;
0485     ipv6h = pkt + req->l3_offset;
0486     th = pkt + req->l4_offset;
0487 
0488     if ((u8 *)&th[1] > (u8 *)pkt + pkt_len) {
0489         netdev_warn_once(netdev, "invalid TLS RX resync request (l3_off: %hhu l4_off: %hhu pkt_len: %u)\n",
0490                  req->l3_offset, req->l4_offset, pkt_len);
0491         err = -EINVAL;
0492         goto err_cnt_ign;
0493     }
0494 
0495     switch (ipv6h->version) {
0496     case 4:
0497         sk = inet_lookup_established(dev_net(netdev), &tcp_hashinfo,
0498                          iph->saddr, th->source, iph->daddr,
0499                          th->dest, netdev->ifindex);
0500         break;
0501 #if IS_ENABLED(CONFIG_IPV6)
0502     case 6:
0503         sk = __inet6_lookup_established(dev_net(netdev), &tcp_hashinfo,
0504                         &ipv6h->saddr, th->source,
0505                         &ipv6h->daddr, ntohs(th->dest),
0506                         netdev->ifindex, 0);
0507         break;
0508 #endif
0509     default:
0510         netdev_warn_once(netdev, "invalid TLS RX resync request (l3_off: %hhu l4_off: %hhu ipver: %u)\n",
0511                  req->l3_offset, req->l4_offset, iph->version);
0512         err = -EINVAL;
0513         goto err_cnt_ign;
0514     }
0515 
0516     err = 0;
0517     if (!sk)
0518         goto err_cnt_ign;
0519     if (!tls_is_sk_rx_device_offloaded(sk) ||
0520         sk->sk_shutdown & RCV_SHUTDOWN)
0521         goto err_put_sock;
0522 
0523     ntls = tls_driver_ctx(sk, TLS_OFFLOAD_CTX_DIR_RX);
0524     /* some FW versions can't report the handle and report 0s */
0525     if (memchr_inv(&req->fw_handle, 0, sizeof(req->fw_handle)) &&
0526         memcmp(&req->fw_handle, &ntls->fw_handle, sizeof(ntls->fw_handle)))
0527         goto err_put_sock;
0528 
0529     /* copy to ensure alignment */
0530     memcpy(&tcp_seq, &req->tcp_seq, sizeof(tcp_seq));
0531     tls_offload_rx_resync_request(sk, tcp_seq);
0532     atomic_inc(&nn->ktls_rx_resync_req);
0533 
0534     sock_gen_put(sk);
0535     return 0;
0536 
0537 err_put_sock:
0538     sock_gen_put(sk);
0539 err_cnt_ign:
0540     atomic_inc(&nn->ktls_rx_resync_ign);
0541     return err;
0542 }
0543 
0544 static int nfp_net_tls_reset(struct nfp_net *nn)
0545 {
0546     struct nfp_crypto_req_reset *req;
0547     struct sk_buff *skb;
0548 
0549     skb = nfp_net_tls_alloc_simple(nn, sizeof(*req), GFP_KERNEL);
0550     if (!skb)
0551         return -ENOMEM;
0552 
0553     req = (void *)skb->data;
0554     req->ep_id = 0;
0555 
0556     return nfp_net_tls_communicate_simple(nn, skb, "reset",
0557                           NFP_CCM_TYPE_CRYPTO_RESET);
0558 }
0559 
0560 int nfp_net_tls_init(struct nfp_net *nn)
0561 {
0562     struct net_device *netdev = nn->dp.netdev;
0563     int err;
0564 
0565     if (!(nn->tlv_caps.crypto_ops & NFP_NET_TLS_OPCODE_MASK))
0566         return 0;
0567 
0568     if ((nn->tlv_caps.mbox_cmsg_types & NFP_NET_TLS_CCM_MBOX_OPS_MASK) !=
0569         NFP_NET_TLS_CCM_MBOX_OPS_MASK)
0570         return 0;
0571 
0572     if (!nfp_ccm_mbox_fits(nn, sizeof(struct nfp_crypto_req_add_v6))) {
0573         nn_warn(nn, "disabling TLS offload - mbox too small: %d\n",
0574             nn->tlv_caps.mbox_len);
0575         return 0;
0576     }
0577 
0578     err = nfp_net_tls_reset(nn);
0579     if (err)
0580         return err;
0581 
0582     nn_ctrl_bar_lock(nn);
0583     nn_writel(nn, nn->tlv_caps.crypto_enable_off, 0);
0584     err = __nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_CRYPTO);
0585     nn_ctrl_bar_unlock(nn);
0586     if (err)
0587         return err;
0588 
0589     if (nn->tlv_caps.crypto_ops & NFP_NET_TLS_OPCODE_MASK_RX) {
0590         netdev->hw_features |= NETIF_F_HW_TLS_RX;
0591         netdev->features |= NETIF_F_HW_TLS_RX;
0592     }
0593     if (nn->tlv_caps.crypto_ops & NFP_NET_TLS_OPCODE_MASK_TX) {
0594         netdev->hw_features |= NETIF_F_HW_TLS_TX;
0595         netdev->features |= NETIF_F_HW_TLS_TX;
0596     }
0597 
0598     netdev->tlsdev_ops = &nfp_net_tls_ops;
0599 
0600     return 0;
0601 }