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 bool always_include_sci;
74 bool use_es;
75 bool use_scb;
76 bool protect_frames;
77 bool replay_protect;
78 u32 replay_window;
79
80 struct channel_map receive_channel_map[MAXSC];
81 struct channel_map transmit_channel_map[MAXSC];
82 };
83
84
__macsec_drv_init(struct macsec_qca_data * drv)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
__macsec_drv_deinit(struct macsec_qca_data * drv)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
macsec_qca_handle_data(void * ctx,unsigned char * buf,size_t len)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
macsec_qca_handle_read(int sock,void * eloop_ctx,void * sock_ctx)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
macsec_qca_init_sockets(struct macsec_qca_data * drv,u8 * own_addr)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
macsec_qca_init(void * ctx,const char * ifname)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
macsec_qca_deinit(void * priv)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
macsec_qca_hapd_init(struct hostapd_data * hapd,struct wpa_init_params * params)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
macsec_qca_hapd_deinit(void * priv)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
macsec_qca_send_eapol(void * priv,const u8 * addr,const u8 * data,size_t data_len,int encrypt,const u8 * own_addr,u32 flags)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
macsec_qca_macsec_init(void * priv,struct macsec_init_params * params)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
macsec_qca_macsec_deinit(void * priv)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
macsec_qca_get_capability(void * priv,enum macsec_cap * cap)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
macsec_qca_enable_protect_frames(void * priv,bool enabled)425 static int macsec_qca_enable_protect_frames(void *priv, bool 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
macsec_qca_set_replay_protect(void * priv,bool enabled,unsigned int window)438 static int macsec_qca_set_replay_protect(void *priv, bool 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
macsec_qca_cs_type_get(u64 cs)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
macsec_qca_set_current_cipher_suite(void * priv,u64 cs)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
macsec_qca_enable_controlled_port(void * priv,bool enabled)483 static int macsec_qca_enable_controlled_port(void *priv, bool 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
macsec_qca_lookup_channel(struct channel_map * map,struct ieee802_1x_mka_sci * sci,u32 * channel)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
macsec_qca_register_channel(struct channel_map * map,struct ieee802_1x_mka_sci * sci,u32 channel)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
macsec_qca_lookup_receive_channel(struct macsec_qca_data * drv,struct receive_sc * sc,u32 * channel)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
macsec_qca_register_receive_channel(struct macsec_qca_data * drv,struct receive_sc * sc,u32 channel)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
macsec_qca_lookup_transmit_channel(struct macsec_qca_data * drv,struct transmit_sc * sc,u32 * channel)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
macsec_qca_register_transmit_channel(struct macsec_qca_data * drv,struct transmit_sc * sc,u32 channel)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
macsec_qca_get_receive_lowest_pn(void * priv,struct receive_sa * sa)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
macsec_qca_get_transmit_next_pn(void * priv,struct transmit_sa * sa)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
macsec_qca_set_transmit_next_pn(void * priv,struct transmit_sa * sa)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
macsec_qca_get_available_receive_sc(void * priv,u32 * channel)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
macsec_qca_create_receive_sc(void * priv,struct receive_sc * sc,unsigned int conf_offset,int validation)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
macsec_qca_delete_receive_sc(void * priv,struct receive_sc * sc)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
macsec_qca_create_receive_sa(void * priv,struct receive_sa * sa)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
macsec_qca_enable_receive_sa(void * priv,struct receive_sa * sa)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
macsec_qca_disable_receive_sa(void * priv,struct receive_sa * sa)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
macsec_qca_get_available_transmit_sc(void * priv,u32 * channel)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
macsec_qca_create_transmit_sc(void * priv,struct transmit_sc * sc,unsigned int conf_offset)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
macsec_qca_delete_transmit_sc(void * priv,struct transmit_sc * sc)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
macsec_qca_create_transmit_sa(void * priv,struct transmit_sa * sa)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
macsec_qca_enable_transmit_sa(void * priv,struct transmit_sa * sa)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
macsec_qca_disable_transmit_sa(void * priv,struct transmit_sa * sa)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