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
8 * This software may be distributed under the terms of the BSD license.
9 * See README for more details.
13 #include <sys/ioctl.h>
17 #include <netpacket/packet.h>
18 #include <net/if_arp.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__) */
26 #include <sys/sockio.h>
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"
36 #include "driver_wired_common.h"
38 #include "nss_macsec_secy.h"
39 #include "nss_macsec_secy_rx.h"
40 #include "nss_macsec_secy_tx.h"
44 #define SAK_128_LEN 16
45 #define SAK_256_LEN 32
47 /* TCI field definition */
63 struct ieee802_1x_mka_sci sci;
66 struct macsec_qca_data {
67 struct driver_wired_common_data common;
69 int use_pae_group_addr;
73 Boolean always_include_sci;
76 Boolean protect_frames;
77 Boolean replay_protect;
80 struct channel_map receive_channel_map[MAXSC];
81 struct channel_map transmit_channel_map[MAXSC];
85 static void __macsec_drv_init(struct macsec_qca_data *drv)
88 fal_rx_ctl_filt_t rx_ctl_filt;
89 fal_tx_ctl_filt_t tx_ctl_filt;
91 wpa_printf(MSG_INFO, "%s: secy_id=%d", __func__, drv->secy_id);
93 /* Enable Secy and Let EAPoL bypass */
94 ret = nss_macsec_secy_en_set(drv->secy_id, TRUE);
96 wpa_printf(MSG_ERROR, "nss_macsec_secy_en_set: FAIL");
98 ret = nss_macsec_secy_sc_sa_mapping_mode_set(drv->secy_id,
101 wpa_printf(MSG_ERROR,
102 "nss_macsec_secy_sc_sa_mapping_mode_set: FAIL");
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);
111 wpa_printf(MSG_ERROR, "nss_macsec_secy_rx_ctl_filt_set: FAIL");
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);
120 wpa_printf(MSG_ERROR, "nss_macsec_secy_tx_ctl_filt_set: FAIL");
124 static void __macsec_drv_deinit(struct macsec_qca_data *drv)
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);
134 static void macsec_qca_handle_data(void *ctx, unsigned char *buf, size_t len)
137 struct ieee8023_hdr *hdr;
140 union wpa_event_data event;
142 /* at least 6 bytes src macaddress, 6 bytes dst macaddress
143 * and 2 bytes ethertype
146 wpa_printf(MSG_MSGDUMP,
147 "macsec_qca_handle_data: too short (%lu)",
148 (unsigned long) len);
151 hdr = (struct ieee8023_hdr *) buf;
153 switch (ntohs(hdr->ethertype)) {
155 wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
157 os_memset(&event, 0, sizeof(event));
158 event.new_sta.addr = sa;
159 wpa_supplicant_event(ctx, EVENT_NEW_STA, &event);
161 pos = (u8 *) (hdr + 1);
162 left = len - sizeof(*hdr);
163 drv_event_eapol_rx(ctx, sa, pos, left);
166 wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame",
167 ntohs(hdr->ethertype));
174 static void macsec_qca_handle_read(int sock, void *eloop_ctx, void *sock_ctx)
177 unsigned char buf[3000];
179 len = recv(sock, buf, sizeof(buf), 0);
181 wpa_printf(MSG_ERROR, "macsec_qca: recv: %s", strerror(errno));
185 macsec_qca_handle_data(eloop_ctx, buf, len);
188 #endif /* __linux__ */
191 static int macsec_qca_init_sockets(struct macsec_qca_data *drv, u8 *own_addr)
195 struct sockaddr_ll addr;
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",
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");
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",
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",
224 if (bind(drv->common.sock, (struct sockaddr *) &addr,
226 wpa_printf(MSG_ERROR, "macsec_qca: bind: %s", strerror(errno));
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");
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",
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);
251 os_memcpy(own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
254 #else /* __linux__ */
256 #endif /* __linux__ */
260 static void * macsec_qca_init(void *ctx, const char *ifname)
262 struct macsec_qca_data *drv;
264 drv = os_zalloc(sizeof(*drv));
268 /* Board specific settings */
269 if (os_memcmp("eth2", ifname, 4) == 0)
271 else if (os_memcmp("eth3", ifname, 4) == 0)
276 if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) {
285 static void macsec_qca_deinit(void *priv)
287 struct macsec_qca_data *drv = priv;
289 driver_wired_deinit_common(&drv->common);
294 static void * macsec_qca_hapd_init(struct hostapd_data *hapd,
295 struct wpa_init_params *params)
297 struct macsec_qca_data *drv;
299 drv = os_zalloc(sizeof(struct macsec_qca_data));
302 "Could not allocate memory for macsec_qca driver data");
306 /* Board specific settings */
307 if (os_memcmp("eth2", params->ifname, 4) == 0)
309 else if (os_memcmp("eth3", params->ifname, 4) == 0)
311 else if (os_memcmp("eth4", params->ifname, 4) == 0)
313 else if (os_memcmp("eth5", params->ifname, 4) == 0)
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;
323 if (macsec_qca_init_sockets(drv, params->own_addr)) {
332 static void macsec_qca_hapd_deinit(void *priv)
334 struct macsec_qca_data *drv = priv;
336 if (drv->common.sock >= 0) {
337 eloop_unregister_read_sock(drv->common.sock);
338 close(drv->common.sock);
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)
349 struct macsec_qca_data *drv = priv;
350 struct ieee8023_hdr *hdr;
355 len = sizeof(*hdr) + data_len;
356 hdr = os_zalloc(len);
359 "malloc() failed for macsec_qca_send_eapol(len=%lu)",
360 (unsigned long) len);
364 os_memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr,
366 os_memcpy(hdr->src, own_addr, ETH_ALEN);
367 hdr->ethertype = htons(ETH_P_PAE);
369 pos = (u8 *) (hdr + 1);
370 os_memcpy(pos, data, data_len);
372 res = send(drv->common.sock, (u8 *) hdr, len, 0);
376 wpa_printf(MSG_ERROR,
377 "macsec_qca_send_eapol - packet len: %lu - failed: send: %s",
378 (unsigned long) len, strerror(errno));
385 static int macsec_qca_macsec_init(void *priv, struct macsec_init_params *params)
387 struct macsec_qca_data *drv = priv;
389 drv->always_include_sci = params->always_include_sci;
390 drv->use_es = params->use_es;
391 drv->use_scb = params->use_scb;
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);
397 __macsec_drv_init(drv);
403 static int macsec_qca_macsec_deinit(void *priv)
405 struct macsec_qca_data *drv = priv;
407 wpa_printf(MSG_DEBUG, "%s", __func__);
409 __macsec_drv_deinit(drv);
415 static int macsec_qca_get_capability(void *priv, enum macsec_cap *cap)
417 wpa_printf(MSG_DEBUG, "%s", __func__);
419 *cap = MACSEC_CAP_INTEG_AND_CONF_0_30_50;
425 static int macsec_qca_enable_protect_frames(void *priv, Boolean enabled)
427 struct macsec_qca_data *drv = priv;
430 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
432 drv->protect_frames = enabled;
438 static int macsec_qca_set_replay_protect(void *priv, Boolean enabled,
441 struct macsec_qca_data *drv = priv;
444 wpa_printf(MSG_DEBUG, "%s: enabled=%d, win=%u",
445 __func__, enabled, window);
447 drv->replay_protect = enabled;
448 drv->replay_window = window;
454 static fal_cipher_suite_e macsec_qca_cs_type_get(u64 cs)
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;
464 static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs)
466 struct macsec_qca_data *drv = priv;
467 fal_cipher_suite_e cs_type;
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,
476 wpa_printf(MSG_DEBUG, "%s: CipherSuite: %016" PRIx64, __func__, cs);
478 cs_type = macsec_qca_cs_type_get(cs);
479 return nss_macsec_secy_cipher_suite_set(drv->secy_id, cs_type);
483 static int macsec_qca_enable_controlled_port(void *priv, Boolean enabled)
485 struct macsec_qca_data *drv = priv;
488 wpa_printf(MSG_DEBUG, "%s: enable=%d", __func__, enabled);
490 ret += nss_macsec_secy_controlled_port_en_set(drv->secy_id, enabled);
496 static int macsec_qca_lookup_channel(struct channel_map *map,
497 struct ieee802_1x_mka_sci *sci,
502 for (i = 0; i < MAXSC; i++) {
503 if (os_memcmp(&map[i].sci, sci,
504 sizeof(struct ieee802_1x_mka_sci)) == 0) {
514 static void macsec_qca_register_channel(struct channel_map *map,
515 struct ieee802_1x_mka_sci *sci,
518 os_memcpy(&map[channel].sci, sci, sizeof(struct ieee802_1x_mka_sci));
522 static int macsec_qca_lookup_receive_channel(struct macsec_qca_data *drv,
523 struct receive_sc *sc,
526 return macsec_qca_lookup_channel(drv->receive_channel_map, &sc->sci,
531 static void macsec_qca_register_receive_channel(struct macsec_qca_data *drv,
532 struct receive_sc *sc,
535 macsec_qca_register_channel(drv->receive_channel_map, &sc->sci,
540 static int macsec_qca_lookup_transmit_channel(struct macsec_qca_data *drv,
541 struct transmit_sc *sc,
544 return macsec_qca_lookup_channel(drv->transmit_channel_map, &sc->sci,
549 static void macsec_qca_register_transmit_channel(struct macsec_qca_data *drv,
550 struct transmit_sc *sc,
553 macsec_qca_register_channel(drv->transmit_channel_map, &sc->sci,
558 static int macsec_qca_get_receive_lowest_pn(void *priv, struct receive_sa *sa)
560 struct macsec_qca_data *drv = priv;
563 bool enabled = FALSE;
567 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
571 ret += nss_macsec_secy_rx_sa_next_pn_get(drv->secy_id, channel, sa->an,
573 ret += nss_macsec_secy_rx_sc_replay_protect_get(drv->secy_id, channel,
575 ret += nss_macsec_secy_rx_sc_anti_replay_window_get(drv->secy_id,
579 sa->lowest_pn = (next_pn > win) ? (next_pn - win) : 1;
581 sa->lowest_pn = next_pn;
583 wpa_printf(MSG_DEBUG, "%s: lpn=0x%x", __func__, sa->lowest_pn);
589 static int macsec_qca_get_transmit_next_pn(void *priv, struct transmit_sa *sa)
591 struct macsec_qca_data *drv = priv;
595 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
599 ret += nss_macsec_secy_tx_sa_next_pn_get(drv->secy_id, channel, sa->an,
602 wpa_printf(MSG_DEBUG, "%s: npn=0x%x", __func__, sa->next_pn);
608 static int macsec_qca_set_transmit_next_pn(void *priv, struct transmit_sa *sa)
610 struct macsec_qca_data *drv = priv;
614 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
618 ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an,
621 wpa_printf(MSG_INFO, "%s: npn=0x%x", __func__, sa->next_pn);
627 static int macsec_qca_get_available_receive_sc(void *priv, u32 *channel)
629 struct macsec_qca_data *drv = priv;
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,
642 wpa_printf(MSG_DEBUG, "%s: channel=%d",
648 wpa_printf(MSG_DEBUG, "%s: no available channel", __func__);
654 static int macsec_qca_create_receive_sc(void *priv, struct receive_sc *sc,
655 unsigned int conf_offset,
658 struct macsec_qca_data *drv = priv;
660 fal_rx_prc_lut_t entry;
661 fal_rx_sc_validate_frame_e vf;
662 enum validate_frames validate_frames = validation;
664 const u8 *sci_addr = sc->sci.addr;
665 u16 sci_port = be_to_host16(sc->sci.port);
667 ret = macsec_qca_get_available_receive_sc(priv, &channel);
671 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
674 os_memset(&entry, 0, sizeof(entry));
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;
682 entry.channel = channel;
683 entry.action = FAL_RX_PRC_ACTION_PROCESS;
684 entry.offset = conf_offset;
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;
692 vf = FAL_RX_SC_VALIDATE_FRAME_DISABLED;
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,
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,
704 macsec_qca_register_receive_channel(drv, sc, channel);
710 static int macsec_qca_delete_receive_sc(void *priv, struct receive_sc *sc)
712 struct macsec_qca_data *drv = priv;
714 fal_rx_prc_lut_t entry;
717 ret = macsec_qca_lookup_receive_channel(priv, sc, &channel);
721 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
724 os_memset(&entry, 0, sizeof(entry));
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);
733 static int macsec_qca_create_receive_sa(void *priv, struct receive_sa *sa)
735 struct macsec_qca_data *drv = priv;
740 fal_rx_prc_lut_t entry;
743 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
747 wpa_printf(MSG_DEBUG, "%s, channel=%d, an=%d, lpn=0x%x",
748 __func__, channel, sa->an, sa->lowest_pn);
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];
764 if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0)
766 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30)
768 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50)
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,
783 static int macsec_qca_enable_receive_sa(void *priv, struct receive_sa *sa)
785 struct macsec_qca_data *drv = priv;
789 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
793 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
796 ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an,
803 static int macsec_qca_disable_receive_sa(void *priv, struct receive_sa *sa)
805 struct macsec_qca_data *drv = priv;
809 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
813 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
816 ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an,
823 static int macsec_qca_get_available_transmit_sc(void *priv, u32 *channel)
825 struct macsec_qca_data *drv = priv;
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,
836 wpa_printf(MSG_DEBUG, "%s: channel=%d",
842 wpa_printf(MSG_DEBUG, "%s: no avaiable channel", __func__);
848 static int macsec_qca_create_transmit_sc(void *priv, struct transmit_sc *sc,
849 unsigned int conf_offset)
851 struct macsec_qca_data *drv = priv;
853 fal_tx_class_lut_t entry;
854 u8 psci[ETH_ALEN + 2];
856 u16 sci_port = be_to_host16(sc->sci.port);
858 ret = macsec_qca_get_available_transmit_sc(priv, &channel);
862 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
865 os_memset(&entry, 0, sizeof(entry));
868 entry.action = FAL_TX_CLASS_ACTION_FORWARD;
869 entry.channel = channel;
871 os_memcpy(psci, sc->sci.addr, ETH_ALEN);
872 psci[6] = (sci_port >> 8) & 0xff;
873 psci[7] = sci_port & 0xff;
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,
883 macsec_qca_register_transmit_channel(drv, sc, channel);
889 static int macsec_qca_delete_transmit_sc(void *priv, struct transmit_sc *sc)
891 struct macsec_qca_data *drv = priv;
893 fal_tx_class_lut_t entry;
896 ret = macsec_qca_lookup_transmit_channel(priv, sc, &channel);
900 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
903 os_memset(&entry, 0, sizeof(entry));
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);
912 static int macsec_qca_create_transmit_sa(void *priv, struct transmit_sa *sa)
914 struct macsec_qca_data *drv = priv;
922 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
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);
930 if (drv->always_include_sci)
932 else if (drv->use_es)
934 else if (drv->use_scb)
937 if (sa->confidentiality)
938 tci |= TCI_E | TCI_C;
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];
954 if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0)
956 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30)
958 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50)
962 ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id,
965 ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an,
967 ret += nss_macsec_secy_tx_sak_set(drv->secy_id, channel, sa->an,
969 ret += nss_macsec_secy_tx_sc_tci_7_2_set(drv->secy_id, channel,
971 ret += nss_macsec_secy_tx_sc_an_set(drv->secy_id, channel, sa->an);
977 static int macsec_qca_enable_transmit_sa(void *priv, struct transmit_sa *sa)
979 struct macsec_qca_data *drv = priv;
983 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
987 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
990 ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
997 static int macsec_qca_disable_transmit_sa(void *priv, struct transmit_sa *sa)
999 struct macsec_qca_data *drv = priv;
1003 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
1007 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
1010 ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
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,
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,