1 /* 2 * Wired Ethernet driver interface for QCA MACsec driver 3 * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi> 4 * Copyright (c) 2004, Gunter Burchardt <tira@isx.de> 5 * Copyright (c) 2013-2014, Qualcomm Atheros, Inc. 6 * Copyright (c) 2019, The Linux Foundation 7 * 8 * This software may be distributed under the terms of the BSD license. 9 * See README for more details. 10 */ 11 12 #include "includes.h" 13 #include <sys/ioctl.h> 14 #include <net/if.h> 15 #include <inttypes.h> 16 #ifdef __linux__ 17 #include <netpacket/packet.h> 18 #include <net/if_arp.h> 19 #include <net/if.h> 20 #endif /* __linux__ */ 21 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) 22 #include <net/if_dl.h> 23 #include <net/if_media.h> 24 #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */ 25 #ifdef __sun__ 26 #include <sys/sockio.h> 27 #endif /* __sun__ */ 28 29 #include "utils/common.h" 30 #include "utils/eloop.h" 31 #include "common/defs.h" 32 #include "common/ieee802_1x_defs.h" 33 #include "common/eapol_common.h" 34 #include "pae/ieee802_1x_kay.h" 35 #include "driver.h" 36 #include "driver_wired_common.h" 37 38 #include "nss_macsec_secy.h" 39 #include "nss_macsec_secy_rx.h" 40 #include "nss_macsec_secy_tx.h" 41 42 #define MAXSC 16 43 44 #define SAK_128_LEN 16 45 #define SAK_256_LEN 32 46 47 /* TCI field definition */ 48 #define TCI_ES 0x40 49 #define TCI_SC 0x20 50 #define TCI_SCB 0x10 51 #define TCI_E 0x08 52 #define TCI_C 0x04 53 54 #ifdef _MSC_VER 55 #pragma pack(push, 1) 56 #endif /* _MSC_VER */ 57 58 #ifdef _MSC_VER 59 #pragma pack(pop) 60 #endif /* _MSC_VER */ 61 62 struct channel_map { 63 struct ieee802_1x_mka_sci sci; 64 }; 65 66 struct macsec_qca_data { 67 struct driver_wired_common_data common; 68 69 int use_pae_group_addr; 70 u32 secy_id; 71 72 /* shadow */ 73 bool always_include_sci; 74 bool use_es; 75 bool use_scb; 76 bool protect_frames; 77 bool replay_protect; 78 u32 replay_window; 79 80 struct channel_map receive_channel_map[MAXSC]; 81 struct channel_map transmit_channel_map[MAXSC]; 82 }; 83 84 85 static void __macsec_drv_init(struct macsec_qca_data *drv) 86 { 87 int ret = 0; 88 fal_rx_ctl_filt_t rx_ctl_filt; 89 fal_tx_ctl_filt_t tx_ctl_filt; 90 91 wpa_printf(MSG_INFO, "%s: secy_id=%d", __func__, drv->secy_id); 92 93 /* Enable Secy and Let EAPoL bypass */ 94 ret = nss_macsec_secy_en_set(drv->secy_id, true); 95 if (ret) 96 wpa_printf(MSG_ERROR, "nss_macsec_secy_en_set: FAIL"); 97 98 ret = nss_macsec_secy_sc_sa_mapping_mode_set(drv->secy_id, 99 FAL_SC_SA_MAP_1_4); 100 if (ret) 101 wpa_printf(MSG_ERROR, 102 "nss_macsec_secy_sc_sa_mapping_mode_set: FAIL"); 103 104 os_memset(&rx_ctl_filt, 0, sizeof(rx_ctl_filt)); 105 rx_ctl_filt.bypass = 1; 106 rx_ctl_filt.match_type = IG_CTL_COMPARE_ETHER_TYPE; 107 rx_ctl_filt.match_mask = 0xffff; 108 rx_ctl_filt.ether_type_da_range = 0x888e; 109 ret = nss_macsec_secy_rx_ctl_filt_set(drv->secy_id, 0, &rx_ctl_filt); 110 if (ret) 111 wpa_printf(MSG_ERROR, "nss_macsec_secy_rx_ctl_filt_set: FAIL"); 112 113 os_memset(&tx_ctl_filt, 0, sizeof(tx_ctl_filt)); 114 tx_ctl_filt.bypass = 1; 115 tx_ctl_filt.match_type = EG_CTL_COMPARE_ETHER_TYPE; 116 tx_ctl_filt.match_mask = 0xffff; 117 tx_ctl_filt.ether_type_da_range = 0x888e; 118 ret = nss_macsec_secy_tx_ctl_filt_set(drv->secy_id, 0, &tx_ctl_filt); 119 if (ret) 120 wpa_printf(MSG_ERROR, "nss_macsec_secy_tx_ctl_filt_set: FAIL"); 121 } 122 123 124 static void __macsec_drv_deinit(struct macsec_qca_data *drv) 125 { 126 nss_macsec_secy_en_set(drv->secy_id, false); 127 nss_macsec_secy_rx_sc_del_all(drv->secy_id); 128 nss_macsec_secy_tx_sc_del_all(drv->secy_id); 129 } 130 131 132 #ifdef __linux__ 133 134 static void macsec_qca_handle_data(void *ctx, unsigned char *buf, size_t len) 135 { 136 #ifdef HOSTAPD 137 struct ieee8023_hdr *hdr; 138 u8 *pos, *sa; 139 size_t left; 140 union wpa_event_data event; 141 142 /* at least 6 bytes src macaddress, 6 bytes dst macaddress 143 * and 2 bytes ethertype 144 */ 145 if (len < 14) { 146 wpa_printf(MSG_MSGDUMP, 147 "macsec_qca_handle_data: too short (%lu)", 148 (unsigned long) len); 149 return; 150 } 151 hdr = (struct ieee8023_hdr *) buf; 152 153 switch (ntohs(hdr->ethertype)) { 154 case ETH_P_PAE: 155 wpa_printf(MSG_MSGDUMP, "Received EAPOL packet"); 156 sa = hdr->src; 157 os_memset(&event, 0, sizeof(event)); 158 event.new_sta.addr = sa; 159 wpa_supplicant_event(ctx, EVENT_NEW_STA, &event); 160 161 pos = (u8 *) (hdr + 1); 162 left = len - sizeof(*hdr); 163 drv_event_eapol_rx(ctx, sa, pos, left); 164 break; 165 default: 166 wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame", 167 ntohs(hdr->ethertype)); 168 break; 169 } 170 #endif /* HOSTAPD */ 171 } 172 173 174 static void macsec_qca_handle_read(int sock, void *eloop_ctx, void *sock_ctx) 175 { 176 int len; 177 unsigned char buf[3000]; 178 179 len = recv(sock, buf, sizeof(buf), 0); 180 if (len < 0) { 181 wpa_printf(MSG_ERROR, "macsec_qca: recv: %s", strerror(errno)); 182 return; 183 } 184 185 macsec_qca_handle_data(eloop_ctx, buf, len); 186 } 187 188 #endif /* __linux__ */ 189 190 191 static int macsec_qca_init_sockets(struct macsec_qca_data *drv, u8 *own_addr) 192 { 193 #ifdef __linux__ 194 struct ifreq ifr; 195 struct sockaddr_ll addr; 196 197 drv->common.sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE)); 198 if (drv->common.sock < 0) { 199 wpa_printf(MSG_ERROR, "socket[PF_PACKET,SOCK_RAW]: %s", 200 strerror(errno)); 201 return -1; 202 } 203 204 if (eloop_register_read_sock(drv->common.sock, macsec_qca_handle_read, 205 drv->common.ctx, NULL)) { 206 wpa_printf(MSG_INFO, "Could not register read socket"); 207 return -1; 208 } 209 210 os_memset(&ifr, 0, sizeof(ifr)); 211 os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name)); 212 if (ioctl(drv->common.sock, SIOCGIFINDEX, &ifr) != 0) { 213 wpa_printf(MSG_ERROR, "ioctl(SIOCGIFINDEX): %s", 214 strerror(errno)); 215 return -1; 216 } 217 218 os_memset(&addr, 0, sizeof(addr)); 219 addr.sll_family = AF_PACKET; 220 addr.sll_ifindex = ifr.ifr_ifindex; 221 wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", 222 addr.sll_ifindex); 223 224 if (bind(drv->common.sock, (struct sockaddr *) &addr, 225 sizeof(addr)) < 0) { 226 wpa_printf(MSG_ERROR, "macsec_qca: bind: %s", strerror(errno)); 227 return -1; 228 } 229 230 /* filter multicast address */ 231 if (wired_multicast_membership(drv->common.sock, ifr.ifr_ifindex, 232 pae_group_addr, 1) < 0) { 233 wpa_printf(MSG_ERROR, 234 "macsec_qca_init_sockets: Failed to add multicast group membership"); 235 return -1; 236 } 237 238 os_memset(&ifr, 0, sizeof(ifr)); 239 os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name)); 240 if (ioctl(drv->common.sock, SIOCGIFHWADDR, &ifr) != 0) { 241 wpa_printf(MSG_ERROR, "ioctl(SIOCGIFHWADDR): %s", 242 strerror(errno)); 243 return -1; 244 } 245 246 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { 247 wpa_printf(MSG_INFO, "Invalid HW-addr family 0x%04x", 248 ifr.ifr_hwaddr.sa_family); 249 return -1; 250 } 251 os_memcpy(own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); 252 253 return 0; 254 #else /* __linux__ */ 255 return -1; 256 #endif /* __linux__ */ 257 } 258 259 260 static void * macsec_qca_init(void *ctx, const char *ifname) 261 { 262 struct macsec_qca_data *drv; 263 264 drv = os_zalloc(sizeof(*drv)); 265 if (drv == NULL) 266 return NULL; 267 268 /* Board specific settings */ 269 if (os_memcmp("eth2", ifname, 4) == 0) 270 drv->secy_id = 1; 271 else if (os_memcmp("eth3", ifname, 4) == 0) 272 drv->secy_id = 2; 273 else 274 drv->secy_id = -1; 275 276 if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) { 277 os_free(drv); 278 return NULL; 279 } 280 281 return drv; 282 } 283 284 285 static void macsec_qca_deinit(void *priv) 286 { 287 struct macsec_qca_data *drv = priv; 288 289 driver_wired_deinit_common(&drv->common); 290 os_free(drv); 291 } 292 293 294 static void * macsec_qca_hapd_init(struct hostapd_data *hapd, 295 struct wpa_init_params *params) 296 { 297 struct macsec_qca_data *drv; 298 299 drv = os_zalloc(sizeof(struct macsec_qca_data)); 300 if (!drv) { 301 wpa_printf(MSG_INFO, 302 "Could not allocate memory for macsec_qca driver data"); 303 return NULL; 304 } 305 306 /* Board specific settings */ 307 if (os_memcmp("eth2", params->ifname, 4) == 0) 308 drv->secy_id = 1; 309 else if (os_memcmp("eth3", params->ifname, 4) == 0) 310 drv->secy_id = 2; 311 else if (os_memcmp("eth4", params->ifname, 4) == 0) 312 drv->secy_id = 0; 313 else if (os_memcmp("eth5", params->ifname, 4) == 0) 314 drv->secy_id = 1; 315 else 316 drv->secy_id = -1; 317 318 drv->common.ctx = hapd; 319 os_strlcpy(drv->common.ifname, params->ifname, 320 sizeof(drv->common.ifname)); 321 drv->use_pae_group_addr = params->use_pae_group_addr; 322 323 if (macsec_qca_init_sockets(drv, params->own_addr)) { 324 os_free(drv); 325 return NULL; 326 } 327 328 return drv; 329 } 330 331 332 static void macsec_qca_hapd_deinit(void *priv) 333 { 334 struct macsec_qca_data *drv = priv; 335 336 if (drv->common.sock >= 0) { 337 eloop_unregister_read_sock(drv->common.sock); 338 close(drv->common.sock); 339 } 340 341 os_free(drv); 342 } 343 344 345 static int macsec_qca_send_eapol(void *priv, const u8 *addr, 346 const u8 *data, size_t data_len, int encrypt, 347 const u8 *own_addr, u32 flags) 348 { 349 struct macsec_qca_data *drv = priv; 350 struct ieee8023_hdr *hdr; 351 size_t len; 352 u8 *pos; 353 int res; 354 355 len = sizeof(*hdr) + data_len; 356 hdr = os_zalloc(len); 357 if (!hdr) { 358 wpa_printf(MSG_INFO, 359 "malloc() failed for macsec_qca_send_eapol(len=%lu)", 360 (unsigned long) len); 361 return -1; 362 } 363 364 os_memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr, 365 ETH_ALEN); 366 os_memcpy(hdr->src, own_addr, ETH_ALEN); 367 hdr->ethertype = htons(ETH_P_PAE); 368 369 pos = (u8 *) (hdr + 1); 370 os_memcpy(pos, data, data_len); 371 372 res = send(drv->common.sock, (u8 *) hdr, len, 0); 373 os_free(hdr); 374 375 if (res < 0) { 376 wpa_printf(MSG_ERROR, 377 "macsec_qca_send_eapol - packet len: %lu - failed: send: %s", 378 (unsigned long) len, strerror(errno)); 379 } 380 381 return res; 382 } 383 384 385 static int macsec_qca_macsec_init(void *priv, struct macsec_init_params *params) 386 { 387 struct macsec_qca_data *drv = priv; 388 389 drv->always_include_sci = params->always_include_sci; 390 drv->use_es = params->use_es; 391 drv->use_scb = params->use_scb; 392 393 wpa_printf(MSG_DEBUG, "%s: es=%d, scb=%d, sci=%d", 394 __func__, drv->use_es, drv->use_scb, 395 drv->always_include_sci); 396 397 __macsec_drv_init(drv); 398 399 return 0; 400 } 401 402 403 static int macsec_qca_macsec_deinit(void *priv) 404 { 405 struct macsec_qca_data *drv = priv; 406 407 wpa_printf(MSG_DEBUG, "%s", __func__); 408 409 __macsec_drv_deinit(drv); 410 411 return 0; 412 } 413 414 415 static int macsec_qca_get_capability(void *priv, enum macsec_cap *cap) 416 { 417 wpa_printf(MSG_DEBUG, "%s", __func__); 418 419 *cap = MACSEC_CAP_INTEG_AND_CONF_0_30_50; 420 421 return 0; 422 } 423 424 425 static int macsec_qca_enable_protect_frames(void *priv, bool enabled) 426 { 427 struct macsec_qca_data *drv = priv; 428 int ret = 0; 429 430 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 431 432 drv->protect_frames = enabled; 433 434 return ret; 435 } 436 437 438 static int macsec_qca_set_replay_protect(void *priv, bool enabled, 439 unsigned int window) 440 { 441 struct macsec_qca_data *drv = priv; 442 int ret = 0; 443 444 wpa_printf(MSG_DEBUG, "%s: enabled=%d, win=%u", 445 __func__, enabled, window); 446 447 drv->replay_protect = enabled; 448 drv->replay_window = window; 449 450 return ret; 451 } 452 453 454 static fal_cipher_suite_e macsec_qca_cs_type_get(u64 cs) 455 { 456 if (cs == CS_ID_GCM_AES_128) 457 return FAL_CIPHER_SUITE_AES_GCM_128; 458 if (cs == CS_ID_GCM_AES_256) 459 return FAL_CIPHER_SUITE_AES_GCM_256; 460 return FAL_CIPHER_SUITE_MAX; 461 } 462 463 464 static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs) 465 { 466 struct macsec_qca_data *drv = priv; 467 fal_cipher_suite_e cs_type; 468 469 if (cs != CS_ID_GCM_AES_128 && cs != CS_ID_GCM_AES_256) { 470 wpa_printf(MSG_ERROR, 471 "%s: NOT supported CipherSuite: %016" PRIx64, 472 __func__, cs); 473 return -1; 474 } 475 476 wpa_printf(MSG_DEBUG, "%s: CipherSuite: %016" PRIx64, __func__, cs); 477 478 cs_type = macsec_qca_cs_type_get(cs); 479 return nss_macsec_secy_cipher_suite_set(drv->secy_id, cs_type); 480 } 481 482 483 static int macsec_qca_enable_controlled_port(void *priv, bool enabled) 484 { 485 struct macsec_qca_data *drv = priv; 486 int ret = 0; 487 488 wpa_printf(MSG_DEBUG, "%s: enable=%d", __func__, enabled); 489 490 ret += nss_macsec_secy_controlled_port_en_set(drv->secy_id, enabled); 491 492 return ret; 493 } 494 495 496 static int macsec_qca_lookup_channel(struct channel_map *map, 497 struct ieee802_1x_mka_sci *sci, 498 u32 *channel) 499 { 500 u32 i; 501 502 for (i = 0; i < MAXSC; i++) { 503 if (os_memcmp(&map[i].sci, sci, 504 sizeof(struct ieee802_1x_mka_sci)) == 0) { 505 *channel = i; 506 return 0; 507 } 508 } 509 510 return -1; 511 } 512 513 514 static void macsec_qca_register_channel(struct channel_map *map, 515 struct ieee802_1x_mka_sci *sci, 516 u32 channel) 517 { 518 os_memcpy(&map[channel].sci, sci, sizeof(struct ieee802_1x_mka_sci)); 519 } 520 521 522 static int macsec_qca_lookup_receive_channel(struct macsec_qca_data *drv, 523 struct receive_sc *sc, 524 u32 *channel) 525 { 526 return macsec_qca_lookup_channel(drv->receive_channel_map, &sc->sci, 527 channel); 528 } 529 530 531 static void macsec_qca_register_receive_channel(struct macsec_qca_data *drv, 532 struct receive_sc *sc, 533 u32 channel) 534 { 535 macsec_qca_register_channel(drv->receive_channel_map, &sc->sci, 536 channel); 537 } 538 539 540 static int macsec_qca_lookup_transmit_channel(struct macsec_qca_data *drv, 541 struct transmit_sc *sc, 542 u32 *channel) 543 { 544 return macsec_qca_lookup_channel(drv->transmit_channel_map, &sc->sci, 545 channel); 546 } 547 548 549 static void macsec_qca_register_transmit_channel(struct macsec_qca_data *drv, 550 struct transmit_sc *sc, 551 u32 channel) 552 { 553 macsec_qca_register_channel(drv->transmit_channel_map, &sc->sci, 554 channel); 555 } 556 557 558 static int macsec_qca_get_receive_lowest_pn(void *priv, struct receive_sa *sa) 559 { 560 struct macsec_qca_data *drv = priv; 561 int ret = 0; 562 u32 next_pn = 0; 563 bool enabled = false; 564 u32 win; 565 u32 channel; 566 567 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 568 if (ret != 0) 569 return ret; 570 571 ret += nss_macsec_secy_rx_sa_next_pn_get(drv->secy_id, channel, sa->an, 572 &next_pn); 573 ret += nss_macsec_secy_rx_sc_replay_protect_get(drv->secy_id, channel, 574 &enabled); 575 ret += nss_macsec_secy_rx_sc_anti_replay_window_get(drv->secy_id, 576 channel, &win); 577 578 if (enabled) 579 sa->lowest_pn = (next_pn > win) ? (next_pn - win) : 1; 580 else 581 sa->lowest_pn = next_pn; 582 583 wpa_printf(MSG_DEBUG, "%s: lpn=0x%x", __func__, sa->lowest_pn); 584 585 return ret; 586 } 587 588 589 static int macsec_qca_get_transmit_next_pn(void *priv, struct transmit_sa *sa) 590 { 591 struct macsec_qca_data *drv = priv; 592 int ret = 0; 593 u32 channel; 594 595 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 596 if (ret != 0) 597 return ret; 598 599 ret += nss_macsec_secy_tx_sa_next_pn_get(drv->secy_id, channel, sa->an, 600 &sa->next_pn); 601 602 wpa_printf(MSG_DEBUG, "%s: npn=0x%x", __func__, sa->next_pn); 603 604 return ret; 605 } 606 607 608 static int macsec_qca_set_transmit_next_pn(void *priv, struct transmit_sa *sa) 609 { 610 struct macsec_qca_data *drv = priv; 611 int ret = 0; 612 u32 channel; 613 614 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 615 if (ret != 0) 616 return ret; 617 618 ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an, 619 sa->next_pn); 620 621 wpa_printf(MSG_INFO, "%s: npn=0x%x", __func__, sa->next_pn); 622 623 return ret; 624 } 625 626 627 static int macsec_qca_get_available_receive_sc(void *priv, u32 *channel) 628 { 629 struct macsec_qca_data *drv = priv; 630 int ret = 0; 631 u32 sc_ch = 0; 632 bool in_use = false; 633 634 for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) { 635 ret = nss_macsec_secy_rx_sc_in_used_get(drv->secy_id, sc_ch, 636 &in_use); 637 if (ret) 638 continue; 639 640 if (!in_use) { 641 *channel = sc_ch; 642 wpa_printf(MSG_DEBUG, "%s: channel=%d", 643 __func__, *channel); 644 return 0; 645 } 646 } 647 648 wpa_printf(MSG_DEBUG, "%s: no available channel", __func__); 649 650 return -1; 651 } 652 653 654 static int macsec_qca_create_receive_sc(void *priv, struct receive_sc *sc, 655 unsigned int conf_offset, 656 int validation) 657 { 658 struct macsec_qca_data *drv = priv; 659 int ret = 0; 660 fal_rx_prc_lut_t entry; 661 fal_rx_sc_validate_frame_e vf; 662 enum validate_frames validate_frames = validation; 663 u32 channel; 664 const u8 *sci_addr = sc->sci.addr; 665 u16 sci_port = be_to_host16(sc->sci.port); 666 667 ret = macsec_qca_get_available_receive_sc(priv, &channel); 668 if (ret != 0) 669 return ret; 670 671 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 672 673 /* rx prc lut */ 674 os_memset(&entry, 0, sizeof(entry)); 675 676 os_memcpy(entry.sci, sci_addr, ETH_ALEN); 677 entry.sci[6] = (sci_port >> 8) & 0xff; 678 entry.sci[7] = sci_port & 0xff; 679 entry.sci_mask = 0xf; 680 681 entry.valid = 1; 682 entry.channel = channel; 683 entry.action = FAL_RX_PRC_ACTION_PROCESS; 684 entry.offset = conf_offset; 685 686 /* rx validate frame */ 687 if (validate_frames == Strict) 688 vf = FAL_RX_SC_VALIDATE_FRAME_STRICT; 689 else if (validate_frames == Checked) 690 vf = FAL_RX_SC_VALIDATE_FRAME_CHECK; 691 else 692 vf = FAL_RX_SC_VALIDATE_FRAME_DISABLED; 693 694 ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry); 695 ret += nss_macsec_secy_rx_sc_create(drv->secy_id, channel); 696 ret += nss_macsec_secy_rx_sc_validate_frame_set(drv->secy_id, channel, 697 vf); 698 ret += nss_macsec_secy_rx_sc_replay_protect_set(drv->secy_id, channel, 699 drv->replay_protect); 700 ret += nss_macsec_secy_rx_sc_anti_replay_window_set(drv->secy_id, 701 channel, 702 drv->replay_window); 703 704 macsec_qca_register_receive_channel(drv, sc, channel); 705 706 return ret; 707 } 708 709 710 static int macsec_qca_delete_receive_sc(void *priv, struct receive_sc *sc) 711 { 712 struct macsec_qca_data *drv = priv; 713 int ret; 714 fal_rx_prc_lut_t entry; 715 u32 channel; 716 717 ret = macsec_qca_lookup_receive_channel(priv, sc, &channel); 718 if (ret != 0) 719 return ret; 720 721 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 722 723 /* rx prc lut */ 724 os_memset(&entry, 0, sizeof(entry)); 725 726 ret += nss_macsec_secy_rx_sc_del(drv->secy_id, channel); 727 ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry); 728 729 return ret; 730 } 731 732 733 static int macsec_qca_create_receive_sa(void *priv, struct receive_sa *sa) 734 { 735 struct macsec_qca_data *drv = priv; 736 int ret; 737 fal_rx_sak_t rx_sak; 738 int i = 0; 739 u32 channel; 740 fal_rx_prc_lut_t entry; 741 u32 offset; 742 743 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 744 if (ret != 0) 745 return ret; 746 747 wpa_printf(MSG_DEBUG, "%s, channel=%d, an=%d, lpn=0x%x", 748 __func__, channel, sa->an, sa->lowest_pn); 749 750 os_memset(&rx_sak, 0, sizeof(rx_sak)); 751 rx_sak.sak_len = sa->pkey->key_len; 752 if (sa->pkey->key_len == SAK_128_LEN) { 753 for (i = 0; i < 16; i++) 754 rx_sak.sak[i] = sa->pkey->key[15 - i]; 755 } else if (sa->pkey->key_len == SAK_256_LEN) { 756 for (i = 0; i < 16; i++) { 757 rx_sak.sak1[i] = sa->pkey->key[15 - i]; 758 rx_sak.sak[i] = sa->pkey->key[31 - i]; 759 } 760 } else { 761 return -1; 762 } 763 764 if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0) 765 offset = 0; 766 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30) 767 offset = 30; 768 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50) 769 offset = 50; 770 else 771 return -1; 772 ret += nss_macsec_secy_rx_prc_lut_get(drv->secy_id, channel, &entry); 773 entry.offset = offset; 774 ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry); 775 ret += nss_macsec_secy_rx_sa_create(drv->secy_id, channel, sa->an); 776 ret += nss_macsec_secy_rx_sak_set(drv->secy_id, channel, sa->an, 777 &rx_sak); 778 779 return ret; 780 } 781 782 783 static int macsec_qca_enable_receive_sa(void *priv, struct receive_sa *sa) 784 { 785 struct macsec_qca_data *drv = priv; 786 int ret; 787 u32 channel; 788 789 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 790 if (ret != 0) 791 return ret; 792 793 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 794 sa->an); 795 796 ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an, 797 true); 798 799 return ret; 800 } 801 802 803 static int macsec_qca_disable_receive_sa(void *priv, struct receive_sa *sa) 804 { 805 struct macsec_qca_data *drv = priv; 806 int ret; 807 u32 channel; 808 809 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 810 if (ret != 0) 811 return ret; 812 813 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 814 sa->an); 815 816 ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an, 817 false); 818 819 return ret; 820 } 821 822 823 static int macsec_qca_get_available_transmit_sc(void *priv, u32 *channel) 824 { 825 struct macsec_qca_data *drv = priv; 826 u32 sc_ch = 0; 827 bool in_use = false; 828 829 for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) { 830 if (nss_macsec_secy_tx_sc_in_used_get(drv->secy_id, sc_ch, 831 &in_use)) 832 continue; 833 834 if (!in_use) { 835 *channel = sc_ch; 836 wpa_printf(MSG_DEBUG, "%s: channel=%d", 837 __func__, *channel); 838 return 0; 839 } 840 } 841 842 wpa_printf(MSG_DEBUG, "%s: no avaiable channel", __func__); 843 844 return -1; 845 } 846 847 848 static int macsec_qca_create_transmit_sc(void *priv, struct transmit_sc *sc, 849 unsigned int conf_offset) 850 { 851 struct macsec_qca_data *drv = priv; 852 int ret; 853 fal_tx_class_lut_t entry; 854 u8 psci[ETH_ALEN + 2]; 855 u32 channel; 856 u16 sci_port = be_to_host16(sc->sci.port); 857 858 ret = macsec_qca_get_available_transmit_sc(priv, &channel); 859 if (ret != 0) 860 return ret; 861 862 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 863 864 /* class lut */ 865 os_memset(&entry, 0, sizeof(entry)); 866 867 entry.valid = 1; 868 entry.action = FAL_TX_CLASS_ACTION_FORWARD; 869 entry.channel = channel; 870 871 os_memcpy(psci, sc->sci.addr, ETH_ALEN); 872 psci[6] = (sci_port >> 8) & 0xff; 873 psci[7] = sci_port & 0xff; 874 875 ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry); 876 ret += nss_macsec_secy_tx_sc_create(drv->secy_id, channel, psci, 8); 877 ret += nss_macsec_secy_tx_sc_protect_set(drv->secy_id, channel, 878 drv->protect_frames); 879 ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id, 880 channel, 881 conf_offset); 882 883 macsec_qca_register_transmit_channel(drv, sc, channel); 884 885 return ret; 886 } 887 888 889 static int macsec_qca_delete_transmit_sc(void *priv, struct transmit_sc *sc) 890 { 891 struct macsec_qca_data *drv = priv; 892 int ret; 893 fal_tx_class_lut_t entry; 894 u32 channel; 895 896 ret = macsec_qca_lookup_transmit_channel(priv, sc, &channel); 897 if (ret != 0) 898 return ret; 899 900 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 901 902 /* class lut */ 903 os_memset(&entry, 0, sizeof(entry)); 904 905 ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry); 906 ret += nss_macsec_secy_tx_sc_del(drv->secy_id, channel); 907 908 return ret; 909 } 910 911 912 static int macsec_qca_create_transmit_sa(void *priv, struct transmit_sa *sa) 913 { 914 struct macsec_qca_data *drv = priv; 915 int ret; 916 u8 tci = 0; 917 fal_tx_sak_t tx_sak; 918 int i; 919 u32 channel; 920 u32 offset; 921 922 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 923 if (ret != 0) 924 return ret; 925 926 wpa_printf(MSG_DEBUG, 927 "%s: channel=%d, an=%d, next_pn=0x%x, confidentiality=%d", 928 __func__, channel, sa->an, sa->next_pn, sa->confidentiality); 929 930 if (drv->always_include_sci) 931 tci |= TCI_SC; 932 else if (drv->use_es) 933 tci |= TCI_ES; 934 else if (drv->use_scb) 935 tci |= TCI_SCB; 936 937 if (sa->confidentiality) 938 tci |= TCI_E | TCI_C; 939 940 os_memset(&tx_sak, 0, sizeof(tx_sak)); 941 tx_sak.sak_len = sa->pkey->key_len; 942 if (sa->pkey->key_len == SAK_128_LEN) { 943 for (i = 0; i < 16; i++) 944 tx_sak.sak[i] = sa->pkey->key[15 - i]; 945 } else if (sa->pkey->key_len == SAK_256_LEN) { 946 for (i = 0; i < 16; i++) { 947 tx_sak.sak1[i] = sa->pkey->key[15 - i]; 948 tx_sak.sak[i] = sa->pkey->key[31 - i]; 949 } 950 } else { 951 return -1; 952 } 953 954 if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0) 955 offset = 0; 956 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30) 957 offset = 30; 958 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50) 959 offset = 50; 960 else 961 return -1; 962 ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id, 963 channel, 964 offset); 965 ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an, 966 sa->next_pn); 967 ret += nss_macsec_secy_tx_sak_set(drv->secy_id, channel, sa->an, 968 &tx_sak); 969 ret += nss_macsec_secy_tx_sc_tci_7_2_set(drv->secy_id, channel, 970 (tci >> 2)); 971 ret += nss_macsec_secy_tx_sc_an_set(drv->secy_id, channel, sa->an); 972 973 return ret; 974 } 975 976 977 static int macsec_qca_enable_transmit_sa(void *priv, struct transmit_sa *sa) 978 { 979 struct macsec_qca_data *drv = priv; 980 int ret; 981 u32 channel; 982 983 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 984 if (ret != 0) 985 return ret; 986 987 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 988 sa->an); 989 990 ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an, 991 true); 992 993 return ret; 994 } 995 996 997 static int macsec_qca_disable_transmit_sa(void *priv, struct transmit_sa *sa) 998 { 999 struct macsec_qca_data *drv = priv; 1000 int ret; 1001 u32 channel; 1002 1003 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 1004 if (ret != 0) 1005 return ret; 1006 1007 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 1008 sa->an); 1009 1010 ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an, 1011 false); 1012 1013 return ret; 1014 } 1015 1016 1017 const struct wpa_driver_ops wpa_driver_macsec_qca_ops = { 1018 .name = "macsec_qca", 1019 .desc = "QCA MACsec Ethernet driver", 1020 .get_ssid = driver_wired_get_ssid, 1021 .get_bssid = driver_wired_get_bssid, 1022 .get_capa = driver_wired_get_capa, 1023 .init = macsec_qca_init, 1024 .deinit = macsec_qca_deinit, 1025 .hapd_init = macsec_qca_hapd_init, 1026 .hapd_deinit = macsec_qca_hapd_deinit, 1027 .hapd_send_eapol = macsec_qca_send_eapol, 1028 1029 .macsec_init = macsec_qca_macsec_init, 1030 .macsec_deinit = macsec_qca_macsec_deinit, 1031 .macsec_get_capability = macsec_qca_get_capability, 1032 .enable_protect_frames = macsec_qca_enable_protect_frames, 1033 .set_replay_protect = macsec_qca_set_replay_protect, 1034 .set_current_cipher_suite = macsec_qca_set_current_cipher_suite, 1035 .enable_controlled_port = macsec_qca_enable_controlled_port, 1036 .get_receive_lowest_pn = macsec_qca_get_receive_lowest_pn, 1037 .get_transmit_next_pn = macsec_qca_get_transmit_next_pn, 1038 .set_transmit_next_pn = macsec_qca_set_transmit_next_pn, 1039 .create_receive_sc = macsec_qca_create_receive_sc, 1040 .delete_receive_sc = macsec_qca_delete_receive_sc, 1041 .create_receive_sa = macsec_qca_create_receive_sa, 1042 .enable_receive_sa = macsec_qca_enable_receive_sa, 1043 .disable_receive_sa = macsec_qca_disable_receive_sa, 1044 .create_transmit_sc = macsec_qca_create_transmit_sc, 1045 .delete_transmit_sc = macsec_qca_delete_transmit_sc, 1046 .create_transmit_sa = macsec_qca_create_transmit_sa, 1047 .enable_transmit_sa = macsec_qca_enable_transmit_sa, 1048 .disable_transmit_sa = macsec_qca_disable_transmit_sa, 1049 }; 1050