1 /* 2 * Wired Ethernet driver interface for QCA MACsec driver 3 * Copyright (c) 2005-2009, Jouni Malinen <j (at) w1.fi> 4 * Copyright (c) 2004, Gunter Burchardt <tira (at) isx.de> 5 * Copyright (c) 2013-2014, Qualcomm Atheros, Inc. 6 * 7 * This software may be distributed under the terms of the BSD license. 8 * See README for more details. 9 */ 10 11 #include "includes.h" 12 #include <sys/ioctl.h> 13 #include <net/if.h> 14 #include <inttypes.h> 15 #ifdef __linux__ 16 #include <netpacket/packet.h> 17 #include <net/if_arp.h> 18 #include <net/if.h> 19 #endif /* __linux__ */ 20 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) 21 #include <net/if_dl.h> 22 #include <net/if_media.h> 23 #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */ 24 #ifdef __sun__ 25 #include <sys/sockio.h> 26 #endif /* __sun__ */ 27 28 #include "utils/common.h" 29 #include "utils/eloop.h" 30 #include "common/defs.h" 31 #include "common/ieee802_1x_defs.h" 32 #include "pae/ieee802_1x_kay.h" 33 #include "driver.h" 34 #include "driver_wired_common.h" 35 36 #include "nss_macsec_secy.h" 37 #include "nss_macsec_secy_rx.h" 38 #include "nss_macsec_secy_tx.h" 39 40 #define MAXSC 16 41 42 #define SAK_128_LEN 16 43 #define SAK_256_LEN 32 44 45 /* TCI field definition */ 46 #define TCI_ES 0x40 47 #define TCI_SC 0x20 48 #define TCI_SCB 0x10 49 #define TCI_E 0x08 50 #define TCI_C 0x04 51 52 #ifdef _MSC_VER 53 #pragma pack(push, 1) 54 #endif /* _MSC_VER */ 55 56 #ifdef _MSC_VER 57 #pragma pack(pop) 58 #endif /* _MSC_VER */ 59 60 struct channel_map { 61 struct ieee802_1x_mka_sci sci; 62 }; 63 64 struct macsec_qca_data { 65 struct driver_wired_common_data common; 66 67 u32 secy_id; 68 69 /* shadow */ 70 Boolean always_include_sci; 71 Boolean use_es; 72 Boolean use_scb; 73 Boolean protect_frames; 74 Boolean replay_protect; 75 u32 replay_window; 76 77 struct channel_map receive_channel_map[MAXSC]; 78 struct channel_map transmit_channel_map[MAXSC]; 79 }; 80 81 82 static void __macsec_drv_init(struct macsec_qca_data *drv) 83 { 84 int ret = 0; 85 fal_rx_ctl_filt_t rx_ctl_filt; 86 fal_tx_ctl_filt_t tx_ctl_filt; 87 88 wpa_printf(MSG_INFO, "%s: secy_id=%d", __func__, drv->secy_id); 89 90 /* Enable Secy and Let EAPoL bypass */ 91 ret = nss_macsec_secy_en_set(drv->secy_id, TRUE); 92 if (ret) 93 wpa_printf(MSG_ERROR, "nss_macsec_secy_en_set: FAIL"); 94 95 ret = nss_macsec_secy_sc_sa_mapping_mode_set(drv->secy_id, 96 FAL_SC_SA_MAP_1_4); 97 if (ret) 98 wpa_printf(MSG_ERROR, 99 "nss_macsec_secy_sc_sa_mapping_mode_set: FAIL"); 100 101 os_memset(&rx_ctl_filt, 0, sizeof(rx_ctl_filt)); 102 rx_ctl_filt.bypass = 1; 103 rx_ctl_filt.match_type = IG_CTL_COMPARE_ETHER_TYPE; 104 rx_ctl_filt.match_mask = 0xffff; 105 rx_ctl_filt.ether_type_da_range = 0x888e; 106 ret = nss_macsec_secy_rx_ctl_filt_set(drv->secy_id, 0, &rx_ctl_filt); 107 if (ret) 108 wpa_printf(MSG_ERROR, "nss_macsec_secy_rx_ctl_filt_set: FAIL"); 109 110 os_memset(&tx_ctl_filt, 0, sizeof(tx_ctl_filt)); 111 tx_ctl_filt.bypass = 1; 112 tx_ctl_filt.match_type = EG_CTL_COMPARE_ETHER_TYPE; 113 tx_ctl_filt.match_mask = 0xffff; 114 tx_ctl_filt.ether_type_da_range = 0x888e; 115 ret = nss_macsec_secy_tx_ctl_filt_set(drv->secy_id, 0, &tx_ctl_filt); 116 if (ret) 117 wpa_printf(MSG_ERROR, "nss_macsec_secy_tx_ctl_filt_set: FAIL"); 118 } 119 120 121 static void __macsec_drv_deinit(struct macsec_qca_data *drv) 122 { 123 nss_macsec_secy_en_set(drv->secy_id, FALSE); 124 nss_macsec_secy_rx_sc_del_all(drv->secy_id); 125 nss_macsec_secy_tx_sc_del_all(drv->secy_id); 126 } 127 128 129 static void * macsec_qca_init(void *ctx, const char *ifname) 130 { 131 struct macsec_qca_data *drv; 132 133 drv = os_zalloc(sizeof(*drv)); 134 if (drv == NULL) 135 return NULL; 136 137 /* Board specific settings */ 138 if (os_memcmp("eth2", ifname, 4) == 0) 139 drv->secy_id = 1; 140 else if (os_memcmp("eth3", ifname, 4) == 0) 141 drv->secy_id = 2; 142 else 143 drv->secy_id = -1; 144 145 if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) { 146 os_free(drv); 147 return NULL; 148 } 149 150 return drv; 151 } 152 153 154 static void macsec_qca_deinit(void *priv) 155 { 156 struct macsec_qca_data *drv = priv; 157 158 driver_wired_deinit_common(&drv->common); 159 os_free(drv); 160 } 161 162 163 static int macsec_qca_macsec_init(void *priv, struct macsec_init_params *params) 164 { 165 struct macsec_qca_data *drv = priv; 166 167 drv->always_include_sci = params->always_include_sci; 168 drv->use_es = params->use_es; 169 drv->use_scb = params->use_scb; 170 171 wpa_printf(MSG_DEBUG, "%s: es=%d, scb=%d, sci=%d", 172 __func__, drv->use_es, drv->use_scb, 173 drv->always_include_sci); 174 175 __macsec_drv_init(drv); 176 177 return 0; 178 } 179 180 181 static int macsec_qca_macsec_deinit(void *priv) 182 { 183 struct macsec_qca_data *drv = priv; 184 185 wpa_printf(MSG_DEBUG, "%s", __func__); 186 187 __macsec_drv_deinit(drv); 188 189 return 0; 190 } 191 192 193 static int macsec_qca_get_capability(void *priv, enum macsec_cap *cap) 194 { 195 wpa_printf(MSG_DEBUG, "%s", __func__); 196 197 *cap = MACSEC_CAP_INTEG_AND_CONF_0_30_50; 198 199 return 0; 200 } 201 202 203 static int macsec_qca_enable_protect_frames(void *priv, Boolean enabled) 204 { 205 struct macsec_qca_data *drv = priv; 206 int ret = 0; 207 208 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 209 210 drv->protect_frames = enabled; 211 212 return ret; 213 } 214 215 216 static int macsec_qca_set_replay_protect(void *priv, Boolean enabled, 217 unsigned int window) 218 { 219 struct macsec_qca_data *drv = priv; 220 int ret = 0; 221 222 wpa_printf(MSG_DEBUG, "%s: enabled=%d, win=%u", 223 __func__, enabled, window); 224 225 drv->replay_protect = enabled; 226 drv->replay_window = window; 227 228 return ret; 229 } 230 231 232 static fal_cipher_suite_e macsec_qca_cs_type_get(u64 cs) 233 { 234 if (cs == CS_ID_GCM_AES_128) 235 return FAL_CIPHER_SUITE_AES_GCM_128; 236 if (cs == CS_ID_GCM_AES_256) 237 return FAL_CIPHER_SUITE_AES_GCM_256; 238 return FAL_CIPHER_SUITE_MAX; 239 } 240 241 242 static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs) 243 { 244 struct macsec_qca_data *drv = priv; 245 fal_cipher_suite_e cs_type; 246 247 if (cs != CS_ID_GCM_AES_128 && cs != CS_ID_GCM_AES_256) { 248 wpa_printf(MSG_ERROR, 249 "%s: NOT supported CipherSuite: %016" PRIx64, 250 __func__, cs); 251 return -1; 252 } 253 254 wpa_printf(MSG_DEBUG, "%s: CipherSuite: %016" PRIx64, __func__, cs); 255 256 cs_type = macsec_qca_cs_type_get(cs); 257 return nss_macsec_secy_cipher_suite_set(drv->secy_id, cs_type); 258 } 259 260 261 static int macsec_qca_enable_controlled_port(void *priv, Boolean enabled) 262 { 263 struct macsec_qca_data *drv = priv; 264 int ret = 0; 265 266 wpa_printf(MSG_DEBUG, "%s: enable=%d", __func__, enabled); 267 268 ret += nss_macsec_secy_controlled_port_en_set(drv->secy_id, enabled); 269 270 return ret; 271 } 272 273 274 static int macsec_qca_lookup_channel(struct channel_map *map, 275 struct ieee802_1x_mka_sci *sci, 276 u32 *channel) 277 { 278 u32 i; 279 280 for (i = 0; i < MAXSC; i++) { 281 if (os_memcmp(&map[i].sci, sci, 282 sizeof(struct ieee802_1x_mka_sci)) == 0) { 283 *channel = i; 284 return 0; 285 } 286 } 287 288 return -1; 289 } 290 291 292 static void macsec_qca_register_channel(struct channel_map *map, 293 struct ieee802_1x_mka_sci *sci, 294 u32 channel) 295 { 296 os_memcpy(&map[channel].sci, sci, sizeof(struct ieee802_1x_mka_sci)); 297 } 298 299 300 static int macsec_qca_lookup_receive_channel(struct macsec_qca_data *drv, 301 struct receive_sc *sc, 302 u32 *channel) 303 { 304 return macsec_qca_lookup_channel(drv->receive_channel_map, &sc->sci, 305 channel); 306 } 307 308 309 static void macsec_qca_register_receive_channel(struct macsec_qca_data *drv, 310 struct receive_sc *sc, 311 u32 channel) 312 { 313 macsec_qca_register_channel(drv->receive_channel_map, &sc->sci, 314 channel); 315 } 316 317 318 static int macsec_qca_lookup_transmit_channel(struct macsec_qca_data *drv, 319 struct transmit_sc *sc, 320 u32 *channel) 321 { 322 return macsec_qca_lookup_channel(drv->transmit_channel_map, &sc->sci, 323 channel); 324 } 325 326 327 static void macsec_qca_register_transmit_channel(struct macsec_qca_data *drv, 328 struct transmit_sc *sc, 329 u32 channel) 330 { 331 macsec_qca_register_channel(drv->transmit_channel_map, &sc->sci, 332 channel); 333 } 334 335 336 static int macsec_qca_get_receive_lowest_pn(void *priv, struct receive_sa *sa) 337 { 338 struct macsec_qca_data *drv = priv; 339 int ret = 0; 340 u32 next_pn = 0; 341 bool enabled = FALSE; 342 u32 win; 343 u32 channel; 344 345 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 346 if (ret != 0) 347 return ret; 348 349 ret += nss_macsec_secy_rx_sa_next_pn_get(drv->secy_id, channel, sa->an, 350 &next_pn); 351 ret += nss_macsec_secy_rx_sc_replay_protect_get(drv->secy_id, channel, 352 &enabled); 353 ret += nss_macsec_secy_rx_sc_anti_replay_window_get(drv->secy_id, 354 channel, &win); 355 356 if (enabled) 357 sa->lowest_pn = (next_pn > win) ? (next_pn - win) : 1; 358 else 359 sa->lowest_pn = next_pn; 360 361 wpa_printf(MSG_DEBUG, "%s: lpn=0x%x", __func__, sa->lowest_pn); 362 363 return ret; 364 } 365 366 367 static int macsec_qca_get_transmit_next_pn(void *priv, struct transmit_sa *sa) 368 { 369 struct macsec_qca_data *drv = priv; 370 int ret = 0; 371 u32 channel; 372 373 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 374 if (ret != 0) 375 return ret; 376 377 ret += nss_macsec_secy_tx_sa_next_pn_get(drv->secy_id, channel, sa->an, 378 &sa->next_pn); 379 380 wpa_printf(MSG_DEBUG, "%s: npn=0x%x", __func__, sa->next_pn); 381 382 return ret; 383 } 384 385 386 static int macsec_qca_set_transmit_next_pn(void *priv, struct transmit_sa *sa) 387 { 388 struct macsec_qca_data *drv = priv; 389 int ret = 0; 390 u32 channel; 391 392 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 393 if (ret != 0) 394 return ret; 395 396 ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an, 397 sa->next_pn); 398 399 wpa_printf(MSG_INFO, "%s: npn=0x%x", __func__, sa->next_pn); 400 401 return ret; 402 } 403 404 405 static int macsec_qca_get_available_receive_sc(void *priv, u32 *channel) 406 { 407 struct macsec_qca_data *drv = priv; 408 int ret = 0; 409 u32 sc_ch = 0; 410 bool in_use = FALSE; 411 412 for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) { 413 ret = nss_macsec_secy_rx_sc_in_used_get(drv->secy_id, sc_ch, 414 &in_use); 415 if (ret) 416 continue; 417 418 if (!in_use) { 419 *channel = sc_ch; 420 wpa_printf(MSG_DEBUG, "%s: channel=%d", 421 __func__, *channel); 422 return 0; 423 } 424 } 425 426 wpa_printf(MSG_DEBUG, "%s: no available channel", __func__); 427 428 return -1; 429 } 430 431 432 static int macsec_qca_create_receive_sc(void *priv, struct receive_sc *sc, 433 unsigned int conf_offset, 434 int validation) 435 { 436 struct macsec_qca_data *drv = priv; 437 int ret = 0; 438 fal_rx_prc_lut_t entry; 439 fal_rx_sc_validate_frame_e vf; 440 enum validate_frames validate_frames = validation; 441 u32 channel; 442 const u8 *sci_addr = sc->sci.addr; 443 u16 sci_port = be_to_host16(sc->sci.port); 444 445 ret = macsec_qca_get_available_receive_sc(priv, &channel); 446 if (ret != 0) 447 return ret; 448 449 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 450 451 /* rx prc lut */ 452 os_memset(&entry, 0, sizeof(entry)); 453 454 os_memcpy(entry.sci, sci_addr, ETH_ALEN); 455 entry.sci[6] = (sci_port >> 8) & 0xff; 456 entry.sci[7] = sci_port & 0xff; 457 entry.sci_mask = 0xf; 458 459 entry.valid = 1; 460 entry.channel = channel; 461 entry.action = FAL_RX_PRC_ACTION_PROCESS; 462 entry.offset = conf_offset; 463 464 /* rx validate frame */ 465 if (validate_frames == Strict) 466 vf = FAL_RX_SC_VALIDATE_FRAME_STRICT; 467 else if (validate_frames == Checked) 468 vf = FAL_RX_SC_VALIDATE_FRAME_CHECK; 469 else 470 vf = FAL_RX_SC_VALIDATE_FRAME_DISABLED; 471 472 ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry); 473 ret += nss_macsec_secy_rx_sc_create(drv->secy_id, channel); 474 ret += nss_macsec_secy_rx_sc_validate_frame_set(drv->secy_id, channel, 475 vf); 476 ret += nss_macsec_secy_rx_sc_replay_protect_set(drv->secy_id, channel, 477 drv->replay_protect); 478 ret += nss_macsec_secy_rx_sc_anti_replay_window_set(drv->secy_id, 479 channel, 480 drv->replay_window); 481 482 macsec_qca_register_receive_channel(drv, sc, channel); 483 484 return ret; 485 } 486 487 488 static int macsec_qca_delete_receive_sc(void *priv, struct receive_sc *sc) 489 { 490 struct macsec_qca_data *drv = priv; 491 int ret; 492 fal_rx_prc_lut_t entry; 493 u32 channel; 494 495 ret = macsec_qca_lookup_receive_channel(priv, sc, &channel); 496 if (ret != 0) 497 return ret; 498 499 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 500 501 /* rx prc lut */ 502 os_memset(&entry, 0, sizeof(entry)); 503 504 ret += nss_macsec_secy_rx_sc_del(drv->secy_id, channel); 505 ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry); 506 507 return ret; 508 } 509 510 511 static int macsec_qca_create_receive_sa(void *priv, struct receive_sa *sa) 512 { 513 struct macsec_qca_data *drv = priv; 514 int ret; 515 fal_rx_sak_t rx_sak; 516 int i = 0; 517 u32 channel; 518 fal_rx_prc_lut_t entry; 519 u32 offset; 520 521 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 522 if (ret != 0) 523 return ret; 524 525 wpa_printf(MSG_DEBUG, "%s, channel=%d, an=%d, lpn=0x%x", 526 __func__, channel, sa->an, sa->lowest_pn); 527 528 os_memset(&rx_sak, 0, sizeof(rx_sak)); 529 rx_sak.sak_len = sa->pkey->key_len; 530 if (sa->pkey->key_len == SAK_128_LEN) { 531 for (i = 0; i < 16; i++) 532 rx_sak.sak[i] = sa->pkey->key[15 - i]; 533 } else if (sa->pkey->key_len == SAK_256_LEN) { 534 for (i = 0; i < 16; i++) { 535 rx_sak.sak1[i] = sa->pkey->key[15 - i]; 536 rx_sak.sak[i] = sa->pkey->key[31 - i]; 537 } 538 } else { 539 return -1; 540 } 541 542 if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0) 543 offset = 0; 544 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30) 545 offset = 30; 546 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50) 547 offset = 50; 548 else 549 return -1; 550 ret += nss_macsec_secy_rx_prc_lut_get(drv->secy_id, channel, &entry); 551 entry.offset = offset; 552 ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry); 553 ret += nss_macsec_secy_rx_sa_create(drv->secy_id, channel, sa->an); 554 ret += nss_macsec_secy_rx_sak_set(drv->secy_id, channel, sa->an, 555 &rx_sak); 556 557 return ret; 558 } 559 560 561 static int macsec_qca_enable_receive_sa(void *priv, struct receive_sa *sa) 562 { 563 struct macsec_qca_data *drv = priv; 564 int ret; 565 u32 channel; 566 567 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 568 if (ret != 0) 569 return ret; 570 571 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 572 sa->an); 573 574 ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an, 575 TRUE); 576 577 return ret; 578 } 579 580 581 static int macsec_qca_disable_receive_sa(void *priv, struct receive_sa *sa) 582 { 583 struct macsec_qca_data *drv = priv; 584 int ret; 585 u32 channel; 586 587 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 588 if (ret != 0) 589 return ret; 590 591 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 592 sa->an); 593 594 ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an, 595 FALSE); 596 597 return ret; 598 } 599 600 601 static int macsec_qca_get_available_transmit_sc(void *priv, u32 *channel) 602 { 603 struct macsec_qca_data *drv = priv; 604 u32 sc_ch = 0; 605 bool in_use = FALSE; 606 607 for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) { 608 if (nss_macsec_secy_tx_sc_in_used_get(drv->secy_id, sc_ch, 609 &in_use)) 610 continue; 611 612 if (!in_use) { 613 *channel = sc_ch; 614 wpa_printf(MSG_DEBUG, "%s: channel=%d", 615 __func__, *channel); 616 return 0; 617 } 618 } 619 620 wpa_printf(MSG_DEBUG, "%s: no avaiable channel", __func__); 621 622 return -1; 623 } 624 625 626 static int macsec_qca_create_transmit_sc(void *priv, struct transmit_sc *sc, 627 unsigned int conf_offset) 628 { 629 struct macsec_qca_data *drv = priv; 630 int ret; 631 fal_tx_class_lut_t entry; 632 u8 psci[ETH_ALEN + 2]; 633 u32 channel; 634 u16 sci_port = be_to_host16(sc->sci.port); 635 636 ret = macsec_qca_get_available_transmit_sc(priv, &channel); 637 if (ret != 0) 638 return ret; 639 640 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 641 642 /* class lut */ 643 os_memset(&entry, 0, sizeof(entry)); 644 645 entry.valid = 1; 646 entry.action = FAL_TX_CLASS_ACTION_FORWARD; 647 entry.channel = channel; 648 649 os_memcpy(psci, sc->sci.addr, ETH_ALEN); 650 psci[6] = (sci_port >> 8) & 0xff; 651 psci[7] = sci_port & 0xff; 652 653 ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry); 654 ret += nss_macsec_secy_tx_sc_create(drv->secy_id, channel, psci, 8); 655 ret += nss_macsec_secy_tx_sc_protect_set(drv->secy_id, channel, 656 drv->protect_frames); 657 ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id, 658 channel, 659 conf_offset); 660 661 macsec_qca_register_transmit_channel(drv, sc, channel); 662 663 return ret; 664 } 665 666 667 static int macsec_qca_delete_transmit_sc(void *priv, struct transmit_sc *sc) 668 { 669 struct macsec_qca_data *drv = priv; 670 int ret; 671 fal_tx_class_lut_t entry; 672 u32 channel; 673 674 ret = macsec_qca_lookup_transmit_channel(priv, sc, &channel); 675 if (ret != 0) 676 return ret; 677 678 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 679 680 /* class lut */ 681 os_memset(&entry, 0, sizeof(entry)); 682 683 ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry); 684 ret += nss_macsec_secy_tx_sc_del(drv->secy_id, channel); 685 686 return ret; 687 } 688 689 690 static int macsec_qca_create_transmit_sa(void *priv, struct transmit_sa *sa) 691 { 692 struct macsec_qca_data *drv = priv; 693 int ret; 694 u8 tci = 0; 695 fal_tx_sak_t tx_sak; 696 int i; 697 u32 channel; 698 u32 offset; 699 700 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 701 if (ret != 0) 702 return ret; 703 704 wpa_printf(MSG_DEBUG, 705 "%s: channel=%d, an=%d, next_pn=0x%x, confidentiality=%d", 706 __func__, channel, sa->an, sa->next_pn, sa->confidentiality); 707 708 if (drv->always_include_sci) 709 tci |= TCI_SC; 710 else if (drv->use_es) 711 tci |= TCI_ES; 712 else if (drv->use_scb) 713 tci |= TCI_SCB; 714 715 if (sa->confidentiality) 716 tci |= TCI_E | TCI_C; 717 718 os_memset(&tx_sak, 0, sizeof(tx_sak)); 719 tx_sak.sak_len = sa->pkey->key_len; 720 if (sa->pkey->key_len == SAK_128_LEN) { 721 for (i = 0; i < 16; i++) 722 tx_sak.sak[i] = sa->pkey->key[15 - i]; 723 } else if (sa->pkey->key_len == SAK_256_LEN) { 724 for (i = 0; i < 16; i++) { 725 tx_sak.sak1[i] = sa->pkey->key[15 - i]; 726 tx_sak.sak[i] = sa->pkey->key[31 - i]; 727 } 728 } else { 729 return -1; 730 } 731 732 if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0) 733 offset = 0; 734 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30) 735 offset = 30; 736 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50) 737 offset = 50; 738 else 739 return -1; 740 ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id, 741 channel, 742 offset); 743 ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an, 744 sa->next_pn); 745 ret += nss_macsec_secy_tx_sak_set(drv->secy_id, channel, sa->an, 746 &tx_sak); 747 ret += nss_macsec_secy_tx_sc_tci_7_2_set(drv->secy_id, channel, 748 (tci >> 2)); 749 ret += nss_macsec_secy_tx_sc_an_set(drv->secy_id, channel, sa->an); 750 751 return ret; 752 } 753 754 755 static int macsec_qca_enable_transmit_sa(void *priv, struct transmit_sa *sa) 756 { 757 struct macsec_qca_data *drv = priv; 758 int ret; 759 u32 channel; 760 761 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 762 if (ret != 0) 763 return ret; 764 765 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 766 sa->an); 767 768 ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an, 769 TRUE); 770 771 return ret; 772 } 773 774 775 static int macsec_qca_disable_transmit_sa(void *priv, struct transmit_sa *sa) 776 { 777 struct macsec_qca_data *drv = priv; 778 int ret; 779 u32 channel; 780 781 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 782 if (ret != 0) 783 return ret; 784 785 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 786 sa->an); 787 788 ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an, 789 FALSE); 790 791 return ret; 792 } 793 794 795 const struct wpa_driver_ops wpa_driver_macsec_qca_ops = { 796 .name = "macsec_qca", 797 .desc = "QCA MACsec Ethernet driver", 798 .get_ssid = driver_wired_get_ssid, 799 .get_bssid = driver_wired_get_bssid, 800 .get_capa = driver_wired_get_capa, 801 .init = macsec_qca_init, 802 .deinit = macsec_qca_deinit, 803 804 .macsec_init = macsec_qca_macsec_init, 805 .macsec_deinit = macsec_qca_macsec_deinit, 806 .macsec_get_capability = macsec_qca_get_capability, 807 .enable_protect_frames = macsec_qca_enable_protect_frames, 808 .set_replay_protect = macsec_qca_set_replay_protect, 809 .set_current_cipher_suite = macsec_qca_set_current_cipher_suite, 810 .enable_controlled_port = macsec_qca_enable_controlled_port, 811 .get_receive_lowest_pn = macsec_qca_get_receive_lowest_pn, 812 .get_transmit_next_pn = macsec_qca_get_transmit_next_pn, 813 .set_transmit_next_pn = macsec_qca_set_transmit_next_pn, 814 .create_receive_sc = macsec_qca_create_receive_sc, 815 .delete_receive_sc = macsec_qca_delete_receive_sc, 816 .create_receive_sa = macsec_qca_create_receive_sa, 817 .enable_receive_sa = macsec_qca_enable_receive_sa, 818 .disable_receive_sa = macsec_qca_disable_receive_sa, 819 .create_transmit_sc = macsec_qca_create_transmit_sc, 820 .delete_transmit_sc = macsec_qca_delete_transmit_sc, 821 .create_transmit_sa = macsec_qca_create_transmit_sa, 822 .enable_transmit_sa = macsec_qca_enable_transmit_sa, 823 .disable_transmit_sa = macsec_qca_disable_transmit_sa, 824 }; 825