xref: /freebsd/contrib/wpa/src/drivers/driver_macsec_qca.c (revision cfd6422a5217410fbd66f7a7a8a64d9d85e61229)
1 /*
2  * Wired Ethernet driver interface for QCA MACsec driver
3  * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
4  * Copyright (c) 2004, Gunter Burchardt <tira@isx.de>
5  * Copyright (c) 2013-2014, Qualcomm Atheros, Inc.
6  * Copyright (c) 2019, The Linux Foundation
7  *
8  * This software may be distributed under the terms of the BSD license.
9  * See README for more details.
10  */
11 
12 #include "includes.h"
13 #include <sys/ioctl.h>
14 #include <net/if.h>
15 #include <inttypes.h>
16 #ifdef __linux__
17 #include <netpacket/packet.h>
18 #include <net/if_arp.h>
19 #include <net/if.h>
20 #endif /* __linux__ */
21 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
22 #include <net/if_dl.h>
23 #include <net/if_media.h>
24 #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */
25 #ifdef __sun__
26 #include <sys/sockio.h>
27 #endif /* __sun__ */
28 
29 #include "utils/common.h"
30 #include "utils/eloop.h"
31 #include "common/defs.h"
32 #include "common/ieee802_1x_defs.h"
33 #include "common/eapol_common.h"
34 #include "pae/ieee802_1x_kay.h"
35 #include "driver.h"
36 #include "driver_wired_common.h"
37 
38 #include "nss_macsec_secy.h"
39 #include "nss_macsec_secy_rx.h"
40 #include "nss_macsec_secy_tx.h"
41 
42 #define MAXSC 16
43 
44 #define SAK_128_LEN	16
45 #define SAK_256_LEN	32
46 
47 /* TCI field definition */
48 #define TCI_ES                0x40
49 #define TCI_SC                0x20
50 #define TCI_SCB               0x10
51 #define TCI_E                 0x08
52 #define TCI_C                 0x04
53 
54 #ifdef _MSC_VER
55 #pragma pack(push, 1)
56 #endif /* _MSC_VER */
57 
58 #ifdef _MSC_VER
59 #pragma pack(pop)
60 #endif /* _MSC_VER */
61 
62 struct channel_map {
63 	struct ieee802_1x_mka_sci sci;
64 };
65 
66 struct macsec_qca_data {
67 	struct driver_wired_common_data common;
68 
69 	int use_pae_group_addr;
70 	u32 secy_id;
71 
72 	/* shadow */
73 	Boolean always_include_sci;
74 	Boolean use_es;
75 	Boolean use_scb;
76 	Boolean protect_frames;
77 	Boolean 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 void * macsec_qca_init(void *ctx, const char *ifname)
261 {
262 	struct macsec_qca_data *drv;
263 
264 	drv = os_zalloc(sizeof(*drv));
265 	if (drv == NULL)
266 		return NULL;
267 
268 	/* Board specific settings */
269 	if (os_memcmp("eth2", ifname, 4) == 0)
270 		drv->secy_id = 1;
271 	else if (os_memcmp("eth3", ifname, 4) == 0)
272 		drv->secy_id = 2;
273 	else
274 		drv->secy_id = -1;
275 
276 	if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) {
277 		os_free(drv);
278 		return NULL;
279 	}
280 
281 	return drv;
282 }
283 
284 
285 static void macsec_qca_deinit(void *priv)
286 {
287 	struct macsec_qca_data *drv = priv;
288 
289 	driver_wired_deinit_common(&drv->common);
290 	os_free(drv);
291 }
292 
293 
294 static void * macsec_qca_hapd_init(struct hostapd_data *hapd,
295 				   struct wpa_init_params *params)
296 {
297 	struct macsec_qca_data *drv;
298 
299 	drv = os_zalloc(sizeof(struct macsec_qca_data));
300 	if (!drv) {
301 		wpa_printf(MSG_INFO,
302 			   "Could not allocate memory for macsec_qca driver data");
303 		return NULL;
304 	}
305 
306 	/* Board specific settings */
307 	if (os_memcmp("eth2", params->ifname, 4) == 0)
308 		drv->secy_id = 1;
309 	else if (os_memcmp("eth3", params->ifname, 4) == 0)
310 		drv->secy_id = 2;
311 	else if (os_memcmp("eth4", params->ifname, 4) == 0)
312 		drv->secy_id = 0;
313 	else if (os_memcmp("eth5", params->ifname, 4) == 0)
314 		drv->secy_id = 1;
315 	else
316 		drv->secy_id = -1;
317 
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;
322 
323 	if (macsec_qca_init_sockets(drv, params->own_addr)) {
324 		os_free(drv);
325 		return NULL;
326 	}
327 
328 	return drv;
329 }
330 
331 
332 static void macsec_qca_hapd_deinit(void *priv)
333 {
334 	struct macsec_qca_data *drv = priv;
335 
336 	if (drv->common.sock >= 0) {
337 		eloop_unregister_read_sock(drv->common.sock);
338 		close(drv->common.sock);
339 	}
340 
341 	os_free(drv);
342 }
343 
344 
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)
348 {
349 	struct macsec_qca_data *drv = priv;
350 	struct ieee8023_hdr *hdr;
351 	size_t len;
352 	u8 *pos;
353 	int res;
354 
355 	len = sizeof(*hdr) + data_len;
356 	hdr = os_zalloc(len);
357 	if (!hdr) {
358 		wpa_printf(MSG_INFO,
359 			   "malloc() failed for macsec_qca_send_eapol(len=%lu)",
360 			   (unsigned long) len);
361 		return -1;
362 	}
363 
364 	os_memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr,
365 		  ETH_ALEN);
366 	os_memcpy(hdr->src, own_addr, ETH_ALEN);
367 	hdr->ethertype = htons(ETH_P_PAE);
368 
369 	pos = (u8 *) (hdr + 1);
370 	os_memcpy(pos, data, data_len);
371 
372 	res = send(drv->common.sock, (u8 *) hdr, len, 0);
373 	os_free(hdr);
374 
375 	if (res < 0) {
376 		wpa_printf(MSG_ERROR,
377 			   "macsec_qca_send_eapol - packet len: %lu - failed: send: %s",
378 			   (unsigned long) len, strerror(errno));
379 	}
380 
381 	return res;
382 }
383 
384 
385 static int macsec_qca_macsec_init(void *priv, struct macsec_init_params *params)
386 {
387 	struct macsec_qca_data *drv = priv;
388 
389 	drv->always_include_sci = params->always_include_sci;
390 	drv->use_es = params->use_es;
391 	drv->use_scb = params->use_scb;
392 
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);
396 
397 	__macsec_drv_init(drv);
398 
399 	return 0;
400 }
401 
402 
403 static int macsec_qca_macsec_deinit(void *priv)
404 {
405 	struct macsec_qca_data *drv = priv;
406 
407 	wpa_printf(MSG_DEBUG, "%s", __func__);
408 
409 	__macsec_drv_deinit(drv);
410 
411 	return 0;
412 }
413 
414 
415 static int macsec_qca_get_capability(void *priv, enum macsec_cap *cap)
416 {
417 	wpa_printf(MSG_DEBUG, "%s", __func__);
418 
419 	*cap = MACSEC_CAP_INTEG_AND_CONF_0_30_50;
420 
421 	return 0;
422 }
423 
424 
425 static int macsec_qca_enable_protect_frames(void *priv, Boolean enabled)
426 {
427 	struct macsec_qca_data *drv = priv;
428 	int ret = 0;
429 
430 	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
431 
432 	drv->protect_frames = enabled;
433 
434 	return ret;
435 }
436 
437 
438 static int macsec_qca_set_replay_protect(void *priv, Boolean enabled,
439 					 unsigned int window)
440 {
441 	struct macsec_qca_data *drv = priv;
442 	int ret = 0;
443 
444 	wpa_printf(MSG_DEBUG, "%s: enabled=%d, win=%u",
445 		   __func__, enabled, window);
446 
447 	drv->replay_protect = enabled;
448 	drv->replay_window = window;
449 
450 	return ret;
451 }
452 
453 
454 static fal_cipher_suite_e macsec_qca_cs_type_get(u64 cs)
455 {
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;
461 }
462 
463 
464 static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs)
465 {
466 	struct macsec_qca_data *drv = priv;
467 	fal_cipher_suite_e cs_type;
468 
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,
472 			   __func__, cs);
473 		return -1;
474 	}
475 
476 	wpa_printf(MSG_DEBUG, "%s: CipherSuite: %016" PRIx64, __func__, cs);
477 
478 	cs_type = macsec_qca_cs_type_get(cs);
479 	return nss_macsec_secy_cipher_suite_set(drv->secy_id, cs_type);
480 }
481 
482 
483 static int macsec_qca_enable_controlled_port(void *priv, Boolean enabled)
484 {
485 	struct macsec_qca_data *drv = priv;
486 	int ret = 0;
487 
488 	wpa_printf(MSG_DEBUG, "%s: enable=%d", __func__, enabled);
489 
490 	ret += nss_macsec_secy_controlled_port_en_set(drv->secy_id, enabled);
491 
492 	return ret;
493 }
494 
495 
496 static int macsec_qca_lookup_channel(struct channel_map *map,
497 				     struct ieee802_1x_mka_sci *sci,
498 				     u32 *channel)
499 {
500 	u32 i;
501 
502 	for (i = 0; i < MAXSC; i++) {
503 		if (os_memcmp(&map[i].sci, sci,
504 			      sizeof(struct ieee802_1x_mka_sci)) == 0) {
505 			*channel = i;
506 			return 0;
507 		}
508 	}
509 
510 	return -1;
511 }
512 
513 
514 static void macsec_qca_register_channel(struct channel_map *map,
515 					struct ieee802_1x_mka_sci *sci,
516 					u32 channel)
517 {
518 	os_memcpy(&map[channel].sci, sci, sizeof(struct ieee802_1x_mka_sci));
519 }
520 
521 
522 static int macsec_qca_lookup_receive_channel(struct macsec_qca_data *drv,
523 					     struct receive_sc *sc,
524 					     u32 *channel)
525 {
526 	return macsec_qca_lookup_channel(drv->receive_channel_map, &sc->sci,
527 					 channel);
528 }
529 
530 
531 static void macsec_qca_register_receive_channel(struct macsec_qca_data *drv,
532 						struct receive_sc *sc,
533 						u32 channel)
534 {
535 	macsec_qca_register_channel(drv->receive_channel_map, &sc->sci,
536 				    channel);
537 }
538 
539 
540 static int macsec_qca_lookup_transmit_channel(struct macsec_qca_data *drv,
541 					      struct transmit_sc *sc,
542 					      u32 *channel)
543 {
544 	return macsec_qca_lookup_channel(drv->transmit_channel_map, &sc->sci,
545 					 channel);
546 }
547 
548 
549 static void macsec_qca_register_transmit_channel(struct macsec_qca_data *drv,
550 						 struct transmit_sc *sc,
551 						 u32 channel)
552 {
553 	macsec_qca_register_channel(drv->transmit_channel_map, &sc->sci,
554 				    channel);
555 }
556 
557 
558 static int macsec_qca_get_receive_lowest_pn(void *priv, struct receive_sa *sa)
559 {
560 	struct macsec_qca_data *drv = priv;
561 	int ret = 0;
562 	u32 next_pn = 0;
563 	bool enabled = FALSE;
564 	u32 win;
565 	u32 channel;
566 
567 	ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
568 	if (ret != 0)
569 		return ret;
570 
571 	ret += nss_macsec_secy_rx_sa_next_pn_get(drv->secy_id, channel, sa->an,
572 						 &next_pn);
573 	ret += nss_macsec_secy_rx_sc_replay_protect_get(drv->secy_id, channel,
574 							&enabled);
575 	ret += nss_macsec_secy_rx_sc_anti_replay_window_get(drv->secy_id,
576 							    channel, &win);
577 
578 	if (enabled)
579 		sa->lowest_pn = (next_pn > win) ? (next_pn - win) : 1;
580 	else
581 		sa->lowest_pn = next_pn;
582 
583 	wpa_printf(MSG_DEBUG, "%s: lpn=0x%x", __func__, sa->lowest_pn);
584 
585 	return ret;
586 }
587 
588 
589 static int macsec_qca_get_transmit_next_pn(void *priv, struct transmit_sa *sa)
590 {
591 	struct macsec_qca_data *drv = priv;
592 	int ret = 0;
593 	u32 channel;
594 
595 	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
596 	if (ret != 0)
597 		return ret;
598 
599 	ret += nss_macsec_secy_tx_sa_next_pn_get(drv->secy_id, channel, sa->an,
600 						 &sa->next_pn);
601 
602 	wpa_printf(MSG_DEBUG, "%s: npn=0x%x", __func__, sa->next_pn);
603 
604 	return ret;
605 }
606 
607 
608 static int macsec_qca_set_transmit_next_pn(void *priv, struct transmit_sa *sa)
609 {
610 	struct macsec_qca_data *drv = priv;
611 	int ret = 0;
612 	u32 channel;
613 
614 	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
615 	if (ret != 0)
616 		return ret;
617 
618 	ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an,
619 						 sa->next_pn);
620 
621 	wpa_printf(MSG_INFO, "%s: npn=0x%x", __func__, sa->next_pn);
622 
623 	return ret;
624 }
625 
626 
627 static int macsec_qca_get_available_receive_sc(void *priv, u32 *channel)
628 {
629 	struct macsec_qca_data *drv = priv;
630 	int ret = 0;
631 	u32 sc_ch = 0;
632 	bool in_use = FALSE;
633 
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,
636 							&in_use);
637 		if (ret)
638 			continue;
639 
640 		if (!in_use) {
641 			*channel = sc_ch;
642 			wpa_printf(MSG_DEBUG, "%s: channel=%d",
643 				   __func__, *channel);
644 			return 0;
645 		}
646 	}
647 
648 	wpa_printf(MSG_DEBUG, "%s: no available channel", __func__);
649 
650 	return -1;
651 }
652 
653 
654 static int macsec_qca_create_receive_sc(void *priv, struct receive_sc *sc,
655 					unsigned int conf_offset,
656 					int validation)
657 {
658 	struct macsec_qca_data *drv = priv;
659 	int ret = 0;
660 	fal_rx_prc_lut_t entry;
661 	fal_rx_sc_validate_frame_e vf;
662 	enum validate_frames validate_frames = validation;
663 	u32 channel;
664 	const u8 *sci_addr = sc->sci.addr;
665 	u16 sci_port = be_to_host16(sc->sci.port);
666 
667 	ret = macsec_qca_get_available_receive_sc(priv, &channel);
668 	if (ret != 0)
669 		return ret;
670 
671 	wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
672 
673 	/* rx prc lut */
674 	os_memset(&entry, 0, sizeof(entry));
675 
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;
680 
681 	entry.valid = 1;
682 	entry.channel = channel;
683 	entry.action = FAL_RX_PRC_ACTION_PROCESS;
684 	entry.offset = conf_offset;
685 
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;
691 	else
692 		vf = FAL_RX_SC_VALIDATE_FRAME_DISABLED;
693 
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,
697 							vf);
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,
701 							    channel,
702 							    drv->replay_window);
703 
704 	macsec_qca_register_receive_channel(drv, sc, channel);
705 
706 	return ret;
707 }
708 
709 
710 static int macsec_qca_delete_receive_sc(void *priv, struct receive_sc *sc)
711 {
712 	struct macsec_qca_data *drv = priv;
713 	int ret;
714 	fal_rx_prc_lut_t entry;
715 	u32 channel;
716 
717 	ret = macsec_qca_lookup_receive_channel(priv, sc, &channel);
718 	if (ret != 0)
719 		return ret;
720 
721 	wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
722 
723 	/* rx prc lut */
724 	os_memset(&entry, 0, sizeof(entry));
725 
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);
728 
729 	return ret;
730 }
731 
732 
733 static int macsec_qca_create_receive_sa(void *priv, struct receive_sa *sa)
734 {
735 	struct macsec_qca_data *drv = priv;
736 	int ret;
737 	fal_rx_sak_t rx_sak;
738 	int i = 0;
739 	u32 channel;
740 	fal_rx_prc_lut_t entry;
741 	u32 offset;
742 
743 	ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
744 	if (ret != 0)
745 		return ret;
746 
747 	wpa_printf(MSG_DEBUG, "%s, channel=%d, an=%d, lpn=0x%x",
748 		   __func__, channel, sa->an, sa->lowest_pn);
749 
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];
759 		}
760 	} else {
761 		return -1;
762 	}
763 
764 	if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0)
765 		offset = 0;
766 	else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30)
767 		offset = 30;
768 	else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50)
769 		offset = 50;
770 	else
771 		return -1;
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,
777 					  &rx_sak);
778 
779 	return ret;
780 }
781 
782 
783 static int macsec_qca_enable_receive_sa(void *priv, struct receive_sa *sa)
784 {
785 	struct macsec_qca_data *drv = priv;
786 	int ret;
787 	u32 channel;
788 
789 	ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
790 	if (ret != 0)
791 		return ret;
792 
793 	wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
794 		   sa->an);
795 
796 	ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an,
797 					    TRUE);
798 
799 	return ret;
800 }
801 
802 
803 static int macsec_qca_disable_receive_sa(void *priv, struct receive_sa *sa)
804 {
805 	struct macsec_qca_data *drv = priv;
806 	int ret;
807 	u32 channel;
808 
809 	ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
810 	if (ret != 0)
811 		return ret;
812 
813 	wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
814 		   sa->an);
815 
816 	ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an,
817 					    FALSE);
818 
819 	return ret;
820 }
821 
822 
823 static int macsec_qca_get_available_transmit_sc(void *priv, u32 *channel)
824 {
825 	struct macsec_qca_data *drv = priv;
826 	u32 sc_ch = 0;
827 	bool in_use = FALSE;
828 
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,
831 						      &in_use))
832 			continue;
833 
834 		if (!in_use) {
835 			*channel = sc_ch;
836 			wpa_printf(MSG_DEBUG, "%s: channel=%d",
837 				   __func__, *channel);
838 			return 0;
839 		}
840 	}
841 
842 	wpa_printf(MSG_DEBUG, "%s: no avaiable channel", __func__);
843 
844 	return -1;
845 }
846 
847 
848 static int macsec_qca_create_transmit_sc(void *priv, struct transmit_sc *sc,
849 					 unsigned int conf_offset)
850 {
851 	struct macsec_qca_data *drv = priv;
852 	int ret;
853 	fal_tx_class_lut_t entry;
854 	u8 psci[ETH_ALEN + 2];
855 	u32 channel;
856 	u16 sci_port = be_to_host16(sc->sci.port);
857 
858 	ret = macsec_qca_get_available_transmit_sc(priv, &channel);
859 	if (ret != 0)
860 		return ret;
861 
862 	wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
863 
864 	/* class lut */
865 	os_memset(&entry, 0, sizeof(entry));
866 
867 	entry.valid = 1;
868 	entry.action = FAL_TX_CLASS_ACTION_FORWARD;
869 	entry.channel = channel;
870 
871 	os_memcpy(psci, sc->sci.addr, ETH_ALEN);
872 	psci[6] = (sci_port >> 8) & 0xff;
873 	psci[7] = sci_port & 0xff;
874 
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,
880 								channel,
881 								conf_offset);
882 
883 	macsec_qca_register_transmit_channel(drv, sc, channel);
884 
885 	return ret;
886 }
887 
888 
889 static int macsec_qca_delete_transmit_sc(void *priv, struct transmit_sc *sc)
890 {
891 	struct macsec_qca_data *drv = priv;
892 	int ret;
893 	fal_tx_class_lut_t entry;
894 	u32 channel;
895 
896 	ret = macsec_qca_lookup_transmit_channel(priv, sc, &channel);
897 	if (ret != 0)
898 		return ret;
899 
900 	wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
901 
902 	/* class lut */
903 	os_memset(&entry, 0, sizeof(entry));
904 
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);
907 
908 	return ret;
909 }
910 
911 
912 static int macsec_qca_create_transmit_sa(void *priv, struct transmit_sa *sa)
913 {
914 	struct macsec_qca_data *drv = priv;
915 	int ret;
916 	u8 tci = 0;
917 	fal_tx_sak_t tx_sak;
918 	int i;
919 	u32 channel;
920 	u32 offset;
921 
922 	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
923 	if (ret != 0)
924 		return ret;
925 
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);
929 
930 	if (drv->always_include_sci)
931 		tci |= TCI_SC;
932 	else if (drv->use_es)
933 		tci |= TCI_ES;
934 	else if (drv->use_scb)
935 		tci |= TCI_SCB;
936 
937 	if (sa->confidentiality)
938 		tci |= TCI_E | TCI_C;
939 
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];
949 		}
950 	} else {
951 		return -1;
952 	}
953 
954 	if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0)
955 		offset = 0;
956 	else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30)
957 		offset = 30;
958 	else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50)
959 		offset = 50;
960 	else
961 		return -1;
962 	ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id,
963 								channel,
964 								offset);
965 	ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an,
966 						 sa->next_pn);
967 	ret += nss_macsec_secy_tx_sak_set(drv->secy_id, channel, sa->an,
968 					  &tx_sak);
969 	ret += nss_macsec_secy_tx_sc_tci_7_2_set(drv->secy_id, channel,
970 						 (tci >> 2));
971 	ret += nss_macsec_secy_tx_sc_an_set(drv->secy_id, channel, sa->an);
972 
973 	return ret;
974 }
975 
976 
977 static int macsec_qca_enable_transmit_sa(void *priv, struct transmit_sa *sa)
978 {
979 	struct macsec_qca_data *drv = priv;
980 	int ret;
981 	u32 channel;
982 
983 	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
984 	if (ret != 0)
985 		return ret;
986 
987 	wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
988 		   sa->an);
989 
990 	ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
991 					    TRUE);
992 
993 	return ret;
994 }
995 
996 
997 static int macsec_qca_disable_transmit_sa(void *priv, struct transmit_sa *sa)
998 {
999 	struct macsec_qca_data *drv = priv;
1000 	int ret;
1001 	u32 channel;
1002 
1003 	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
1004 	if (ret != 0)
1005 		return ret;
1006 
1007 	wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
1008 		   sa->an);
1009 
1010 	ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
1011 					    FALSE);
1012 
1013 	return ret;
1014 }
1015 
1016 
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,
1028 
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,
1049 };
1050