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.
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
12 #include <sys/ioctl.h>
16 #include <netpacket/packet.h>
17 #include <net/if_arp.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__) */
25 #include <sys/sockio.h>
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"
34 #include "driver_wired_common.h"
36 #include "nss_macsec_secy.h"
37 #include "nss_macsec_secy_rx.h"
38 #include "nss_macsec_secy_tx.h"
42 #define SAK_128_LEN 16
43 #define SAK_256_LEN 32
45 /* TCI field definition */
61 struct ieee802_1x_mka_sci sci;
64 struct macsec_qca_data {
65 struct driver_wired_common_data common;
70 Boolean always_include_sci;
73 Boolean protect_frames;
74 Boolean replay_protect;
77 struct channel_map receive_channel_map[MAXSC];
78 struct channel_map transmit_channel_map[MAXSC];
82 static void __macsec_drv_init(struct macsec_qca_data *drv)
85 fal_rx_ctl_filt_t rx_ctl_filt;
86 fal_tx_ctl_filt_t tx_ctl_filt;
88 wpa_printf(MSG_INFO, "%s: secy_id=%d", __func__, drv->secy_id);
90 /* Enable Secy and Let EAPoL bypass */
91 ret = nss_macsec_secy_en_set(drv->secy_id, TRUE);
93 wpa_printf(MSG_ERROR, "nss_macsec_secy_en_set: FAIL");
95 ret = nss_macsec_secy_sc_sa_mapping_mode_set(drv->secy_id,
99 "nss_macsec_secy_sc_sa_mapping_mode_set: FAIL");
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);
108 wpa_printf(MSG_ERROR, "nss_macsec_secy_rx_ctl_filt_set: FAIL");
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);
117 wpa_printf(MSG_ERROR, "nss_macsec_secy_tx_ctl_filt_set: FAIL");
121 static void __macsec_drv_deinit(struct macsec_qca_data *drv)
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);
129 static void * macsec_qca_init(void *ctx, const char *ifname)
131 struct macsec_qca_data *drv;
133 drv = os_zalloc(sizeof(*drv));
137 /* Board specific settings */
138 if (os_memcmp("eth2", ifname, 4) == 0)
140 else if (os_memcmp("eth3", ifname, 4) == 0)
145 if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) {
154 static void macsec_qca_deinit(void *priv)
156 struct macsec_qca_data *drv = priv;
158 driver_wired_deinit_common(&drv->common);
163 static int macsec_qca_macsec_init(void *priv, struct macsec_init_params *params)
165 struct macsec_qca_data *drv = priv;
167 drv->always_include_sci = params->always_include_sci;
168 drv->use_es = params->use_es;
169 drv->use_scb = params->use_scb;
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);
175 __macsec_drv_init(drv);
181 static int macsec_qca_macsec_deinit(void *priv)
183 struct macsec_qca_data *drv = priv;
185 wpa_printf(MSG_DEBUG, "%s", __func__);
187 __macsec_drv_deinit(drv);
193 static int macsec_qca_get_capability(void *priv, enum macsec_cap *cap)
195 wpa_printf(MSG_DEBUG, "%s", __func__);
197 *cap = MACSEC_CAP_INTEG_AND_CONF_0_30_50;
203 static int macsec_qca_enable_protect_frames(void *priv, Boolean enabled)
205 struct macsec_qca_data *drv = priv;
208 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
210 drv->protect_frames = enabled;
216 static int macsec_qca_set_replay_protect(void *priv, Boolean enabled,
219 struct macsec_qca_data *drv = priv;
222 wpa_printf(MSG_DEBUG, "%s: enabled=%d, win=%u",
223 __func__, enabled, window);
225 drv->replay_protect = enabled;
226 drv->replay_window = window;
232 static fal_cipher_suite_e macsec_qca_cs_type_get(u64 cs)
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;
242 static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs)
244 struct macsec_qca_data *drv = priv;
245 fal_cipher_suite_e cs_type;
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,
254 wpa_printf(MSG_DEBUG, "%s: CipherSuite: %016" PRIx64, __func__, cs);
256 cs_type = macsec_qca_cs_type_get(cs);
257 return nss_macsec_secy_cipher_suite_set(drv->secy_id, cs_type);
261 static int macsec_qca_enable_controlled_port(void *priv, Boolean enabled)
263 struct macsec_qca_data *drv = priv;
266 wpa_printf(MSG_DEBUG, "%s: enable=%d", __func__, enabled);
268 ret += nss_macsec_secy_controlled_port_en_set(drv->secy_id, enabled);
274 static int macsec_qca_lookup_channel(struct channel_map *map,
275 struct ieee802_1x_mka_sci *sci,
280 for (i = 0; i < MAXSC; i++) {
281 if (os_memcmp(&map[i].sci, sci,
282 sizeof(struct ieee802_1x_mka_sci)) == 0) {
292 static void macsec_qca_register_channel(struct channel_map *map,
293 struct ieee802_1x_mka_sci *sci,
296 os_memcpy(&map[channel].sci, sci, sizeof(struct ieee802_1x_mka_sci));
300 static int macsec_qca_lookup_receive_channel(struct macsec_qca_data *drv,
301 struct receive_sc *sc,
304 return macsec_qca_lookup_channel(drv->receive_channel_map, &sc->sci,
309 static void macsec_qca_register_receive_channel(struct macsec_qca_data *drv,
310 struct receive_sc *sc,
313 macsec_qca_register_channel(drv->receive_channel_map, &sc->sci,
318 static int macsec_qca_lookup_transmit_channel(struct macsec_qca_data *drv,
319 struct transmit_sc *sc,
322 return macsec_qca_lookup_channel(drv->transmit_channel_map, &sc->sci,
327 static void macsec_qca_register_transmit_channel(struct macsec_qca_data *drv,
328 struct transmit_sc *sc,
331 macsec_qca_register_channel(drv->transmit_channel_map, &sc->sci,
336 static int macsec_qca_get_receive_lowest_pn(void *priv, struct receive_sa *sa)
338 struct macsec_qca_data *drv = priv;
341 bool enabled = FALSE;
345 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
349 ret += nss_macsec_secy_rx_sa_next_pn_get(drv->secy_id, channel, sa->an,
351 ret += nss_macsec_secy_rx_sc_replay_protect_get(drv->secy_id, channel,
353 ret += nss_macsec_secy_rx_sc_anti_replay_window_get(drv->secy_id,
357 sa->lowest_pn = (next_pn > win) ? (next_pn - win) : 1;
359 sa->lowest_pn = next_pn;
361 wpa_printf(MSG_DEBUG, "%s: lpn=0x%x", __func__, sa->lowest_pn);
367 static int macsec_qca_get_transmit_next_pn(void *priv, struct transmit_sa *sa)
369 struct macsec_qca_data *drv = priv;
373 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
377 ret += nss_macsec_secy_tx_sa_next_pn_get(drv->secy_id, channel, sa->an,
380 wpa_printf(MSG_DEBUG, "%s: npn=0x%x", __func__, sa->next_pn);
386 static int macsec_qca_set_transmit_next_pn(void *priv, struct transmit_sa *sa)
388 struct macsec_qca_data *drv = priv;
392 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
396 ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an,
399 wpa_printf(MSG_INFO, "%s: npn=0x%x", __func__, sa->next_pn);
405 static int macsec_qca_get_available_receive_sc(void *priv, u32 *channel)
407 struct macsec_qca_data *drv = priv;
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,
420 wpa_printf(MSG_DEBUG, "%s: channel=%d",
426 wpa_printf(MSG_DEBUG, "%s: no available channel", __func__);
432 static int macsec_qca_create_receive_sc(void *priv, struct receive_sc *sc,
433 unsigned int conf_offset,
436 struct macsec_qca_data *drv = priv;
438 fal_rx_prc_lut_t entry;
439 fal_rx_sc_validate_frame_e vf;
440 enum validate_frames validate_frames = validation;
442 const u8 *sci_addr = sc->sci.addr;
443 u16 sci_port = be_to_host16(sc->sci.port);
445 ret = macsec_qca_get_available_receive_sc(priv, &channel);
449 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
452 os_memset(&entry, 0, sizeof(entry));
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;
460 entry.channel = channel;
461 entry.action = FAL_RX_PRC_ACTION_PROCESS;
462 entry.offset = conf_offset;
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;
470 vf = FAL_RX_SC_VALIDATE_FRAME_DISABLED;
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,
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,
482 macsec_qca_register_receive_channel(drv, sc, channel);
488 static int macsec_qca_delete_receive_sc(void *priv, struct receive_sc *sc)
490 struct macsec_qca_data *drv = priv;
492 fal_rx_prc_lut_t entry;
495 ret = macsec_qca_lookup_receive_channel(priv, sc, &channel);
499 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
502 os_memset(&entry, 0, sizeof(entry));
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);
511 static int macsec_qca_create_receive_sa(void *priv, struct receive_sa *sa)
513 struct macsec_qca_data *drv = priv;
518 fal_rx_prc_lut_t entry;
521 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
525 wpa_printf(MSG_DEBUG, "%s, channel=%d, an=%d, lpn=0x%x",
526 __func__, channel, sa->an, sa->lowest_pn);
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];
542 if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0)
544 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30)
546 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50)
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,
561 static int macsec_qca_enable_receive_sa(void *priv, struct receive_sa *sa)
563 struct macsec_qca_data *drv = priv;
567 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
571 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
574 ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an,
581 static int macsec_qca_disable_receive_sa(void *priv, struct receive_sa *sa)
583 struct macsec_qca_data *drv = priv;
587 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
591 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
594 ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an,
601 static int macsec_qca_get_available_transmit_sc(void *priv, u32 *channel)
603 struct macsec_qca_data *drv = priv;
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,
614 wpa_printf(MSG_DEBUG, "%s: channel=%d",
620 wpa_printf(MSG_DEBUG, "%s: no avaiable channel", __func__);
626 static int macsec_qca_create_transmit_sc(void *priv, struct transmit_sc *sc,
627 unsigned int conf_offset)
629 struct macsec_qca_data *drv = priv;
631 fal_tx_class_lut_t entry;
632 u8 psci[ETH_ALEN + 2];
634 u16 sci_port = be_to_host16(sc->sci.port);
636 ret = macsec_qca_get_available_transmit_sc(priv, &channel);
640 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
643 os_memset(&entry, 0, sizeof(entry));
646 entry.action = FAL_TX_CLASS_ACTION_FORWARD;
647 entry.channel = channel;
649 os_memcpy(psci, sc->sci.addr, ETH_ALEN);
650 psci[6] = (sci_port >> 8) & 0xff;
651 psci[7] = sci_port & 0xff;
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,
661 macsec_qca_register_transmit_channel(drv, sc, channel);
667 static int macsec_qca_delete_transmit_sc(void *priv, struct transmit_sc *sc)
669 struct macsec_qca_data *drv = priv;
671 fal_tx_class_lut_t entry;
674 ret = macsec_qca_lookup_transmit_channel(priv, sc, &channel);
678 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
681 os_memset(&entry, 0, sizeof(entry));
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);
690 static int macsec_qca_create_transmit_sa(void *priv, struct transmit_sa *sa)
692 struct macsec_qca_data *drv = priv;
700 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
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);
708 if (drv->always_include_sci)
710 else if (drv->use_es)
712 else if (drv->use_scb)
715 if (sa->confidentiality)
716 tci |= TCI_E | TCI_C;
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];
732 if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0)
734 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30)
736 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50)
740 ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id,
743 ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an,
745 ret += nss_macsec_secy_tx_sak_set(drv->secy_id, channel, sa->an,
747 ret += nss_macsec_secy_tx_sc_tci_7_2_set(drv->secy_id, channel,
749 ret += nss_macsec_secy_tx_sc_an_set(drv->secy_id, channel, sa->an);
755 static int macsec_qca_enable_transmit_sa(void *priv, struct transmit_sa *sa)
757 struct macsec_qca_data *drv = priv;
761 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
765 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
768 ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
775 static int macsec_qca_disable_transmit_sa(void *priv, struct transmit_sa *sa)
777 struct macsec_qca_data *drv = priv;
781 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
785 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
788 ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
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,
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,