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_secy_id_get(const char * ifname,u32 * secy_id)260 static int macsec_qca_secy_id_get(const char *ifname, u32 *secy_id)
261 {
262 #ifdef NSS_MACSEC_SECY_ID_GET_FUNC
263 /* Get secy id from nss macsec driver */
264 return nss_macsec_secy_id_get((u8 *) ifname, secy_id);
265 #else /* NSS_MACSEC_SECY_ID_GET_FUNC */
266 /* Board specific settings */
267 if (os_strcmp(ifname, "eth2") == 0) {
268 *secy_id = 1;
269 } else if (os_strcmp(ifname, "eth3") == 0) {
270 *secy_id = 2;
271 } else if (os_strcmp(ifname, "eth4") == 0 ||
272 os_strcmp(ifname, "eth0") == 0) {
273 *secy_id = 0;
274 } else if (os_strcmp(ifname, "eth5") == 0 ||
275 os_strcmp(ifname, "eth1") == 0) {
276 *secy_id = 1;
277 } else {
278 *secy_id = -1;
279 return -1;
280 }
281
282 return 0;
283 #endif /* NSS_MACSEC_SECY_ID_GET_FUNC */
284 }
285
286
macsec_qca_init(void * ctx,const char * ifname)287 static void * macsec_qca_init(void *ctx, const char *ifname)
288 {
289 struct macsec_qca_data *drv;
290
291 drv = os_zalloc(sizeof(*drv));
292 if (drv == NULL)
293 return NULL;
294
295 if (macsec_qca_secy_id_get(ifname, &drv->secy_id)) {
296 wpa_printf(MSG_ERROR,
297 "macsec_qca: Failed to get secy_id for %s", ifname);
298 os_free(drv);
299 return NULL;
300 }
301
302 if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) {
303 os_free(drv);
304 return NULL;
305 }
306
307 return drv;
308 }
309
310
macsec_qca_deinit(void * priv)311 static void macsec_qca_deinit(void *priv)
312 {
313 struct macsec_qca_data *drv = priv;
314
315 driver_wired_deinit_common(&drv->common);
316 os_free(drv);
317 }
318
319
macsec_qca_hapd_init(struct hostapd_data * hapd,struct wpa_init_params * params)320 static void * macsec_qca_hapd_init(struct hostapd_data *hapd,
321 struct wpa_init_params *params)
322 {
323 struct macsec_qca_data *drv;
324
325 drv = os_zalloc(sizeof(struct macsec_qca_data));
326 if (!drv) {
327 wpa_printf(MSG_INFO,
328 "Could not allocate memory for macsec_qca driver data");
329 return NULL;
330 }
331
332 if (macsec_qca_secy_id_get(params->ifname, &drv->secy_id)) {
333 wpa_printf(MSG_ERROR,
334 "macsec_qca: Failed to get secy_id for %s",
335 params->ifname);
336 os_free(drv);
337 return NULL;
338 }
339
340 drv->common.ctx = hapd;
341 os_strlcpy(drv->common.ifname, params->ifname,
342 sizeof(drv->common.ifname));
343 drv->use_pae_group_addr = params->use_pae_group_addr;
344
345 if (macsec_qca_init_sockets(drv, params->own_addr)) {
346 os_free(drv);
347 return NULL;
348 }
349
350 return drv;
351 }
352
353
macsec_qca_hapd_deinit(void * priv)354 static void macsec_qca_hapd_deinit(void *priv)
355 {
356 struct macsec_qca_data *drv = priv;
357
358 if (drv->common.sock >= 0) {
359 eloop_unregister_read_sock(drv->common.sock);
360 close(drv->common.sock);
361 }
362
363 os_free(drv);
364 }
365
366
macsec_qca_send_eapol(void * priv,const u8 * addr,const u8 * data,size_t data_len,int encrypt,const u8 * own_addr,u32 flags,int link_id)367 static int macsec_qca_send_eapol(void *priv, const u8 *addr,
368 const u8 *data, size_t data_len, int encrypt,
369 const u8 *own_addr, u32 flags, int link_id)
370 {
371 struct macsec_qca_data *drv = priv;
372 struct ieee8023_hdr *hdr;
373 size_t len;
374 u8 *pos;
375 int res;
376
377 len = sizeof(*hdr) + data_len;
378 hdr = os_zalloc(len);
379 if (!hdr) {
380 wpa_printf(MSG_INFO,
381 "malloc() failed for macsec_qca_send_eapol(len=%lu)",
382 (unsigned long) len);
383 return -1;
384 }
385
386 os_memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr,
387 ETH_ALEN);
388 os_memcpy(hdr->src, own_addr, ETH_ALEN);
389 hdr->ethertype = htons(ETH_P_PAE);
390
391 pos = (u8 *) (hdr + 1);
392 os_memcpy(pos, data, data_len);
393
394 res = send(drv->common.sock, (u8 *) hdr, len, 0);
395 os_free(hdr);
396
397 if (res < 0) {
398 wpa_printf(MSG_ERROR,
399 "macsec_qca_send_eapol - packet len: %lu - failed: send: %s",
400 (unsigned long) len, strerror(errno));
401 }
402
403 return res;
404 }
405
406
macsec_qca_macsec_init(void * priv,struct macsec_init_params * params)407 static int macsec_qca_macsec_init(void *priv, struct macsec_init_params *params)
408 {
409 struct macsec_qca_data *drv = priv;
410
411 drv->always_include_sci = params->always_include_sci;
412 drv->use_es = params->use_es;
413 drv->use_scb = params->use_scb;
414
415 wpa_printf(MSG_DEBUG, "%s: es=%d, scb=%d, sci=%d",
416 __func__, drv->use_es, drv->use_scb,
417 drv->always_include_sci);
418
419 __macsec_drv_init(drv);
420
421 return 0;
422 }
423
424
macsec_qca_macsec_deinit(void * priv)425 static int macsec_qca_macsec_deinit(void *priv)
426 {
427 struct macsec_qca_data *drv = priv;
428
429 wpa_printf(MSG_DEBUG, "%s", __func__);
430
431 __macsec_drv_deinit(drv);
432
433 return 0;
434 }
435
436
macsec_qca_get_capability(void * priv,enum macsec_cap * cap)437 static int macsec_qca_get_capability(void *priv, enum macsec_cap *cap)
438 {
439 wpa_printf(MSG_DEBUG, "%s", __func__);
440
441 *cap = MACSEC_CAP_INTEG_AND_CONF_0_30_50;
442
443 return 0;
444 }
445
446
macsec_qca_enable_protect_frames(void * priv,bool enabled)447 static int macsec_qca_enable_protect_frames(void *priv, bool enabled)
448 {
449 struct macsec_qca_data *drv = priv;
450 int ret = 0;
451
452 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
453
454 drv->protect_frames = enabled;
455
456 return ret;
457 }
458
459
macsec_qca_set_replay_protect(void * priv,bool enabled,unsigned int window)460 static int macsec_qca_set_replay_protect(void *priv, bool enabled,
461 unsigned int window)
462 {
463 struct macsec_qca_data *drv = priv;
464 int ret = 0;
465
466 wpa_printf(MSG_DEBUG, "%s: enabled=%d, win=%u",
467 __func__, enabled, window);
468
469 drv->replay_protect = enabled;
470 drv->replay_window = window;
471
472 return ret;
473 }
474
475
macsec_qca_cs_type_get(u64 cs)476 static fal_cipher_suite_e macsec_qca_cs_type_get(u64 cs)
477 {
478 if (cs == CS_ID_GCM_AES_128)
479 return FAL_CIPHER_SUITE_AES_GCM_128;
480 if (cs == CS_ID_GCM_AES_256)
481 return FAL_CIPHER_SUITE_AES_GCM_256;
482 return FAL_CIPHER_SUITE_MAX;
483 }
484
485
macsec_qca_set_current_cipher_suite(void * priv,u64 cs)486 static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs)
487 {
488 struct macsec_qca_data *drv = priv;
489 fal_cipher_suite_e cs_type;
490
491 if (cs != CS_ID_GCM_AES_128 && cs != CS_ID_GCM_AES_256) {
492 wpa_printf(MSG_ERROR,
493 "%s: NOT supported CipherSuite: %016" PRIx64,
494 __func__, cs);
495 return -1;
496 }
497
498 wpa_printf(MSG_DEBUG, "%s: CipherSuite: %016" PRIx64, __func__, cs);
499
500 cs_type = macsec_qca_cs_type_get(cs);
501 return nss_macsec_secy_cipher_suite_set(drv->secy_id, cs_type);
502 }
503
504
macsec_qca_enable_controlled_port(void * priv,bool enabled)505 static int macsec_qca_enable_controlled_port(void *priv, bool enabled)
506 {
507 struct macsec_qca_data *drv = priv;
508 int ret = 0;
509
510 wpa_printf(MSG_DEBUG, "%s: enable=%d", __func__, enabled);
511
512 ret += nss_macsec_secy_controlled_port_en_set(drv->secy_id, enabled);
513
514 return ret;
515 }
516
517
macsec_qca_lookup_channel(struct channel_map * map,struct ieee802_1x_mka_sci * sci,u32 * channel)518 static int macsec_qca_lookup_channel(struct channel_map *map,
519 struct ieee802_1x_mka_sci *sci,
520 u32 *channel)
521 {
522 u32 i;
523
524 for (i = 0; i < MAXSC; i++) {
525 if (os_memcmp(&map[i].sci, sci,
526 sizeof(struct ieee802_1x_mka_sci)) == 0) {
527 *channel = i;
528 return 0;
529 }
530 }
531
532 return -1;
533 }
534
535
macsec_qca_register_channel(struct channel_map * map,struct ieee802_1x_mka_sci * sci,u32 channel)536 static void macsec_qca_register_channel(struct channel_map *map,
537 struct ieee802_1x_mka_sci *sci,
538 u32 channel)
539 {
540 os_memcpy(&map[channel].sci, sci, sizeof(struct ieee802_1x_mka_sci));
541 }
542
543
macsec_qca_lookup_receive_channel(struct macsec_qca_data * drv,struct receive_sc * sc,u32 * channel)544 static int macsec_qca_lookup_receive_channel(struct macsec_qca_data *drv,
545 struct receive_sc *sc,
546 u32 *channel)
547 {
548 return macsec_qca_lookup_channel(drv->receive_channel_map, &sc->sci,
549 channel);
550 }
551
552
macsec_qca_register_receive_channel(struct macsec_qca_data * drv,struct receive_sc * sc,u32 channel)553 static void macsec_qca_register_receive_channel(struct macsec_qca_data *drv,
554 struct receive_sc *sc,
555 u32 channel)
556 {
557 macsec_qca_register_channel(drv->receive_channel_map, &sc->sci,
558 channel);
559 }
560
561
macsec_qca_lookup_transmit_channel(struct macsec_qca_data * drv,struct transmit_sc * sc,u32 * channel)562 static int macsec_qca_lookup_transmit_channel(struct macsec_qca_data *drv,
563 struct transmit_sc *sc,
564 u32 *channel)
565 {
566 return macsec_qca_lookup_channel(drv->transmit_channel_map, &sc->sci,
567 channel);
568 }
569
570
macsec_qca_register_transmit_channel(struct macsec_qca_data * drv,struct transmit_sc * sc,u32 channel)571 static void macsec_qca_register_transmit_channel(struct macsec_qca_data *drv,
572 struct transmit_sc *sc,
573 u32 channel)
574 {
575 macsec_qca_register_channel(drv->transmit_channel_map, &sc->sci,
576 channel);
577 }
578
579
macsec_qca_get_receive_lowest_pn(void * priv,struct receive_sa * sa)580 static int macsec_qca_get_receive_lowest_pn(void *priv, struct receive_sa *sa)
581 {
582 struct macsec_qca_data *drv = priv;
583 int ret = 0;
584 u32 next_pn = 0;
585 bool enabled = false;
586 u32 win;
587 u32 channel;
588
589 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
590 if (ret != 0)
591 return ret;
592
593 ret += nss_macsec_secy_rx_sa_next_pn_get(drv->secy_id, channel, sa->an,
594 &next_pn);
595 ret += nss_macsec_secy_rx_sc_replay_protect_get(drv->secy_id, channel,
596 &enabled);
597 ret += nss_macsec_secy_rx_sc_anti_replay_window_get(drv->secy_id,
598 channel, &win);
599
600 if (enabled)
601 sa->lowest_pn = (next_pn > win) ? (next_pn - win) : 1;
602 else
603 sa->lowest_pn = next_pn;
604
605 wpa_printf(MSG_DEBUG, "%s: lpn=0x%x", __func__, sa->lowest_pn);
606
607 return ret;
608 }
609
610
macsec_qca_get_transmit_next_pn(void * priv,struct transmit_sa * sa)611 static int macsec_qca_get_transmit_next_pn(void *priv, struct transmit_sa *sa)
612 {
613 struct macsec_qca_data *drv = priv;
614 int ret = 0;
615 u32 channel;
616
617 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
618 if (ret != 0)
619 return ret;
620
621 ret += nss_macsec_secy_tx_sa_next_pn_get(drv->secy_id, channel, sa->an,
622 &sa->next_pn);
623
624 wpa_printf(MSG_DEBUG, "%s: npn=0x%x", __func__, sa->next_pn);
625
626 return ret;
627 }
628
629
macsec_qca_set_transmit_next_pn(void * priv,struct transmit_sa * sa)630 static int macsec_qca_set_transmit_next_pn(void *priv, struct transmit_sa *sa)
631 {
632 struct macsec_qca_data *drv = priv;
633 int ret = 0;
634 u32 channel;
635
636 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
637 if (ret != 0)
638 return ret;
639
640 ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an,
641 sa->next_pn);
642
643 wpa_printf(MSG_INFO, "%s: npn=0x%x", __func__, sa->next_pn);
644
645 return ret;
646 }
647
648
macsec_qca_get_available_receive_sc(void * priv,u32 * channel)649 static int macsec_qca_get_available_receive_sc(void *priv, u32 *channel)
650 {
651 struct macsec_qca_data *drv = priv;
652 int ret = 0;
653 u32 sc_ch = 0;
654 bool in_use = false;
655
656 for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) {
657 ret = nss_macsec_secy_rx_sc_in_used_get(drv->secy_id, sc_ch,
658 &in_use);
659 if (ret)
660 continue;
661
662 if (!in_use) {
663 *channel = sc_ch;
664 wpa_printf(MSG_DEBUG, "%s: channel=%d",
665 __func__, *channel);
666 return 0;
667 }
668 }
669
670 wpa_printf(MSG_DEBUG, "%s: no available channel", __func__);
671
672 return -1;
673 }
674
675
macsec_qca_create_receive_sc(void * priv,struct receive_sc * sc,unsigned int conf_offset,int validation)676 static int macsec_qca_create_receive_sc(void *priv, struct receive_sc *sc,
677 unsigned int conf_offset,
678 int validation)
679 {
680 struct macsec_qca_data *drv = priv;
681 int ret = 0;
682 fal_rx_prc_lut_t entry;
683 fal_rx_sc_validate_frame_e vf;
684 enum validate_frames validate_frames = validation;
685 u32 channel;
686 const u8 *sci_addr = sc->sci.addr;
687 u16 sci_port = be_to_host16(sc->sci.port);
688
689 ret = macsec_qca_get_available_receive_sc(priv, &channel);
690 if (ret != 0)
691 return ret;
692
693 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
694
695 /* rx prc lut */
696 os_memset(&entry, 0, sizeof(entry));
697
698 os_memcpy(entry.sci, sci_addr, ETH_ALEN);
699 entry.sci[6] = (sci_port >> 8) & 0xff;
700 entry.sci[7] = sci_port & 0xff;
701 entry.sci_mask = 0xf;
702
703 entry.valid = 1;
704 entry.channel = channel;
705 entry.action = FAL_RX_PRC_ACTION_PROCESS;
706 entry.offset = conf_offset;
707
708 /* rx validate frame */
709 if (validate_frames == Strict)
710 vf = FAL_RX_SC_VALIDATE_FRAME_STRICT;
711 else if (validate_frames == Checked)
712 vf = FAL_RX_SC_VALIDATE_FRAME_CHECK;
713 else
714 vf = FAL_RX_SC_VALIDATE_FRAME_DISABLED;
715
716 ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry);
717 ret += nss_macsec_secy_rx_sc_create(drv->secy_id, channel);
718 ret += nss_macsec_secy_rx_sc_validate_frame_set(drv->secy_id, channel,
719 vf);
720 ret += nss_macsec_secy_rx_sc_replay_protect_set(drv->secy_id, channel,
721 drv->replay_protect);
722 ret += nss_macsec_secy_rx_sc_anti_replay_window_set(drv->secy_id,
723 channel,
724 drv->replay_window);
725
726 macsec_qca_register_receive_channel(drv, sc, channel);
727
728 return ret;
729 }
730
731
macsec_qca_delete_receive_sc(void * priv,struct receive_sc * sc)732 static int macsec_qca_delete_receive_sc(void *priv, struct receive_sc *sc)
733 {
734 struct macsec_qca_data *drv = priv;
735 int ret;
736 fal_rx_prc_lut_t entry;
737 u32 channel;
738
739 ret = macsec_qca_lookup_receive_channel(priv, sc, &channel);
740 if (ret != 0)
741 return ret;
742
743 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
744
745 /* rx prc lut */
746 os_memset(&entry, 0, sizeof(entry));
747
748 ret += nss_macsec_secy_rx_sc_del(drv->secy_id, channel);
749 ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry);
750
751 return ret;
752 }
753
754
macsec_qca_create_receive_sa(void * priv,struct receive_sa * sa)755 static int macsec_qca_create_receive_sa(void *priv, struct receive_sa *sa)
756 {
757 struct macsec_qca_data *drv = priv;
758 int ret;
759 fal_rx_sak_t rx_sak;
760 int i = 0;
761 u32 channel;
762 fal_rx_prc_lut_t entry;
763 u32 offset;
764
765 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
766 if (ret != 0)
767 return ret;
768
769 wpa_printf(MSG_DEBUG, "%s, channel=%d, an=%d, lpn=0x%x",
770 __func__, channel, sa->an, sa->lowest_pn);
771
772 os_memset(&rx_sak, 0, sizeof(rx_sak));
773 rx_sak.sak_len = sa->pkey->key_len;
774 if (sa->pkey->key_len == SAK_128_LEN) {
775 for (i = 0; i < 16; i++)
776 rx_sak.sak[i] = sa->pkey->key[15 - i];
777 } else if (sa->pkey->key_len == SAK_256_LEN) {
778 for (i = 0; i < 16; i++) {
779 rx_sak.sak1[i] = sa->pkey->key[15 - i];
780 rx_sak.sak[i] = sa->pkey->key[31 - i];
781 }
782 } else {
783 return -1;
784 }
785
786 if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0)
787 offset = 0;
788 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30)
789 offset = 30;
790 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50)
791 offset = 50;
792 else
793 return -1;
794 ret += nss_macsec_secy_rx_prc_lut_get(drv->secy_id, channel, &entry);
795 entry.offset = offset;
796 ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry);
797 ret += nss_macsec_secy_rx_sa_create(drv->secy_id, channel, sa->an);
798 ret += nss_macsec_secy_rx_sak_set(drv->secy_id, channel, sa->an,
799 &rx_sak);
800
801 return ret;
802 }
803
804
macsec_qca_enable_receive_sa(void * priv,struct receive_sa * sa)805 static int macsec_qca_enable_receive_sa(void *priv, struct receive_sa *sa)
806 {
807 struct macsec_qca_data *drv = priv;
808 int ret;
809 u32 channel;
810
811 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
812 if (ret != 0)
813 return ret;
814
815 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
816 sa->an);
817
818 ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an,
819 true);
820
821 return ret;
822 }
823
824
macsec_qca_disable_receive_sa(void * priv,struct receive_sa * sa)825 static int macsec_qca_disable_receive_sa(void *priv, struct receive_sa *sa)
826 {
827 struct macsec_qca_data *drv = priv;
828 int ret;
829 u32 channel;
830
831 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
832 if (ret != 0)
833 return ret;
834
835 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
836 sa->an);
837
838 ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an,
839 false);
840
841 return ret;
842 }
843
844
macsec_qca_get_available_transmit_sc(void * priv,u32 * channel)845 static int macsec_qca_get_available_transmit_sc(void *priv, u32 *channel)
846 {
847 struct macsec_qca_data *drv = priv;
848 u32 sc_ch = 0;
849 bool in_use = false;
850
851 for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) {
852 if (nss_macsec_secy_tx_sc_in_used_get(drv->secy_id, sc_ch,
853 &in_use))
854 continue;
855
856 if (!in_use) {
857 *channel = sc_ch;
858 wpa_printf(MSG_DEBUG, "%s: channel=%d",
859 __func__, *channel);
860 return 0;
861 }
862 }
863
864 wpa_printf(MSG_DEBUG, "%s: no available channel", __func__);
865
866 return -1;
867 }
868
869
macsec_qca_create_transmit_sc(void * priv,struct transmit_sc * sc,unsigned int conf_offset)870 static int macsec_qca_create_transmit_sc(void *priv, struct transmit_sc *sc,
871 unsigned int conf_offset)
872 {
873 struct macsec_qca_data *drv = priv;
874 int ret;
875 fal_tx_class_lut_t entry;
876 u8 psci[ETH_ALEN + 2];
877 u32 channel;
878 u16 sci_port = be_to_host16(sc->sci.port);
879
880 ret = macsec_qca_get_available_transmit_sc(priv, &channel);
881 if (ret != 0)
882 return ret;
883
884 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
885
886 /* class lut */
887 os_memset(&entry, 0, sizeof(entry));
888
889 entry.valid = 1;
890 entry.action = FAL_TX_CLASS_ACTION_FORWARD;
891 entry.channel = channel;
892
893 os_memcpy(psci, sc->sci.addr, ETH_ALEN);
894 psci[6] = (sci_port >> 8) & 0xff;
895 psci[7] = sci_port & 0xff;
896
897 ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry);
898 ret += nss_macsec_secy_tx_sc_create(drv->secy_id, channel, psci, 8);
899 ret += nss_macsec_secy_tx_sc_protect_set(drv->secy_id, channel,
900 drv->protect_frames);
901 ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id,
902 channel,
903 conf_offset);
904
905 macsec_qca_register_transmit_channel(drv, sc, channel);
906
907 return ret;
908 }
909
910
macsec_qca_delete_transmit_sc(void * priv,struct transmit_sc * sc)911 static int macsec_qca_delete_transmit_sc(void *priv, struct transmit_sc *sc)
912 {
913 struct macsec_qca_data *drv = priv;
914 int ret;
915 fal_tx_class_lut_t entry;
916 u32 channel;
917
918 ret = macsec_qca_lookup_transmit_channel(priv, sc, &channel);
919 if (ret != 0)
920 return ret;
921
922 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
923
924 /* class lut */
925 os_memset(&entry, 0, sizeof(entry));
926
927 ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry);
928 ret += nss_macsec_secy_tx_sc_del(drv->secy_id, channel);
929
930 return ret;
931 }
932
933
macsec_qca_create_transmit_sa(void * priv,struct transmit_sa * sa)934 static int macsec_qca_create_transmit_sa(void *priv, struct transmit_sa *sa)
935 {
936 struct macsec_qca_data *drv = priv;
937 int ret;
938 u8 tci = 0;
939 fal_tx_sak_t tx_sak;
940 int i;
941 u32 channel;
942 u32 offset;
943
944 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
945 if (ret != 0)
946 return ret;
947
948 wpa_printf(MSG_DEBUG,
949 "%s: channel=%d, an=%d, next_pn=0x%x, confidentiality=%d",
950 __func__, channel, sa->an, sa->next_pn, sa->confidentiality);
951
952 if (drv->always_include_sci)
953 tci |= TCI_SC;
954 else if (drv->use_es)
955 tci |= TCI_ES;
956 else if (drv->use_scb)
957 tci |= TCI_SCB;
958
959 if (sa->confidentiality)
960 tci |= TCI_E | TCI_C;
961
962 os_memset(&tx_sak, 0, sizeof(tx_sak));
963 tx_sak.sak_len = sa->pkey->key_len;
964 if (sa->pkey->key_len == SAK_128_LEN) {
965 for (i = 0; i < 16; i++)
966 tx_sak.sak[i] = sa->pkey->key[15 - i];
967 } else if (sa->pkey->key_len == SAK_256_LEN) {
968 for (i = 0; i < 16; i++) {
969 tx_sak.sak1[i] = sa->pkey->key[15 - i];
970 tx_sak.sak[i] = sa->pkey->key[31 - i];
971 }
972 } else {
973 return -1;
974 }
975
976 if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0)
977 offset = 0;
978 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30)
979 offset = 30;
980 else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50)
981 offset = 50;
982 else
983 return -1;
984 ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id,
985 channel,
986 offset);
987 ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an,
988 sa->next_pn);
989 ret += nss_macsec_secy_tx_sak_set(drv->secy_id, channel, sa->an,
990 &tx_sak);
991 ret += nss_macsec_secy_tx_sc_tci_7_2_set(drv->secy_id, channel,
992 (tci >> 2));
993 ret += nss_macsec_secy_tx_sc_an_set(drv->secy_id, channel, sa->an);
994
995 return ret;
996 }
997
998
macsec_qca_enable_transmit_sa(void * priv,struct transmit_sa * sa)999 static int macsec_qca_enable_transmit_sa(void *priv, struct transmit_sa *sa)
1000 {
1001 struct macsec_qca_data *drv = priv;
1002 int ret;
1003 u32 channel;
1004
1005 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
1006 if (ret != 0)
1007 return ret;
1008
1009 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
1010 sa->an);
1011
1012 ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
1013 true);
1014
1015 return ret;
1016 }
1017
1018
macsec_qca_disable_transmit_sa(void * priv,struct transmit_sa * sa)1019 static int macsec_qca_disable_transmit_sa(void *priv, struct transmit_sa *sa)
1020 {
1021 struct macsec_qca_data *drv = priv;
1022 int ret;
1023 u32 channel;
1024
1025 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
1026 if (ret != 0)
1027 return ret;
1028
1029 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
1030 sa->an);
1031
1032 ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
1033 false);
1034
1035 return ret;
1036 }
1037
1038
1039 const struct wpa_driver_ops wpa_driver_macsec_qca_ops = {
1040 .name = "macsec_qca",
1041 .desc = "QCA MACsec Ethernet driver",
1042 .get_ssid = driver_wired_get_ssid,
1043 .get_bssid = driver_wired_get_bssid,
1044 .get_capa = driver_wired_get_capa,
1045 .init = macsec_qca_init,
1046 .deinit = macsec_qca_deinit,
1047 .hapd_init = macsec_qca_hapd_init,
1048 .hapd_deinit = macsec_qca_hapd_deinit,
1049 .hapd_send_eapol = macsec_qca_send_eapol,
1050
1051 .macsec_init = macsec_qca_macsec_init,
1052 .macsec_deinit = macsec_qca_macsec_deinit,
1053 .macsec_get_capability = macsec_qca_get_capability,
1054 .enable_protect_frames = macsec_qca_enable_protect_frames,
1055 .set_replay_protect = macsec_qca_set_replay_protect,
1056 .set_current_cipher_suite = macsec_qca_set_current_cipher_suite,
1057 .enable_controlled_port = macsec_qca_enable_controlled_port,
1058 .get_receive_lowest_pn = macsec_qca_get_receive_lowest_pn,
1059 .get_transmit_next_pn = macsec_qca_get_transmit_next_pn,
1060 .set_transmit_next_pn = macsec_qca_set_transmit_next_pn,
1061 .create_receive_sc = macsec_qca_create_receive_sc,
1062 .delete_receive_sc = macsec_qca_delete_receive_sc,
1063 .create_receive_sa = macsec_qca_create_receive_sa,
1064 .enable_receive_sa = macsec_qca_enable_receive_sa,
1065 .disable_receive_sa = macsec_qca_disable_receive_sa,
1066 .create_transmit_sc = macsec_qca_create_transmit_sc,
1067 .delete_transmit_sc = macsec_qca_delete_transmit_sc,
1068 .create_transmit_sa = macsec_qca_create_transmit_sa,
1069 .enable_transmit_sa = macsec_qca_enable_transmit_sa,
1070 .disable_transmit_sa = macsec_qca_disable_transmit_sa,
1071 };
1072