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