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 int macsec_qca_secy_id_get(const char *ifname, u32 *secy_id) 261 { 262 #ifdef NSS_MACSEC_SECY_ID_GET_FUNC 263 /* Get secy id from nss macsec driver */ 264 return nss_macsec_secy_id_get((u8 *) ifname, secy_id); 265 #else /* NSS_MACSEC_SECY_ID_GET_FUNC */ 266 /* Board specific settings */ 267 if (os_strcmp(ifname, "eth2") == 0) { 268 *secy_id = 1; 269 } else if (os_strcmp(ifname, "eth3") == 0) { 270 *secy_id = 2; 271 } else if (os_strcmp(ifname, "eth4") == 0 || 272 os_strcmp(ifname, "eth0") == 0) { 273 *secy_id = 0; 274 } else if (os_strcmp(ifname, "eth5") == 0 || 275 os_strcmp(ifname, "eth1") == 0) { 276 *secy_id = 1; 277 } else { 278 *secy_id = -1; 279 return -1; 280 } 281 282 return 0; 283 #endif /* NSS_MACSEC_SECY_ID_GET_FUNC */ 284 } 285 286 287 static void * macsec_qca_init(void *ctx, const char *ifname) 288 { 289 struct macsec_qca_data *drv; 290 291 drv = os_zalloc(sizeof(*drv)); 292 if (drv == NULL) 293 return NULL; 294 295 if (macsec_qca_secy_id_get(ifname, &drv->secy_id)) { 296 wpa_printf(MSG_ERROR, 297 "macsec_qca: Failed to get secy_id for %s", ifname); 298 os_free(drv); 299 return NULL; 300 } 301 302 if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) { 303 os_free(drv); 304 return NULL; 305 } 306 307 return drv; 308 } 309 310 311 static void macsec_qca_deinit(void *priv) 312 { 313 struct macsec_qca_data *drv = priv; 314 315 driver_wired_deinit_common(&drv->common); 316 os_free(drv); 317 } 318 319 320 static void * macsec_qca_hapd_init(struct hostapd_data *hapd, 321 struct wpa_init_params *params) 322 { 323 struct macsec_qca_data *drv; 324 325 drv = os_zalloc(sizeof(struct macsec_qca_data)); 326 if (!drv) { 327 wpa_printf(MSG_INFO, 328 "Could not allocate memory for macsec_qca driver data"); 329 return NULL; 330 } 331 332 if (macsec_qca_secy_id_get(params->ifname, &drv->secy_id)) { 333 wpa_printf(MSG_ERROR, 334 "macsec_qca: Failed to get secy_id for %s", 335 params->ifname); 336 os_free(drv); 337 return NULL; 338 } 339 340 drv->common.ctx = hapd; 341 os_strlcpy(drv->common.ifname, params->ifname, 342 sizeof(drv->common.ifname)); 343 drv->use_pae_group_addr = params->use_pae_group_addr; 344 345 if (macsec_qca_init_sockets(drv, params->own_addr)) { 346 os_free(drv); 347 return NULL; 348 } 349 350 return drv; 351 } 352 353 354 static void macsec_qca_hapd_deinit(void *priv) 355 { 356 struct macsec_qca_data *drv = priv; 357 358 if (drv->common.sock >= 0) { 359 eloop_unregister_read_sock(drv->common.sock); 360 close(drv->common.sock); 361 } 362 363 os_free(drv); 364 } 365 366 367 static int macsec_qca_send_eapol(void *priv, const u8 *addr, 368 const u8 *data, size_t data_len, int encrypt, 369 const u8 *own_addr, u32 flags) 370 { 371 struct macsec_qca_data *drv = priv; 372 struct ieee8023_hdr *hdr; 373 size_t len; 374 u8 *pos; 375 int res; 376 377 len = sizeof(*hdr) + data_len; 378 hdr = os_zalloc(len); 379 if (!hdr) { 380 wpa_printf(MSG_INFO, 381 "malloc() failed for macsec_qca_send_eapol(len=%lu)", 382 (unsigned long) len); 383 return -1; 384 } 385 386 os_memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr, 387 ETH_ALEN); 388 os_memcpy(hdr->src, own_addr, ETH_ALEN); 389 hdr->ethertype = htons(ETH_P_PAE); 390 391 pos = (u8 *) (hdr + 1); 392 os_memcpy(pos, data, data_len); 393 394 res = send(drv->common.sock, (u8 *) hdr, len, 0); 395 os_free(hdr); 396 397 if (res < 0) { 398 wpa_printf(MSG_ERROR, 399 "macsec_qca_send_eapol - packet len: %lu - failed: send: %s", 400 (unsigned long) len, strerror(errno)); 401 } 402 403 return res; 404 } 405 406 407 static int macsec_qca_macsec_init(void *priv, struct macsec_init_params *params) 408 { 409 struct macsec_qca_data *drv = priv; 410 411 drv->always_include_sci = params->always_include_sci; 412 drv->use_es = params->use_es; 413 drv->use_scb = params->use_scb; 414 415 wpa_printf(MSG_DEBUG, "%s: es=%d, scb=%d, sci=%d", 416 __func__, drv->use_es, drv->use_scb, 417 drv->always_include_sci); 418 419 __macsec_drv_init(drv); 420 421 return 0; 422 } 423 424 425 static int macsec_qca_macsec_deinit(void *priv) 426 { 427 struct macsec_qca_data *drv = priv; 428 429 wpa_printf(MSG_DEBUG, "%s", __func__); 430 431 __macsec_drv_deinit(drv); 432 433 return 0; 434 } 435 436 437 static int macsec_qca_get_capability(void *priv, enum macsec_cap *cap) 438 { 439 wpa_printf(MSG_DEBUG, "%s", __func__); 440 441 *cap = MACSEC_CAP_INTEG_AND_CONF_0_30_50; 442 443 return 0; 444 } 445 446 447 static int macsec_qca_enable_protect_frames(void *priv, bool enabled) 448 { 449 struct macsec_qca_data *drv = priv; 450 int ret = 0; 451 452 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 453 454 drv->protect_frames = enabled; 455 456 return ret; 457 } 458 459 460 static int macsec_qca_set_replay_protect(void *priv, bool enabled, 461 unsigned int window) 462 { 463 struct macsec_qca_data *drv = priv; 464 int ret = 0; 465 466 wpa_printf(MSG_DEBUG, "%s: enabled=%d, win=%u", 467 __func__, enabled, window); 468 469 drv->replay_protect = enabled; 470 drv->replay_window = window; 471 472 return ret; 473 } 474 475 476 static fal_cipher_suite_e macsec_qca_cs_type_get(u64 cs) 477 { 478 if (cs == CS_ID_GCM_AES_128) 479 return FAL_CIPHER_SUITE_AES_GCM_128; 480 if (cs == CS_ID_GCM_AES_256) 481 return FAL_CIPHER_SUITE_AES_GCM_256; 482 return FAL_CIPHER_SUITE_MAX; 483 } 484 485 486 static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs) 487 { 488 struct macsec_qca_data *drv = priv; 489 fal_cipher_suite_e cs_type; 490 491 if (cs != CS_ID_GCM_AES_128 && cs != CS_ID_GCM_AES_256) { 492 wpa_printf(MSG_ERROR, 493 "%s: NOT supported CipherSuite: %016" PRIx64, 494 __func__, cs); 495 return -1; 496 } 497 498 wpa_printf(MSG_DEBUG, "%s: CipherSuite: %016" PRIx64, __func__, cs); 499 500 cs_type = macsec_qca_cs_type_get(cs); 501 return nss_macsec_secy_cipher_suite_set(drv->secy_id, cs_type); 502 } 503 504 505 static int macsec_qca_enable_controlled_port(void *priv, bool enabled) 506 { 507 struct macsec_qca_data *drv = priv; 508 int ret = 0; 509 510 wpa_printf(MSG_DEBUG, "%s: enable=%d", __func__, enabled); 511 512 ret += nss_macsec_secy_controlled_port_en_set(drv->secy_id, enabled); 513 514 return ret; 515 } 516 517 518 static int macsec_qca_lookup_channel(struct channel_map *map, 519 struct ieee802_1x_mka_sci *sci, 520 u32 *channel) 521 { 522 u32 i; 523 524 for (i = 0; i < MAXSC; i++) { 525 if (os_memcmp(&map[i].sci, sci, 526 sizeof(struct ieee802_1x_mka_sci)) == 0) { 527 *channel = i; 528 return 0; 529 } 530 } 531 532 return -1; 533 } 534 535 536 static void macsec_qca_register_channel(struct channel_map *map, 537 struct ieee802_1x_mka_sci *sci, 538 u32 channel) 539 { 540 os_memcpy(&map[channel].sci, sci, sizeof(struct ieee802_1x_mka_sci)); 541 } 542 543 544 static int macsec_qca_lookup_receive_channel(struct macsec_qca_data *drv, 545 struct receive_sc *sc, 546 u32 *channel) 547 { 548 return macsec_qca_lookup_channel(drv->receive_channel_map, &sc->sci, 549 channel); 550 } 551 552 553 static void macsec_qca_register_receive_channel(struct macsec_qca_data *drv, 554 struct receive_sc *sc, 555 u32 channel) 556 { 557 macsec_qca_register_channel(drv->receive_channel_map, &sc->sci, 558 channel); 559 } 560 561 562 static int macsec_qca_lookup_transmit_channel(struct macsec_qca_data *drv, 563 struct transmit_sc *sc, 564 u32 *channel) 565 { 566 return macsec_qca_lookup_channel(drv->transmit_channel_map, &sc->sci, 567 channel); 568 } 569 570 571 static void macsec_qca_register_transmit_channel(struct macsec_qca_data *drv, 572 struct transmit_sc *sc, 573 u32 channel) 574 { 575 macsec_qca_register_channel(drv->transmit_channel_map, &sc->sci, 576 channel); 577 } 578 579 580 static int macsec_qca_get_receive_lowest_pn(void *priv, struct receive_sa *sa) 581 { 582 struct macsec_qca_data *drv = priv; 583 int ret = 0; 584 u32 next_pn = 0; 585 bool enabled = false; 586 u32 win; 587 u32 channel; 588 589 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 590 if (ret != 0) 591 return ret; 592 593 ret += nss_macsec_secy_rx_sa_next_pn_get(drv->secy_id, channel, sa->an, 594 &next_pn); 595 ret += nss_macsec_secy_rx_sc_replay_protect_get(drv->secy_id, channel, 596 &enabled); 597 ret += nss_macsec_secy_rx_sc_anti_replay_window_get(drv->secy_id, 598 channel, &win); 599 600 if (enabled) 601 sa->lowest_pn = (next_pn > win) ? (next_pn - win) : 1; 602 else 603 sa->lowest_pn = next_pn; 604 605 wpa_printf(MSG_DEBUG, "%s: lpn=0x%x", __func__, sa->lowest_pn); 606 607 return ret; 608 } 609 610 611 static int macsec_qca_get_transmit_next_pn(void *priv, struct transmit_sa *sa) 612 { 613 struct macsec_qca_data *drv = priv; 614 int ret = 0; 615 u32 channel; 616 617 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 618 if (ret != 0) 619 return ret; 620 621 ret += nss_macsec_secy_tx_sa_next_pn_get(drv->secy_id, channel, sa->an, 622 &sa->next_pn); 623 624 wpa_printf(MSG_DEBUG, "%s: npn=0x%x", __func__, sa->next_pn); 625 626 return ret; 627 } 628 629 630 static int macsec_qca_set_transmit_next_pn(void *priv, struct transmit_sa *sa) 631 { 632 struct macsec_qca_data *drv = priv; 633 int ret = 0; 634 u32 channel; 635 636 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 637 if (ret != 0) 638 return ret; 639 640 ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an, 641 sa->next_pn); 642 643 wpa_printf(MSG_INFO, "%s: npn=0x%x", __func__, sa->next_pn); 644 645 return ret; 646 } 647 648 649 static int macsec_qca_get_available_receive_sc(void *priv, u32 *channel) 650 { 651 struct macsec_qca_data *drv = priv; 652 int ret = 0; 653 u32 sc_ch = 0; 654 bool in_use = false; 655 656 for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) { 657 ret = nss_macsec_secy_rx_sc_in_used_get(drv->secy_id, sc_ch, 658 &in_use); 659 if (ret) 660 continue; 661 662 if (!in_use) { 663 *channel = sc_ch; 664 wpa_printf(MSG_DEBUG, "%s: channel=%d", 665 __func__, *channel); 666 return 0; 667 } 668 } 669 670 wpa_printf(MSG_DEBUG, "%s: no available channel", __func__); 671 672 return -1; 673 } 674 675 676 static int macsec_qca_create_receive_sc(void *priv, struct receive_sc *sc, 677 unsigned int conf_offset, 678 int validation) 679 { 680 struct macsec_qca_data *drv = priv; 681 int ret = 0; 682 fal_rx_prc_lut_t entry; 683 fal_rx_sc_validate_frame_e vf; 684 enum validate_frames validate_frames = validation; 685 u32 channel; 686 const u8 *sci_addr = sc->sci.addr; 687 u16 sci_port = be_to_host16(sc->sci.port); 688 689 ret = macsec_qca_get_available_receive_sc(priv, &channel); 690 if (ret != 0) 691 return ret; 692 693 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 694 695 /* rx prc lut */ 696 os_memset(&entry, 0, sizeof(entry)); 697 698 os_memcpy(entry.sci, sci_addr, ETH_ALEN); 699 entry.sci[6] = (sci_port >> 8) & 0xff; 700 entry.sci[7] = sci_port & 0xff; 701 entry.sci_mask = 0xf; 702 703 entry.valid = 1; 704 entry.channel = channel; 705 entry.action = FAL_RX_PRC_ACTION_PROCESS; 706 entry.offset = conf_offset; 707 708 /* rx validate frame */ 709 if (validate_frames == Strict) 710 vf = FAL_RX_SC_VALIDATE_FRAME_STRICT; 711 else if (validate_frames == Checked) 712 vf = FAL_RX_SC_VALIDATE_FRAME_CHECK; 713 else 714 vf = FAL_RX_SC_VALIDATE_FRAME_DISABLED; 715 716 ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry); 717 ret += nss_macsec_secy_rx_sc_create(drv->secy_id, channel); 718 ret += nss_macsec_secy_rx_sc_validate_frame_set(drv->secy_id, channel, 719 vf); 720 ret += nss_macsec_secy_rx_sc_replay_protect_set(drv->secy_id, channel, 721 drv->replay_protect); 722 ret += nss_macsec_secy_rx_sc_anti_replay_window_set(drv->secy_id, 723 channel, 724 drv->replay_window); 725 726 macsec_qca_register_receive_channel(drv, sc, channel); 727 728 return ret; 729 } 730 731 732 static int macsec_qca_delete_receive_sc(void *priv, struct receive_sc *sc) 733 { 734 struct macsec_qca_data *drv = priv; 735 int ret; 736 fal_rx_prc_lut_t entry; 737 u32 channel; 738 739 ret = macsec_qca_lookup_receive_channel(priv, sc, &channel); 740 if (ret != 0) 741 return ret; 742 743 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 744 745 /* rx prc lut */ 746 os_memset(&entry, 0, sizeof(entry)); 747 748 ret += nss_macsec_secy_rx_sc_del(drv->secy_id, channel); 749 ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry); 750 751 return ret; 752 } 753 754 755 static int macsec_qca_create_receive_sa(void *priv, struct receive_sa *sa) 756 { 757 struct macsec_qca_data *drv = priv; 758 int ret; 759 fal_rx_sak_t rx_sak; 760 int i = 0; 761 u32 channel; 762 fal_rx_prc_lut_t entry; 763 u32 offset; 764 765 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 766 if (ret != 0) 767 return ret; 768 769 wpa_printf(MSG_DEBUG, "%s, channel=%d, an=%d, lpn=0x%x", 770 __func__, channel, sa->an, sa->lowest_pn); 771 772 os_memset(&rx_sak, 0, sizeof(rx_sak)); 773 rx_sak.sak_len = sa->pkey->key_len; 774 if (sa->pkey->key_len == SAK_128_LEN) { 775 for (i = 0; i < 16; i++) 776 rx_sak.sak[i] = sa->pkey->key[15 - i]; 777 } else if (sa->pkey->key_len == SAK_256_LEN) { 778 for (i = 0; i < 16; i++) { 779 rx_sak.sak1[i] = sa->pkey->key[15 - i]; 780 rx_sak.sak[i] = sa->pkey->key[31 - i]; 781 } 782 } else { 783 return -1; 784 } 785 786 if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0) 787 offset = 0; 788 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30) 789 offset = 30; 790 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50) 791 offset = 50; 792 else 793 return -1; 794 ret += nss_macsec_secy_rx_prc_lut_get(drv->secy_id, channel, &entry); 795 entry.offset = offset; 796 ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry); 797 ret += nss_macsec_secy_rx_sa_create(drv->secy_id, channel, sa->an); 798 ret += nss_macsec_secy_rx_sak_set(drv->secy_id, channel, sa->an, 799 &rx_sak); 800 801 return ret; 802 } 803 804 805 static int macsec_qca_enable_receive_sa(void *priv, struct receive_sa *sa) 806 { 807 struct macsec_qca_data *drv = priv; 808 int ret; 809 u32 channel; 810 811 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 812 if (ret != 0) 813 return ret; 814 815 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 816 sa->an); 817 818 ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an, 819 true); 820 821 return ret; 822 } 823 824 825 static int macsec_qca_disable_receive_sa(void *priv, struct receive_sa *sa) 826 { 827 struct macsec_qca_data *drv = priv; 828 int ret; 829 u32 channel; 830 831 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 832 if (ret != 0) 833 return ret; 834 835 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 836 sa->an); 837 838 ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an, 839 false); 840 841 return ret; 842 } 843 844 845 static int macsec_qca_get_available_transmit_sc(void *priv, u32 *channel) 846 { 847 struct macsec_qca_data *drv = priv; 848 u32 sc_ch = 0; 849 bool in_use = false; 850 851 for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) { 852 if (nss_macsec_secy_tx_sc_in_used_get(drv->secy_id, sc_ch, 853 &in_use)) 854 continue; 855 856 if (!in_use) { 857 *channel = sc_ch; 858 wpa_printf(MSG_DEBUG, "%s: channel=%d", 859 __func__, *channel); 860 return 0; 861 } 862 } 863 864 wpa_printf(MSG_DEBUG, "%s: no avaiable channel", __func__); 865 866 return -1; 867 } 868 869 870 static int macsec_qca_create_transmit_sc(void *priv, struct transmit_sc *sc, 871 unsigned int conf_offset) 872 { 873 struct macsec_qca_data *drv = priv; 874 int ret; 875 fal_tx_class_lut_t entry; 876 u8 psci[ETH_ALEN + 2]; 877 u32 channel; 878 u16 sci_port = be_to_host16(sc->sci.port); 879 880 ret = macsec_qca_get_available_transmit_sc(priv, &channel); 881 if (ret != 0) 882 return ret; 883 884 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 885 886 /* class lut */ 887 os_memset(&entry, 0, sizeof(entry)); 888 889 entry.valid = 1; 890 entry.action = FAL_TX_CLASS_ACTION_FORWARD; 891 entry.channel = channel; 892 893 os_memcpy(psci, sc->sci.addr, ETH_ALEN); 894 psci[6] = (sci_port >> 8) & 0xff; 895 psci[7] = sci_port & 0xff; 896 897 ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry); 898 ret += nss_macsec_secy_tx_sc_create(drv->secy_id, channel, psci, 8); 899 ret += nss_macsec_secy_tx_sc_protect_set(drv->secy_id, channel, 900 drv->protect_frames); 901 ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id, 902 channel, 903 conf_offset); 904 905 macsec_qca_register_transmit_channel(drv, sc, channel); 906 907 return ret; 908 } 909 910 911 static int macsec_qca_delete_transmit_sc(void *priv, struct transmit_sc *sc) 912 { 913 struct macsec_qca_data *drv = priv; 914 int ret; 915 fal_tx_class_lut_t entry; 916 u32 channel; 917 918 ret = macsec_qca_lookup_transmit_channel(priv, sc, &channel); 919 if (ret != 0) 920 return ret; 921 922 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 923 924 /* class lut */ 925 os_memset(&entry, 0, sizeof(entry)); 926 927 ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry); 928 ret += nss_macsec_secy_tx_sc_del(drv->secy_id, channel); 929 930 return ret; 931 } 932 933 934 static int macsec_qca_create_transmit_sa(void *priv, struct transmit_sa *sa) 935 { 936 struct macsec_qca_data *drv = priv; 937 int ret; 938 u8 tci = 0; 939 fal_tx_sak_t tx_sak; 940 int i; 941 u32 channel; 942 u32 offset; 943 944 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 945 if (ret != 0) 946 return ret; 947 948 wpa_printf(MSG_DEBUG, 949 "%s: channel=%d, an=%d, next_pn=0x%x, confidentiality=%d", 950 __func__, channel, sa->an, sa->next_pn, sa->confidentiality); 951 952 if (drv->always_include_sci) 953 tci |= TCI_SC; 954 else if (drv->use_es) 955 tci |= TCI_ES; 956 else if (drv->use_scb) 957 tci |= TCI_SCB; 958 959 if (sa->confidentiality) 960 tci |= TCI_E | TCI_C; 961 962 os_memset(&tx_sak, 0, sizeof(tx_sak)); 963 tx_sak.sak_len = sa->pkey->key_len; 964 if (sa->pkey->key_len == SAK_128_LEN) { 965 for (i = 0; i < 16; i++) 966 tx_sak.sak[i] = sa->pkey->key[15 - i]; 967 } else if (sa->pkey->key_len == SAK_256_LEN) { 968 for (i = 0; i < 16; i++) { 969 tx_sak.sak1[i] = sa->pkey->key[15 - i]; 970 tx_sak.sak[i] = sa->pkey->key[31 - i]; 971 } 972 } else { 973 return -1; 974 } 975 976 if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0) 977 offset = 0; 978 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30) 979 offset = 30; 980 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50) 981 offset = 50; 982 else 983 return -1; 984 ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id, 985 channel, 986 offset); 987 ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an, 988 sa->next_pn); 989 ret += nss_macsec_secy_tx_sak_set(drv->secy_id, channel, sa->an, 990 &tx_sak); 991 ret += nss_macsec_secy_tx_sc_tci_7_2_set(drv->secy_id, channel, 992 (tci >> 2)); 993 ret += nss_macsec_secy_tx_sc_an_set(drv->secy_id, channel, sa->an); 994 995 return ret; 996 } 997 998 999 static int macsec_qca_enable_transmit_sa(void *priv, struct transmit_sa *sa) 1000 { 1001 struct macsec_qca_data *drv = priv; 1002 int ret; 1003 u32 channel; 1004 1005 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 1006 if (ret != 0) 1007 return ret; 1008 1009 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 1010 sa->an); 1011 1012 ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an, 1013 true); 1014 1015 return ret; 1016 } 1017 1018 1019 static int macsec_qca_disable_transmit_sa(void *priv, struct transmit_sa *sa) 1020 { 1021 struct macsec_qca_data *drv = priv; 1022 int ret; 1023 u32 channel; 1024 1025 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 1026 if (ret != 0) 1027 return ret; 1028 1029 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 1030 sa->an); 1031 1032 ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an, 1033 false); 1034 1035 return ret; 1036 } 1037 1038 1039 const struct wpa_driver_ops wpa_driver_macsec_qca_ops = { 1040 .name = "macsec_qca", 1041 .desc = "QCA MACsec Ethernet driver", 1042 .get_ssid = driver_wired_get_ssid, 1043 .get_bssid = driver_wired_get_bssid, 1044 .get_capa = driver_wired_get_capa, 1045 .init = macsec_qca_init, 1046 .deinit = macsec_qca_deinit, 1047 .hapd_init = macsec_qca_hapd_init, 1048 .hapd_deinit = macsec_qca_hapd_deinit, 1049 .hapd_send_eapol = macsec_qca_send_eapol, 1050 1051 .macsec_init = macsec_qca_macsec_init, 1052 .macsec_deinit = macsec_qca_macsec_deinit, 1053 .macsec_get_capability = macsec_qca_get_capability, 1054 .enable_protect_frames = macsec_qca_enable_protect_frames, 1055 .set_replay_protect = macsec_qca_set_replay_protect, 1056 .set_current_cipher_suite = macsec_qca_set_current_cipher_suite, 1057 .enable_controlled_port = macsec_qca_enable_controlled_port, 1058 .get_receive_lowest_pn = macsec_qca_get_receive_lowest_pn, 1059 .get_transmit_next_pn = macsec_qca_get_transmit_next_pn, 1060 .set_transmit_next_pn = macsec_qca_set_transmit_next_pn, 1061 .create_receive_sc = macsec_qca_create_receive_sc, 1062 .delete_receive_sc = macsec_qca_delete_receive_sc, 1063 .create_receive_sa = macsec_qca_create_receive_sa, 1064 .enable_receive_sa = macsec_qca_enable_receive_sa, 1065 .disable_receive_sa = macsec_qca_disable_receive_sa, 1066 .create_transmit_sc = macsec_qca_create_transmit_sc, 1067 .delete_transmit_sc = macsec_qca_delete_transmit_sc, 1068 .create_transmit_sa = macsec_qca_create_transmit_sa, 1069 .enable_transmit_sa = macsec_qca_enable_transmit_sa, 1070 .disable_transmit_sa = macsec_qca_disable_transmit_sa, 1071 }; 1072