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