Home | History | Annotate | Line # | Download | only in drivers
      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  * 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, int link_id)
    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 available 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