]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa/src/drivers/driver_macsec_qca.c
Merge ^/vendor/libc++/dist up to its last change, and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / wpa / src / drivers / driver_macsec_qca.c
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         Boolean always_include_sci;
74         Boolean use_es;
75         Boolean use_scb;
76         Boolean protect_frames;
77         Boolean 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
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
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
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
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
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
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
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
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
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
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
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
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
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
425 static int macsec_qca_enable_protect_frames(void *priv, Boolean 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
438 static int macsec_qca_set_replay_protect(void *priv, Boolean 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
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
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
483 static int macsec_qca_enable_controlled_port(void *priv, Boolean 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 };