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
__macsec_drv_init(struct macsec_qca_data * drv)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
__macsec_drv_deinit(struct macsec_qca_data * drv)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
macsec_qca_init(void * ctx,const char * ifname)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
macsec_qca_deinit(void * priv)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
macsec_qca_macsec_init(void * priv,struct macsec_init_params * params)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
macsec_qca_macsec_deinit(void * priv)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
macsec_qca_get_capability(void * priv,enum macsec_cap * cap)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
macsec_qca_enable_protect_frames(void * priv,Boolean enabled)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
macsec_qca_set_replay_protect(void * priv,Boolean enabled,unsigned int window)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
macsec_qca_cs_type_get(u64 cs)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
macsec_qca_set_current_cipher_suite(void * priv,u64 cs)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
macsec_qca_enable_controlled_port(void * priv,Boolean enabled)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
macsec_qca_lookup_channel(struct channel_map * map,struct ieee802_1x_mka_sci * sci,u32 * channel)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
macsec_qca_register_channel(struct channel_map * map,struct ieee802_1x_mka_sci * sci,u32 channel)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
macsec_qca_lookup_receive_channel(struct macsec_qca_data * drv,struct receive_sc * sc,u32 * channel)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
macsec_qca_register_receive_channel(struct macsec_qca_data * drv,struct receive_sc * sc,u32 channel)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
macsec_qca_lookup_transmit_channel(struct macsec_qca_data * drv,struct transmit_sc * sc,u32 * channel)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
macsec_qca_register_transmit_channel(struct macsec_qca_data * drv,struct transmit_sc * sc,u32 channel)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
macsec_qca_get_receive_lowest_pn(void * priv,struct receive_sa * sa)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
macsec_qca_get_transmit_next_pn(void * priv,struct transmit_sa * sa)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
macsec_qca_set_transmit_next_pn(void * priv,struct transmit_sa * sa)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
macsec_qca_get_available_receive_sc(void * priv,u32 * channel)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
macsec_qca_create_receive_sc(void * priv,struct receive_sc * sc,unsigned int conf_offset,int validation)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
macsec_qca_delete_receive_sc(void * priv,struct receive_sc * sc)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
macsec_qca_create_receive_sa(void * priv,struct receive_sa * sa)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
macsec_qca_enable_receive_sa(void * priv,struct receive_sa * sa)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
macsec_qca_disable_receive_sa(void * priv,struct receive_sa * sa)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
macsec_qca_get_available_transmit_sc(void * priv,u32 * channel)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
macsec_qca_create_transmit_sc(void * priv,struct transmit_sc * sc,unsigned int conf_offset)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
macsec_qca_delete_transmit_sc(void * priv,struct transmit_sc * sc)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
macsec_qca_create_transmit_sa(void * priv,struct transmit_sa * sa)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
macsec_qca_enable_transmit_sa(void * priv,struct transmit_sa * sa)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
macsec_qca_disable_transmit_sa(void * priv,struct transmit_sa * sa)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