tls.c (15587B)
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2/* Copyright (C) 2019 Netronome Systems, Inc. */ 3 4#include <linux/bitfield.h> 5#include <linux/ipv6.h> 6#include <linux/skbuff.h> 7#include <linux/string.h> 8#include <net/inet6_hashtables.h> 9#include <net/tls.h> 10 11#include "../ccm.h" 12#include "../nfp_net.h" 13#include "crypto.h" 14#include "fw.h" 15 16#define NFP_NET_TLS_CCM_MBOX_OPS_MASK \ 17 (BIT(NFP_CCM_TYPE_CRYPTO_RESET) | \ 18 BIT(NFP_CCM_TYPE_CRYPTO_ADD) | \ 19 BIT(NFP_CCM_TYPE_CRYPTO_DEL) | \ 20 BIT(NFP_CCM_TYPE_CRYPTO_UPDATE)) 21 22#define NFP_NET_TLS_OPCODE_MASK_RX \ 23 BIT(NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_DEC) 24 25#define NFP_NET_TLS_OPCODE_MASK_TX \ 26 BIT(NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_ENC) 27 28#define NFP_NET_TLS_OPCODE_MASK \ 29 (NFP_NET_TLS_OPCODE_MASK_RX | NFP_NET_TLS_OPCODE_MASK_TX) 30 31static void nfp_net_crypto_set_op(struct nfp_net *nn, u8 opcode, bool on) 32{ 33 u32 off, val; 34 35 off = nn->tlv_caps.crypto_enable_off + round_down(opcode / 8, 4); 36 37 val = nn_readl(nn, off); 38 if (on) 39 val |= BIT(opcode & 31); 40 else 41 val &= ~BIT(opcode & 31); 42 nn_writel(nn, off, val); 43} 44 45static bool 46__nfp_net_tls_conn_cnt_changed(struct nfp_net *nn, int add, 47 enum tls_offload_ctx_dir direction) 48{ 49 u8 opcode; 50 int cnt; 51 52 if (direction == TLS_OFFLOAD_CTX_DIR_TX) { 53 opcode = NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_ENC; 54 nn->ktls_tx_conn_cnt += add; 55 cnt = nn->ktls_tx_conn_cnt; 56 nn->dp.ktls_tx = !!nn->ktls_tx_conn_cnt; 57 } else { 58 opcode = NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_DEC; 59 nn->ktls_rx_conn_cnt += add; 60 cnt = nn->ktls_rx_conn_cnt; 61 } 62 63 /* Care only about 0 -> 1 and 1 -> 0 transitions */ 64 if (cnt > 1) 65 return false; 66 67 nfp_net_crypto_set_op(nn, opcode, cnt); 68 return true; 69} 70 71static int 72nfp_net_tls_conn_cnt_changed(struct nfp_net *nn, int add, 73 enum tls_offload_ctx_dir direction) 74{ 75 int ret = 0; 76 77 /* Use the BAR lock to protect the connection counts */ 78 nn_ctrl_bar_lock(nn); 79 if (__nfp_net_tls_conn_cnt_changed(nn, add, direction)) { 80 ret = __nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_CRYPTO); 81 /* Undo the cnt adjustment if failed */ 82 if (ret) 83 __nfp_net_tls_conn_cnt_changed(nn, -add, direction); 84 } 85 nn_ctrl_bar_unlock(nn); 86 87 return ret; 88} 89 90static int 91nfp_net_tls_conn_add(struct nfp_net *nn, enum tls_offload_ctx_dir direction) 92{ 93 return nfp_net_tls_conn_cnt_changed(nn, 1, direction); 94} 95 96static int 97nfp_net_tls_conn_remove(struct nfp_net *nn, enum tls_offload_ctx_dir direction) 98{ 99 return nfp_net_tls_conn_cnt_changed(nn, -1, direction); 100} 101 102static struct sk_buff * 103nfp_net_tls_alloc_simple(struct nfp_net *nn, size_t req_sz, gfp_t flags) 104{ 105 return nfp_ccm_mbox_msg_alloc(nn, req_sz, 106 sizeof(struct nfp_crypto_reply_simple), 107 flags); 108} 109 110static int 111nfp_net_tls_communicate_simple(struct nfp_net *nn, struct sk_buff *skb, 112 const char *name, enum nfp_ccm_type type) 113{ 114 struct nfp_crypto_reply_simple *reply; 115 int err; 116 117 err = __nfp_ccm_mbox_communicate(nn, skb, type, 118 sizeof(*reply), sizeof(*reply), 119 type == NFP_CCM_TYPE_CRYPTO_DEL); 120 if (err) { 121 nn_dp_warn(&nn->dp, "failed to %s TLS: %d\n", name, err); 122 return err; 123 } 124 125 reply = (void *)skb->data; 126 err = -be32_to_cpu(reply->error); 127 if (err) 128 nn_dp_warn(&nn->dp, "failed to %s TLS, fw replied: %d\n", 129 name, err); 130 dev_consume_skb_any(skb); 131 132 return err; 133} 134 135static void nfp_net_tls_del_fw(struct nfp_net *nn, __be32 *fw_handle) 136{ 137 struct nfp_crypto_req_del *req; 138 struct sk_buff *skb; 139 140 skb = nfp_net_tls_alloc_simple(nn, sizeof(*req), GFP_KERNEL); 141 if (!skb) 142 return; 143 144 req = (void *)skb->data; 145 req->ep_id = 0; 146 memcpy(req->handle, fw_handle, sizeof(req->handle)); 147 148 nfp_net_tls_communicate_simple(nn, skb, "delete", 149 NFP_CCM_TYPE_CRYPTO_DEL); 150} 151 152static void 153nfp_net_tls_set_ipver_vlan(struct nfp_crypto_req_add_front *front, u8 ipver) 154{ 155 front->ipver_vlan = cpu_to_be16(FIELD_PREP(NFP_NET_TLS_IPVER, ipver) | 156 FIELD_PREP(NFP_NET_TLS_VLAN, 157 NFP_NET_TLS_VLAN_UNUSED)); 158} 159 160static void 161nfp_net_tls_assign_conn_id(struct nfp_net *nn, 162 struct nfp_crypto_req_add_front *front) 163{ 164 u32 len; 165 u64 id; 166 167 id = atomic64_inc_return(&nn->ktls_conn_id_gen); 168 len = front->key_len - NFP_NET_TLS_NON_ADDR_KEY_LEN; 169 170 memcpy(front->l3_addrs, &id, sizeof(id)); 171 memset(front->l3_addrs + sizeof(id), 0, len - sizeof(id)); 172} 173 174static struct nfp_crypto_req_add_back * 175nfp_net_tls_set_ipv4(struct nfp_net *nn, struct nfp_crypto_req_add_v4 *req, 176 struct sock *sk, int direction) 177{ 178 struct inet_sock *inet = inet_sk(sk); 179 180 req->front.key_len += sizeof(__be32) * 2; 181 182 if (direction == TLS_OFFLOAD_CTX_DIR_TX) { 183 nfp_net_tls_assign_conn_id(nn, &req->front); 184 } else { 185 req->src_ip = inet->inet_daddr; 186 req->dst_ip = inet->inet_saddr; 187 } 188 189 return &req->back; 190} 191 192static struct nfp_crypto_req_add_back * 193nfp_net_tls_set_ipv6(struct nfp_net *nn, struct nfp_crypto_req_add_v6 *req, 194 struct sock *sk, int direction) 195{ 196#if IS_ENABLED(CONFIG_IPV6) 197 struct ipv6_pinfo *np = inet6_sk(sk); 198 199 req->front.key_len += sizeof(struct in6_addr) * 2; 200 201 if (direction == TLS_OFFLOAD_CTX_DIR_TX) { 202 nfp_net_tls_assign_conn_id(nn, &req->front); 203 } else { 204 memcpy(req->src_ip, &sk->sk_v6_daddr, sizeof(req->src_ip)); 205 memcpy(req->dst_ip, &np->saddr, sizeof(req->dst_ip)); 206 } 207 208#endif 209 return &req->back; 210} 211 212static void 213nfp_net_tls_set_l4(struct nfp_crypto_req_add_front *front, 214 struct nfp_crypto_req_add_back *back, struct sock *sk, 215 int direction) 216{ 217 struct inet_sock *inet = inet_sk(sk); 218 219 front->l4_proto = IPPROTO_TCP; 220 221 if (direction == TLS_OFFLOAD_CTX_DIR_TX) { 222 back->src_port = 0; 223 back->dst_port = 0; 224 } else { 225 back->src_port = inet->inet_dport; 226 back->dst_port = inet->inet_sport; 227 } 228} 229 230static u8 nfp_tls_1_2_dir_to_opcode(enum tls_offload_ctx_dir direction) 231{ 232 switch (direction) { 233 case TLS_OFFLOAD_CTX_DIR_TX: 234 return NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_ENC; 235 case TLS_OFFLOAD_CTX_DIR_RX: 236 return NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_DEC; 237 default: 238 WARN_ON_ONCE(1); 239 return 0; 240 } 241} 242 243static bool 244nfp_net_cipher_supported(struct nfp_net *nn, u16 cipher_type, 245 enum tls_offload_ctx_dir direction) 246{ 247 u8 bit; 248 249 switch (cipher_type) { 250 case TLS_CIPHER_AES_GCM_128: 251 if (direction == TLS_OFFLOAD_CTX_DIR_TX) 252 bit = NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_ENC; 253 else 254 bit = NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_DEC; 255 break; 256 default: 257 return false; 258 } 259 260 return nn->tlv_caps.crypto_ops & BIT(bit); 261} 262 263static int 264nfp_net_tls_add(struct net_device *netdev, struct sock *sk, 265 enum tls_offload_ctx_dir direction, 266 struct tls_crypto_info *crypto_info, 267 u32 start_offload_tcp_sn) 268{ 269 struct tls12_crypto_info_aes_gcm_128 *tls_ci; 270 struct nfp_net *nn = netdev_priv(netdev); 271 struct nfp_crypto_req_add_front *front; 272 struct nfp_net_tls_offload_ctx *ntls; 273 struct nfp_crypto_req_add_back *back; 274 struct nfp_crypto_reply_add *reply; 275 struct sk_buff *skb; 276 size_t req_sz; 277 void *req; 278 bool ipv6; 279 int err; 280 281 BUILD_BUG_ON(sizeof(struct nfp_net_tls_offload_ctx) > 282 TLS_DRIVER_STATE_SIZE_TX); 283 BUILD_BUG_ON(offsetof(struct nfp_net_tls_offload_ctx, rx_end) > 284 TLS_DRIVER_STATE_SIZE_RX); 285 286 if (!nfp_net_cipher_supported(nn, crypto_info->cipher_type, direction)) 287 return -EOPNOTSUPP; 288 289 switch (sk->sk_family) { 290#if IS_ENABLED(CONFIG_IPV6) 291 case AF_INET6: 292 if (ipv6_only_sock(sk) || 293 ipv6_addr_type(&sk->sk_v6_daddr) != IPV6_ADDR_MAPPED) { 294 req_sz = sizeof(struct nfp_crypto_req_add_v6); 295 ipv6 = true; 296 break; 297 } 298 fallthrough; 299#endif 300 case AF_INET: 301 req_sz = sizeof(struct nfp_crypto_req_add_v4); 302 ipv6 = false; 303 break; 304 default: 305 return -EOPNOTSUPP; 306 } 307 308 err = nfp_net_tls_conn_add(nn, direction); 309 if (err) 310 return err; 311 312 skb = nfp_ccm_mbox_msg_alloc(nn, req_sz, sizeof(*reply), GFP_KERNEL); 313 if (!skb) { 314 err = -ENOMEM; 315 goto err_conn_remove; 316 } 317 318 front = (void *)skb->data; 319 front->ep_id = 0; 320 front->key_len = NFP_NET_TLS_NON_ADDR_KEY_LEN; 321 front->opcode = nfp_tls_1_2_dir_to_opcode(direction); 322 memset(front->resv, 0, sizeof(front->resv)); 323 324 nfp_net_tls_set_ipver_vlan(front, ipv6 ? 6 : 4); 325 326 req = (void *)skb->data; 327 if (ipv6) 328 back = nfp_net_tls_set_ipv6(nn, req, sk, direction); 329 else 330 back = nfp_net_tls_set_ipv4(nn, req, sk, direction); 331 332 nfp_net_tls_set_l4(front, back, sk, direction); 333 334 back->counter = 0; 335 back->tcp_seq = cpu_to_be32(start_offload_tcp_sn); 336 337 tls_ci = (struct tls12_crypto_info_aes_gcm_128 *)crypto_info; 338 memcpy(back->key, tls_ci->key, TLS_CIPHER_AES_GCM_128_KEY_SIZE); 339 memset(&back->key[TLS_CIPHER_AES_GCM_128_KEY_SIZE / 4], 0, 340 sizeof(back->key) - TLS_CIPHER_AES_GCM_128_KEY_SIZE); 341 memcpy(back->iv, tls_ci->iv, TLS_CIPHER_AES_GCM_128_IV_SIZE); 342 memcpy(&back->salt, tls_ci->salt, TLS_CIPHER_AES_GCM_128_SALT_SIZE); 343 memcpy(back->rec_no, tls_ci->rec_seq, sizeof(tls_ci->rec_seq)); 344 345 /* Get an extra ref on the skb so we can wipe the key after */ 346 skb_get(skb); 347 348 err = nfp_ccm_mbox_communicate(nn, skb, NFP_CCM_TYPE_CRYPTO_ADD, 349 sizeof(*reply), sizeof(*reply)); 350 reply = (void *)skb->data; 351 352 /* We depend on CCM MBOX code not reallocating skb we sent 353 * so we can clear the key material out of the memory. 354 */ 355 if (!WARN_ON_ONCE((u8 *)back < skb->head || 356 (u8 *)back > skb_end_pointer(skb)) && 357 !WARN_ON_ONCE((u8 *)&reply[1] > (u8 *)back)) 358 memzero_explicit(back, sizeof(*back)); 359 dev_consume_skb_any(skb); /* the extra ref from skb_get() above */ 360 361 if (err) { 362 nn_dp_warn(&nn->dp, "failed to add TLS: %d (%d)\n", 363 err, direction == TLS_OFFLOAD_CTX_DIR_TX); 364 /* communicate frees skb on error */ 365 goto err_conn_remove; 366 } 367 368 err = -be32_to_cpu(reply->error); 369 if (err) { 370 if (err == -ENOSPC) { 371 if (!atomic_fetch_inc(&nn->ktls_no_space)) 372 nn_info(nn, "HW TLS table full\n"); 373 } else { 374 nn_dp_warn(&nn->dp, 375 "failed to add TLS, FW replied: %d\n", err); 376 } 377 goto err_free_skb; 378 } 379 380 if (!reply->handle[0] && !reply->handle[1]) { 381 nn_dp_warn(&nn->dp, "FW returned NULL handle\n"); 382 err = -EINVAL; 383 goto err_fw_remove; 384 } 385 386 ntls = tls_driver_ctx(sk, direction); 387 memcpy(ntls->fw_handle, reply->handle, sizeof(ntls->fw_handle)); 388 if (direction == TLS_OFFLOAD_CTX_DIR_TX) 389 ntls->next_seq = start_offload_tcp_sn; 390 dev_consume_skb_any(skb); 391 392 if (direction == TLS_OFFLOAD_CTX_DIR_TX) 393 return 0; 394 395 if (!nn->tlv_caps.tls_resync_ss) 396 tls_offload_rx_resync_set_type(sk, TLS_OFFLOAD_SYNC_TYPE_CORE_NEXT_HINT); 397 398 return 0; 399 400err_fw_remove: 401 nfp_net_tls_del_fw(nn, reply->handle); 402err_free_skb: 403 dev_consume_skb_any(skb); 404err_conn_remove: 405 nfp_net_tls_conn_remove(nn, direction); 406 return err; 407} 408 409static void 410nfp_net_tls_del(struct net_device *netdev, struct tls_context *tls_ctx, 411 enum tls_offload_ctx_dir direction) 412{ 413 struct nfp_net *nn = netdev_priv(netdev); 414 struct nfp_net_tls_offload_ctx *ntls; 415 416 nfp_net_tls_conn_remove(nn, direction); 417 418 ntls = __tls_driver_ctx(tls_ctx, direction); 419 nfp_net_tls_del_fw(nn, ntls->fw_handle); 420} 421 422static int 423nfp_net_tls_resync(struct net_device *netdev, struct sock *sk, u32 seq, 424 u8 *rcd_sn, enum tls_offload_ctx_dir direction) 425{ 426 struct nfp_net *nn = netdev_priv(netdev); 427 struct nfp_net_tls_offload_ctx *ntls; 428 struct nfp_crypto_req_update *req; 429 enum nfp_ccm_type type; 430 struct sk_buff *skb; 431 gfp_t flags; 432 int err; 433 434 flags = direction == TLS_OFFLOAD_CTX_DIR_TX ? GFP_KERNEL : GFP_ATOMIC; 435 skb = nfp_net_tls_alloc_simple(nn, sizeof(*req), flags); 436 if (!skb) 437 return -ENOMEM; 438 439 ntls = tls_driver_ctx(sk, direction); 440 req = (void *)skb->data; 441 req->ep_id = 0; 442 req->opcode = nfp_tls_1_2_dir_to_opcode(direction); 443 memset(req->resv, 0, sizeof(req->resv)); 444 memcpy(req->handle, ntls->fw_handle, sizeof(ntls->fw_handle)); 445 req->tcp_seq = cpu_to_be32(seq); 446 memcpy(req->rec_no, rcd_sn, sizeof(req->rec_no)); 447 448 type = NFP_CCM_TYPE_CRYPTO_UPDATE; 449 if (direction == TLS_OFFLOAD_CTX_DIR_TX) { 450 err = nfp_net_tls_communicate_simple(nn, skb, "sync", type); 451 if (err) 452 return err; 453 ntls->next_seq = seq; 454 } else { 455 if (nn->tlv_caps.tls_resync_ss) 456 type = NFP_CCM_TYPE_CRYPTO_RESYNC; 457 nfp_ccm_mbox_post(nn, skb, type, 458 sizeof(struct nfp_crypto_reply_simple)); 459 atomic_inc(&nn->ktls_rx_resync_sent); 460 } 461 462 return 0; 463} 464 465static const struct tlsdev_ops nfp_net_tls_ops = { 466 .tls_dev_add = nfp_net_tls_add, 467 .tls_dev_del = nfp_net_tls_del, 468 .tls_dev_resync = nfp_net_tls_resync, 469}; 470 471int nfp_net_tls_rx_resync_req(struct net_device *netdev, 472 struct nfp_net_tls_resync_req *req, 473 void *pkt, unsigned int pkt_len) 474{ 475 struct nfp_net *nn = netdev_priv(netdev); 476 struct nfp_net_tls_offload_ctx *ntls; 477 struct ipv6hdr *ipv6h; 478 struct tcphdr *th; 479 struct iphdr *iph; 480 struct sock *sk; 481 __be32 tcp_seq; 482 int err; 483 484 iph = pkt + req->l3_offset; 485 ipv6h = pkt + req->l3_offset; 486 th = pkt + req->l4_offset; 487 488 if ((u8 *)&th[1] > (u8 *)pkt + pkt_len) { 489 netdev_warn_once(netdev, "invalid TLS RX resync request (l3_off: %hhu l4_off: %hhu pkt_len: %u)\n", 490 req->l3_offset, req->l4_offset, pkt_len); 491 err = -EINVAL; 492 goto err_cnt_ign; 493 } 494 495 switch (ipv6h->version) { 496 case 4: 497 sk = inet_lookup_established(dev_net(netdev), &tcp_hashinfo, 498 iph->saddr, th->source, iph->daddr, 499 th->dest, netdev->ifindex); 500 break; 501#if IS_ENABLED(CONFIG_IPV6) 502 case 6: 503 sk = __inet6_lookup_established(dev_net(netdev), &tcp_hashinfo, 504 &ipv6h->saddr, th->source, 505 &ipv6h->daddr, ntohs(th->dest), 506 netdev->ifindex, 0); 507 break; 508#endif 509 default: 510 netdev_warn_once(netdev, "invalid TLS RX resync request (l3_off: %hhu l4_off: %hhu ipver: %u)\n", 511 req->l3_offset, req->l4_offset, iph->version); 512 err = -EINVAL; 513 goto err_cnt_ign; 514 } 515 516 err = 0; 517 if (!sk) 518 goto err_cnt_ign; 519 if (!tls_is_sk_rx_device_offloaded(sk) || 520 sk->sk_shutdown & RCV_SHUTDOWN) 521 goto err_put_sock; 522 523 ntls = tls_driver_ctx(sk, TLS_OFFLOAD_CTX_DIR_RX); 524 /* some FW versions can't report the handle and report 0s */ 525 if (memchr_inv(&req->fw_handle, 0, sizeof(req->fw_handle)) && 526 memcmp(&req->fw_handle, &ntls->fw_handle, sizeof(ntls->fw_handle))) 527 goto err_put_sock; 528 529 /* copy to ensure alignment */ 530 memcpy(&tcp_seq, &req->tcp_seq, sizeof(tcp_seq)); 531 tls_offload_rx_resync_request(sk, tcp_seq); 532 atomic_inc(&nn->ktls_rx_resync_req); 533 534 sock_gen_put(sk); 535 return 0; 536 537err_put_sock: 538 sock_gen_put(sk); 539err_cnt_ign: 540 atomic_inc(&nn->ktls_rx_resync_ign); 541 return err; 542} 543 544static int nfp_net_tls_reset(struct nfp_net *nn) 545{ 546 struct nfp_crypto_req_reset *req; 547 struct sk_buff *skb; 548 549 skb = nfp_net_tls_alloc_simple(nn, sizeof(*req), GFP_KERNEL); 550 if (!skb) 551 return -ENOMEM; 552 553 req = (void *)skb->data; 554 req->ep_id = 0; 555 556 return nfp_net_tls_communicate_simple(nn, skb, "reset", 557 NFP_CCM_TYPE_CRYPTO_RESET); 558} 559 560int nfp_net_tls_init(struct nfp_net *nn) 561{ 562 struct net_device *netdev = nn->dp.netdev; 563 int err; 564 565 if (!(nn->tlv_caps.crypto_ops & NFP_NET_TLS_OPCODE_MASK)) 566 return 0; 567 568 if ((nn->tlv_caps.mbox_cmsg_types & NFP_NET_TLS_CCM_MBOX_OPS_MASK) != 569 NFP_NET_TLS_CCM_MBOX_OPS_MASK) 570 return 0; 571 572 if (!nfp_ccm_mbox_fits(nn, sizeof(struct nfp_crypto_req_add_v6))) { 573 nn_warn(nn, "disabling TLS offload - mbox too small: %d\n", 574 nn->tlv_caps.mbox_len); 575 return 0; 576 } 577 578 err = nfp_net_tls_reset(nn); 579 if (err) 580 return err; 581 582 nn_ctrl_bar_lock(nn); 583 nn_writel(nn, nn->tlv_caps.crypto_enable_off, 0); 584 err = __nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_CRYPTO); 585 nn_ctrl_bar_unlock(nn); 586 if (err) 587 return err; 588 589 if (nn->tlv_caps.crypto_ops & NFP_NET_TLS_OPCODE_MASK_RX) { 590 netdev->hw_features |= NETIF_F_HW_TLS_RX; 591 netdev->features |= NETIF_F_HW_TLS_RX; 592 } 593 if (nn->tlv_caps.crypto_ops & NFP_NET_TLS_OPCODE_MASK_TX) { 594 netdev->hw_features |= NETIF_F_HW_TLS_TX; 595 netdev->features |= NETIF_F_HW_TLS_TX; 596 } 597 598 netdev->tlsdev_ops = &nfp_net_tls_ops; 599 600 return 0; 601}