1 /*
2 * Driver interaction with Linux MACsec kernel module
3 * Copyright (c) 2016, Sabrina Dubroca <sd@queasysnail.net> and Red Hat, Inc.
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10 #include <sys/ioctl.h>
11 #include <net/if.h>
12 #include <netpacket/packet.h>
13 #include <net/if_arp.h>
14 #include <net/if.h>
15 #include <netlink/netlink.h>
16 #include <netlink/genl/genl.h>
17 #include <netlink/genl/ctrl.h>
18 #include <netlink/route/link.h>
19 #include <netlink/route/link/macsec.h>
20 #include <linux/if_macsec.h>
21 #include <inttypes.h>
22
23 #include "utils/common.h"
24 #include "utils/eloop.h"
25 #include "pae/ieee802_1x_kay.h"
26 #include "driver.h"
27 #include "driver_wired_common.h"
28
29 #define DRV_PREFIX "macsec_linux: "
30
31 #define UNUSED_SCI 0xffffffffffffffff
32
33 struct cb_arg {
34 struct macsec_drv_data *drv;
35 u32 *pn;
36 int ifindex;
37 u8 txsa;
38 u8 rxsa;
39 u64 rxsci;
40 };
41
42 struct macsec_genl_ctx {
43 struct nl_sock *sk;
44 int macsec_genl_id;
45 struct cb_arg cb_arg;
46 };
47
48 struct macsec_drv_data {
49 struct driver_wired_common_data common;
50 struct rtnl_link *link;
51 struct nl_cache *link_cache;
52 struct nl_sock *sk;
53 struct macsec_genl_ctx ctx;
54
55 struct netlink_data *netlink;
56 struct nl_handle *nl;
57 char ifname[IFNAMSIZ + 1];
58 int ifi;
59 int parent_ifi;
60
61 Boolean created_link;
62
63 Boolean controlled_port_enabled;
64 Boolean controlled_port_enabled_set;
65
66 Boolean protect_frames;
67 Boolean protect_frames_set;
68
69 Boolean encrypt;
70 Boolean encrypt_set;
71
72 Boolean replay_protect;
73 Boolean replay_protect_set;
74
75 u32 replay_window;
76
77 u8 encoding_sa;
78 Boolean encoding_sa_set;
79 };
80
81
82 static int dump_callback(struct nl_msg *msg, void *argp);
83
84
msg_prepare(enum macsec_nl_commands cmd,const struct macsec_genl_ctx * ctx,unsigned int ifindex)85 static struct nl_msg * msg_prepare(enum macsec_nl_commands cmd,
86 const struct macsec_genl_ctx *ctx,
87 unsigned int ifindex)
88 {
89 struct nl_msg *msg;
90
91 msg = nlmsg_alloc();
92 if (!msg) {
93 wpa_printf(MSG_ERROR, DRV_PREFIX "failed to alloc message");
94 return NULL;
95 }
96
97 if (!genlmsg_put(msg, 0, 0, ctx->macsec_genl_id, 0, 0, cmd, 0)) {
98 wpa_printf(MSG_ERROR, DRV_PREFIX "failed to put header");
99 goto nla_put_failure;
100 }
101
102 NLA_PUT_U32(msg, MACSEC_ATTR_IFINDEX, ifindex);
103
104 return msg;
105
106 nla_put_failure:
107 nlmsg_free(msg);
108 return NULL;
109 }
110
111
nla_put_rxsc_config(struct nl_msg * msg,u64 sci)112 static int nla_put_rxsc_config(struct nl_msg *msg, u64 sci)
113 {
114 struct nlattr *nest = nla_nest_start(msg, MACSEC_ATTR_RXSC_CONFIG);
115
116 if (!nest)
117 return -1;
118
119 NLA_PUT_U64(msg, MACSEC_RXSC_ATTR_SCI, sci);
120
121 nla_nest_end(msg, nest);
122
123 return 0;
124
125 nla_put_failure:
126 return -1;
127 }
128
129
init_genl_ctx(struct macsec_drv_data * drv)130 static int init_genl_ctx(struct macsec_drv_data *drv)
131 {
132 struct macsec_genl_ctx *ctx = &drv->ctx;
133
134 ctx->sk = nl_socket_alloc();
135 if (!ctx->sk) {
136 wpa_printf(MSG_ERROR, DRV_PREFIX "failed to alloc genl socket");
137 return -1;
138 }
139
140 if (genl_connect(ctx->sk) < 0) {
141 wpa_printf(MSG_ERROR,
142 DRV_PREFIX "connection to genl socket failed");
143 goto out_free;
144 }
145
146 ctx->macsec_genl_id = genl_ctrl_resolve(ctx->sk, "macsec");
147 if (ctx->macsec_genl_id < 0) {
148 wpa_printf(MSG_ERROR, DRV_PREFIX "genl resolve failed");
149 goto out_free;
150 }
151
152 memset(&ctx->cb_arg, 0, sizeof(ctx->cb_arg));
153 ctx->cb_arg.drv = drv;
154
155 nl_socket_modify_cb(ctx->sk, NL_CB_VALID, NL_CB_CUSTOM, dump_callback,
156 &ctx->cb_arg);
157
158 return 0;
159
160 out_free:
161 nl_socket_free(ctx->sk);
162 ctx->sk = NULL;
163 return -1;
164 }
165
166
try_commit(struct macsec_drv_data * drv)167 static int try_commit(struct macsec_drv_data *drv)
168 {
169 int err;
170
171 if (!drv->link)
172 return 0;
173
174 if (drv->controlled_port_enabled_set) {
175 struct rtnl_link *change = rtnl_link_alloc();
176
177 if (!change)
178 return -1;
179
180 rtnl_link_set_name(change, drv->ifname);
181
182 if (drv->controlled_port_enabled)
183 rtnl_link_set_flags(change, IFF_UP);
184 else
185 rtnl_link_unset_flags(change, IFF_UP);
186
187 err = rtnl_link_change(drv->sk, change, change, 0);
188 if (err < 0)
189 return err;
190
191 rtnl_link_put(change);
192
193 drv->controlled_port_enabled_set = FALSE;
194 }
195
196 if (drv->protect_frames_set)
197 rtnl_link_macsec_set_protect(drv->link, drv->protect_frames);
198
199 if (drv->encrypt_set)
200 rtnl_link_macsec_set_encrypt(drv->link, drv->encrypt);
201
202 if (drv->replay_protect_set) {
203 rtnl_link_macsec_set_replay_protect(drv->link,
204 drv->replay_protect);
205 if (drv->replay_protect)
206 rtnl_link_macsec_set_window(drv->link,
207 drv->replay_window);
208 }
209
210 if (drv->encoding_sa_set)
211 rtnl_link_macsec_set_encoding_sa(drv->link, drv->encoding_sa);
212
213 err = rtnl_link_add(drv->sk, drv->link, 0);
214 if (err < 0)
215 return err;
216
217 drv->protect_frames_set = FALSE;
218 drv->encrypt_set = FALSE;
219 drv->replay_protect_set = FALSE;
220
221 return 0;
222 }
223
224
macsec_drv_wpa_deinit(void * priv)225 static void macsec_drv_wpa_deinit(void *priv)
226 {
227 struct macsec_drv_data *drv = priv;
228
229 driver_wired_deinit_common(&drv->common);
230 os_free(drv);
231 }
232
233
macsec_drv_wpa_init(void * ctx,const char * ifname)234 static void * macsec_drv_wpa_init(void *ctx, const char *ifname)
235 {
236 struct macsec_drv_data *drv;
237
238 drv = os_zalloc(sizeof(*drv));
239 if (!drv)
240 return NULL;
241
242 if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) {
243 os_free(drv);
244 return NULL;
245 }
246
247 return drv;
248 }
249
250
macsec_drv_macsec_init(void * priv,struct macsec_init_params * params)251 static int macsec_drv_macsec_init(void *priv, struct macsec_init_params *params)
252 {
253 struct macsec_drv_data *drv = priv;
254 int err;
255
256 wpa_printf(MSG_DEBUG, "%s", __func__);
257
258 drv->sk = nl_socket_alloc();
259 if (!drv->sk)
260 return -1;
261
262 err = nl_connect(drv->sk, NETLINK_ROUTE);
263 if (err < 0) {
264 wpa_printf(MSG_ERROR, DRV_PREFIX
265 "Unable to connect NETLINK_ROUTE socket: %s",
266 strerror(errno));
267 goto sock;
268 }
269
270 err = rtnl_link_alloc_cache(drv->sk, AF_UNSPEC, &drv->link_cache);
271 if (err < 0) {
272 wpa_printf(MSG_ERROR, DRV_PREFIX "Unable to get link cache: %s",
273 strerror(errno));
274 goto sock;
275 }
276
277 drv->parent_ifi = rtnl_link_name2i(drv->link_cache, drv->common.ifname);
278 if (drv->parent_ifi == 0) {
279 wpa_printf(MSG_ERROR, DRV_PREFIX
280 "couldn't find ifindex for interface %s",
281 drv->common.ifname);
282 goto cache;
283 }
284
285 err = init_genl_ctx(drv);
286 if (err < 0)
287 goto cache;
288
289 return 0;
290
291 cache:
292 nl_cache_free(drv->link_cache);
293 drv->link_cache = NULL;
294 sock:
295 nl_socket_free(drv->sk);
296 drv->sk = NULL;
297 return -1;
298 }
299
300
macsec_drv_macsec_deinit(void * priv)301 static int macsec_drv_macsec_deinit(void *priv)
302 {
303 struct macsec_drv_data *drv = priv;
304
305 wpa_printf(MSG_DEBUG, "%s", __func__);
306
307 if (drv->sk)
308 nl_socket_free(drv->sk);
309 drv->sk = NULL;
310
311 if (drv->link_cache)
312 nl_cache_free(drv->link_cache);
313 drv->link_cache = NULL;
314
315 if (drv->ctx.sk)
316 nl_socket_free(drv->ctx.sk);
317
318 return 0;
319 }
320
321
macsec_drv_get_capability(void * priv,enum macsec_cap * cap)322 static int macsec_drv_get_capability(void *priv, enum macsec_cap *cap)
323 {
324 wpa_printf(MSG_DEBUG, "%s", __func__);
325
326 *cap = MACSEC_CAP_INTEG_AND_CONF;
327
328 return 0;
329 }
330
331
332 /**
333 * macsec_drv_enable_protect_frames - Set protect frames status
334 * @priv: Private driver interface data
335 * @enabled: TRUE = protect frames enabled
336 * FALSE = protect frames disabled
337 * Returns: 0 on success, -1 on failure (or if not supported)
338 */
macsec_drv_enable_protect_frames(void * priv,Boolean enabled)339 static int macsec_drv_enable_protect_frames(void *priv, Boolean enabled)
340 {
341 struct macsec_drv_data *drv = priv;
342
343 wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE");
344
345 drv->protect_frames_set = TRUE;
346 drv->protect_frames = enabled;
347
348 return try_commit(drv);
349 }
350
351
352 /**
353 * macsec_drv_enable_encrypt - Set protect frames status
354 * @priv: Private driver interface data
355 * @enabled: TRUE = protect frames enabled
356 * FALSE = protect frames disabled
357 * Returns: 0 on success, -1 on failure (or if not supported)
358 */
macsec_drv_enable_encrypt(void * priv,Boolean enabled)359 static int macsec_drv_enable_encrypt(void *priv, Boolean enabled)
360 {
361 struct macsec_drv_data *drv = priv;
362
363 wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE");
364
365 drv->encrypt_set = TRUE;
366 drv->encrypt = enabled;
367
368 return try_commit(drv);
369 }
370
371
372 /**
373 * macsec_drv_set_replay_protect - Set replay protect status and window size
374 * @priv: Private driver interface data
375 * @enabled: TRUE = replay protect enabled
376 * FALSE = replay protect disabled
377 * @window: replay window size, valid only when replay protect enabled
378 * Returns: 0 on success, -1 on failure (or if not supported)
379 */
macsec_drv_set_replay_protect(void * priv,Boolean enabled,u32 window)380 static int macsec_drv_set_replay_protect(void *priv, Boolean enabled,
381 u32 window)
382 {
383 struct macsec_drv_data *drv = priv;
384
385 wpa_printf(MSG_DEBUG, "%s -> %s, %u", __func__,
386 enabled ? "TRUE" : "FALSE", window);
387
388 drv->replay_protect_set = TRUE;
389 drv->replay_protect = enabled;
390 if (enabled)
391 drv->replay_window = window;
392
393 return try_commit(drv);
394 }
395
396
397 /**
398 * macsec_drv_set_current_cipher_suite - Set current cipher suite
399 * @priv: Private driver interface data
400 * @cs: EUI64 identifier
401 * Returns: 0 on success, -1 on failure (or if not supported)
402 */
macsec_drv_set_current_cipher_suite(void * priv,u64 cs)403 static int macsec_drv_set_current_cipher_suite(void *priv, u64 cs)
404 {
405 wpa_printf(MSG_DEBUG, "%s -> %016" PRIx64, __func__, cs);
406 return 0;
407 }
408
409
410 /**
411 * macsec_drv_enable_controlled_port - Set controlled port status
412 * @priv: Private driver interface data
413 * @enabled: TRUE = controlled port enabled
414 * FALSE = controlled port disabled
415 * Returns: 0 on success, -1 on failure (or if not supported)
416 */
macsec_drv_enable_controlled_port(void * priv,Boolean enabled)417 static int macsec_drv_enable_controlled_port(void *priv, Boolean enabled)
418 {
419 struct macsec_drv_data *drv = priv;
420
421 wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE");
422
423 drv->controlled_port_enabled = enabled;
424 drv->controlled_port_enabled_set = TRUE;
425
426 return try_commit(drv);
427 }
428
429
430 static struct nla_policy sa_policy[MACSEC_SA_ATTR_MAX + 1] = {
431 [MACSEC_SA_ATTR_AN] = { .type = NLA_U8 },
432 [MACSEC_SA_ATTR_ACTIVE] = { .type = NLA_U8 },
433 [MACSEC_SA_ATTR_PN] = { .type = NLA_U32 },
434 [MACSEC_SA_ATTR_KEYID] = { .type = NLA_BINARY },
435 };
436
437 static struct nla_policy sc_policy[MACSEC_RXSC_ATTR_MAX + 1] = {
438 [MACSEC_RXSC_ATTR_SCI] = { .type = NLA_U64 },
439 [MACSEC_RXSC_ATTR_ACTIVE] = { .type = NLA_U8 },
440 [MACSEC_RXSC_ATTR_SA_LIST] = { .type = NLA_NESTED },
441 };
442
443 static struct nla_policy main_policy[MACSEC_ATTR_MAX + 1] = {
444 [MACSEC_ATTR_IFINDEX] = { .type = NLA_U32 },
445 [MACSEC_ATTR_SECY] = { .type = NLA_NESTED },
446 [MACSEC_ATTR_TXSA_LIST] = { .type = NLA_NESTED },
447 [MACSEC_ATTR_RXSC_LIST] = { .type = NLA_NESTED },
448 };
449
dump_callback(struct nl_msg * msg,void * argp)450 static int dump_callback(struct nl_msg *msg, void *argp)
451 {
452 struct nlmsghdr *ret_hdr = nlmsg_hdr(msg);
453 struct nlattr *tb_msg[MACSEC_ATTR_MAX + 1];
454 struct cb_arg *arg = (struct cb_arg *) argp;
455 struct genlmsghdr *gnlh = (struct genlmsghdr *) nlmsg_data(ret_hdr);
456 int err;
457
458 if (ret_hdr->nlmsg_type != arg->drv->ctx.macsec_genl_id)
459 return 0;
460
461 err = nla_parse(tb_msg, MACSEC_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
462 genlmsg_attrlen(gnlh, 0), main_policy);
463 if (err < 0)
464 return 0;
465
466 if (!tb_msg[MACSEC_ATTR_IFINDEX])
467 return 0;
468
469 if (nla_get_u32(tb_msg[MACSEC_ATTR_IFINDEX]) != (u32) arg->ifindex)
470 return 0;
471
472 if (arg->txsa < 4 && !tb_msg[MACSEC_ATTR_TXSA_LIST]) {
473 return 0;
474 } else if (arg->txsa < 4) {
475 struct nlattr *nla;
476 int rem;
477
478 nla_for_each_nested(nla, tb_msg[MACSEC_ATTR_TXSA_LIST], rem) {
479 struct nlattr *tb[MACSEC_SA_ATTR_MAX + 1];
480
481 err = nla_parse_nested(tb, MACSEC_SA_ATTR_MAX, nla,
482 sa_policy);
483 if (err < 0)
484 continue;
485 if (!tb[MACSEC_SA_ATTR_AN])
486 continue;
487 if (nla_get_u8(tb[MACSEC_SA_ATTR_AN]) != arg->txsa)
488 continue;
489 if (!tb[MACSEC_SA_ATTR_PN])
490 return 0;
491 *arg->pn = nla_get_u32(tb[MACSEC_SA_ATTR_PN]);
492 return 0;
493 }
494
495 return 0;
496 }
497
498 if (arg->rxsci == UNUSED_SCI)
499 return 0;
500
501 if (tb_msg[MACSEC_ATTR_RXSC_LIST]) {
502 struct nlattr *nla;
503 int rem;
504
505 nla_for_each_nested(nla, tb_msg[MACSEC_ATTR_RXSC_LIST], rem) {
506 struct nlattr *tb[MACSEC_RXSC_ATTR_MAX + 1];
507
508 err = nla_parse_nested(tb, MACSEC_RXSC_ATTR_MAX, nla,
509 sc_policy);
510 if (err < 0)
511 return 0;
512 if (!tb[MACSEC_RXSC_ATTR_SCI])
513 continue;
514 if (nla_get_u64(tb[MACSEC_RXSC_ATTR_SCI]) != arg->rxsci)
515 continue;
516 if (!tb[MACSEC_RXSC_ATTR_SA_LIST])
517 return 0;
518
519 nla_for_each_nested(nla, tb[MACSEC_RXSC_ATTR_SA_LIST],
520 rem) {
521 struct nlattr *tb_sa[MACSEC_SA_ATTR_MAX + 1];
522
523 err = nla_parse_nested(tb_sa,
524 MACSEC_SA_ATTR_MAX, nla,
525 sa_policy);
526 if (err < 0)
527 continue;
528 if (!tb_sa[MACSEC_SA_ATTR_AN])
529 continue;
530 if (nla_get_u8(tb_sa[MACSEC_SA_ATTR_AN]) !=
531 arg->rxsa)
532 continue;
533 if (!tb_sa[MACSEC_SA_ATTR_PN])
534 return 0;
535 *arg->pn =
536 nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]);
537
538 return 0;
539 }
540
541 return 0;
542 }
543
544 return 0;
545 }
546
547 return 0;
548 }
549
550
nl_send_recv(struct nl_sock * sk,struct nl_msg * msg)551 static int nl_send_recv(struct nl_sock *sk, struct nl_msg *msg)
552 {
553 int ret;
554
555 ret = nl_send_auto_complete(sk, msg);
556 if (ret < 0) {
557 wpa_printf(MSG_ERROR, DRV_PREFIX "%s: failed to send: %d (%s)",
558 __func__, ret, nl_geterror(-ret));
559 return ret;
560 }
561
562 ret = nl_recvmsgs_default(sk);
563 if (ret < 0) {
564 wpa_printf(MSG_ERROR, DRV_PREFIX "%s: failed to recv: %d (%s)",
565 __func__, ret, nl_geterror(-ret));
566 }
567
568 return ret;
569 }
570
571
do_dump(struct macsec_drv_data * drv,u8 txsa,u64 rxsci,u8 rxsa,u32 * pn)572 static int do_dump(struct macsec_drv_data *drv, u8 txsa, u64 rxsci, u8 rxsa,
573 u32 *pn)
574 {
575 struct macsec_genl_ctx *ctx = &drv->ctx;
576 struct nl_msg *msg;
577 int ret = 1;
578
579 ctx->cb_arg.ifindex = drv->ifi;
580 ctx->cb_arg.rxsci = rxsci;
581 ctx->cb_arg.rxsa = rxsa;
582 ctx->cb_arg.txsa = txsa;
583 ctx->cb_arg.pn = pn;
584
585 msg = nlmsg_alloc();
586 if (!msg) {
587 wpa_printf(MSG_ERROR, DRV_PREFIX "%s: failed to alloc message",
588 __func__);
589 return 1;
590 }
591
592 if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, ctx->macsec_genl_id, 0,
593 NLM_F_DUMP, MACSEC_CMD_GET_TXSC, 0)) {
594 wpa_printf(MSG_ERROR, DRV_PREFIX "%s: failed to put header",
595 __func__);
596 goto out_free_msg;
597 }
598
599 ret = nl_send_recv(ctx->sk, msg);
600 if (ret < 0)
601 wpa_printf(MSG_ERROR,
602 DRV_PREFIX "failed to communicate: %d (%s)",
603 ret, nl_geterror(-ret));
604
605 ctx->cb_arg.pn = 0;
606
607 out_free_msg:
608 nlmsg_free(msg);
609 return ret;
610 }
611
612
613 /**
614 * macsec_drv_get_receive_lowest_pn - Get receive lowest PN
615 * @priv: Private driver interface data
616 * @sa: secure association
617 * Returns: 0 on success, -1 on failure (or if not supported)
618 */
macsec_drv_get_receive_lowest_pn(void * priv,struct receive_sa * sa)619 static int macsec_drv_get_receive_lowest_pn(void *priv, struct receive_sa *sa)
620 {
621 struct macsec_drv_data *drv = priv;
622 int err;
623
624 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s", __func__);
625
626 err = do_dump(drv, 0xff, mka_sci_u64(&sa->sc->sci), sa->an,
627 &sa->lowest_pn);
628 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: result %d", __func__,
629 sa->lowest_pn);
630
631 return err;
632 }
633
634
635 /**
636 * macsec_drv_get_transmit_next_pn - Get transmit next PN
637 * @priv: Private driver interface data
638 * @sa: secure association
639 * Returns: 0 on success, -1 on failure (or if not supported)
640 */
macsec_drv_get_transmit_next_pn(void * priv,struct transmit_sa * sa)641 static int macsec_drv_get_transmit_next_pn(void *priv, struct transmit_sa *sa)
642 {
643 struct macsec_drv_data *drv = priv;
644 int err;
645
646 wpa_printf(MSG_DEBUG, "%s", __func__);
647
648 err = do_dump(drv, sa->an, UNUSED_SCI, 0xff, &sa->next_pn);
649 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: err %d result %d", __func__, err,
650 sa->next_pn);
651 return err;
652 }
653
654
655 /**
656 * macsec_drv_set_transmit_next_pn - Set transmit next pn
657 * @priv: Private driver interface data
658 * @sa: secure association
659 * Returns: 0 on success, -1 on failure (or if not supported)
660 */
macsec_drv_set_transmit_next_pn(void * priv,struct transmit_sa * sa)661 static int macsec_drv_set_transmit_next_pn(void *priv, struct transmit_sa *sa)
662 {
663 struct macsec_drv_data *drv = priv;
664 struct macsec_genl_ctx *ctx = &drv->ctx;
665 struct nl_msg *msg;
666 struct nlattr *nest;
667 int ret = -1;
668
669 wpa_printf(MSG_DEBUG, "%s -> %d: %d", __func__, sa->an, sa->next_pn);
670
671 msg = msg_prepare(MACSEC_CMD_UPD_TXSA, ctx, drv->ifi);
672 if (!msg)
673 return ret;
674
675 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
676 if (!nest)
677 goto nla_put_failure;
678
679 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
680 NLA_PUT_U32(msg, MACSEC_SA_ATTR_PN, sa->next_pn);
681
682 nla_nest_end(msg, nest);
683
684 ret = nl_send_recv(ctx->sk, msg);
685 if (ret < 0) {
686 wpa_printf(MSG_ERROR,
687 DRV_PREFIX "failed to communicate: %d (%s)",
688 ret, nl_geterror(-ret));
689 }
690
691 nla_put_failure:
692 nlmsg_free(msg);
693 return ret;
694 }
695
696
697 #define SCISTR MACSTR "::%hx"
698 #define SCI2STR(addr, port) MAC2STR(addr), htons(port)
699
700 /**
701 * macsec_drv_create_receive_sc - Create secure channel for receiving
702 * @priv: Private driver interface data
703 * @sc: secure channel
704 * @sci_addr: secure channel identifier - address
705 * @sci_port: secure channel identifier - port
706 * @conf_offset: confidentiality offset (0, 30, or 50)
707 * @validation: frame validation policy (0 = Disabled, 1 = Checked,
708 * 2 = Strict)
709 * Returns: 0 on success, -1 on failure (or if not supported)
710 */
macsec_drv_create_receive_sc(void * priv,struct receive_sc * sc,unsigned int conf_offset,int validation)711 static int macsec_drv_create_receive_sc(void *priv, struct receive_sc *sc,
712 unsigned int conf_offset,
713 int validation)
714 {
715 struct macsec_drv_data *drv = priv;
716 struct macsec_genl_ctx *ctx = &drv->ctx;
717 struct nl_msg *msg;
718 int ret = -1;
719
720 wpa_printf(MSG_DEBUG, "%s -> " SCISTR, __func__,
721 SCI2STR(sc->sci.addr, sc->sci.port));
722
723 msg = msg_prepare(MACSEC_CMD_ADD_RXSC, ctx, drv->ifi);
724 if (!msg)
725 return ret;
726
727 if (nla_put_rxsc_config(msg, mka_sci_u64(&sc->sci)))
728 goto nla_put_failure;
729
730 ret = nl_send_recv(ctx->sk, msg);
731 if (ret < 0) {
732 wpa_printf(MSG_ERROR,
733 DRV_PREFIX "%s: failed to communicate: %d (%s)",
734 __func__, ret, nl_geterror(-ret));
735 }
736
737 nla_put_failure:
738 nlmsg_free(msg);
739 return ret;
740 }
741
742
743 /**
744 * macsec_drv_delete_receive_sc - Delete secure connection for receiving
745 * @priv: private driver interface data from init()
746 * @sc: secure channel
747 * Returns: 0 on success, -1 on failure
748 */
macsec_drv_delete_receive_sc(void * priv,struct receive_sc * sc)749 static int macsec_drv_delete_receive_sc(void *priv, struct receive_sc *sc)
750 {
751 struct macsec_drv_data *drv = priv;
752 struct macsec_genl_ctx *ctx = &drv->ctx;
753 struct nl_msg *msg;
754 int ret = -1;
755
756 wpa_printf(MSG_DEBUG, "%s -> " SCISTR, __func__,
757 SCI2STR(sc->sci.addr, sc->sci.port));
758
759 msg = msg_prepare(MACSEC_CMD_DEL_RXSC, ctx, drv->ifi);
760 if (!msg)
761 return ret;
762
763 if (nla_put_rxsc_config(msg, mka_sci_u64(&sc->sci)))
764 goto nla_put_failure;
765
766 ret = nl_send_recv(ctx->sk, msg);
767 if (ret < 0) {
768 wpa_printf(MSG_ERROR,
769 DRV_PREFIX "%s: failed to communicate: %d (%s)",
770 __func__, ret, nl_geterror(-ret));
771 }
772
773 nla_put_failure:
774 nlmsg_free(msg);
775 return ret;
776 }
777
778
779 /**
780 * macsec_drv_create_receive_sa - Create secure association for receive
781 * @priv: private driver interface data from init()
782 * @sa: secure association
783 * Returns: 0 on success, -1 on failure
784 */
macsec_drv_create_receive_sa(void * priv,struct receive_sa * sa)785 static int macsec_drv_create_receive_sa(void *priv, struct receive_sa *sa)
786 {
787 struct macsec_drv_data *drv = priv;
788 struct macsec_genl_ctx *ctx = &drv->ctx;
789 struct nl_msg *msg;
790 struct nlattr *nest;
791 int ret = -1;
792
793 wpa_printf(MSG_DEBUG, "%s -> %d on " SCISTR, __func__, sa->an,
794 SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
795
796 msg = msg_prepare(MACSEC_CMD_ADD_RXSA, ctx, drv->ifi);
797 if (!msg)
798 return ret;
799
800 if (nla_put_rxsc_config(msg, mka_sci_u64(&sa->sc->sci)))
801 goto nla_put_failure;
802
803 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
804 if (!nest)
805 goto nla_put_failure;
806
807 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
808 NLA_PUT_U8(msg, MACSEC_SA_ATTR_ACTIVE, sa->enable_receive);
809 NLA_PUT_U32(msg, MACSEC_SA_ATTR_PN, sa->next_pn);
810 NLA_PUT(msg, MACSEC_SA_ATTR_KEYID, sizeof(sa->pkey->key_identifier),
811 &sa->pkey->key_identifier);
812 NLA_PUT(msg, MACSEC_SA_ATTR_KEY, sa->pkey->key_len, sa->pkey->key);
813
814 nla_nest_end(msg, nest);
815
816 ret = nl_send_recv(ctx->sk, msg);
817 if (ret < 0) {
818 wpa_printf(MSG_ERROR,
819 DRV_PREFIX "%s: failed to communicate: %d (%s)",
820 __func__, ret, nl_geterror(-ret));
821 }
822
823 nla_put_failure:
824 nlmsg_free(msg);
825 return ret;
826 }
827
828
829 /**
830 * macsec_drv_delete_receive_sa - Delete secure association for receive
831 * @priv: private driver interface data from init()
832 * @sa: secure association
833 * Returns: 0 on success, -1 on failure
834 */
macsec_drv_delete_receive_sa(void * priv,struct receive_sa * sa)835 static int macsec_drv_delete_receive_sa(void *priv, struct receive_sa *sa)
836 {
837 struct macsec_drv_data *drv = priv;
838 struct macsec_genl_ctx *ctx = &drv->ctx;
839 struct nl_msg *msg;
840 struct nlattr *nest;
841 int ret = -1;
842
843 wpa_printf(MSG_DEBUG, "%s -> %d on " SCISTR, __func__, sa->an,
844 SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
845
846 msg = msg_prepare(MACSEC_CMD_DEL_RXSA, ctx, drv->ifi);
847 if (!msg)
848 return ret;
849
850 if (nla_put_rxsc_config(msg, mka_sci_u64(&sa->sc->sci)))
851 goto nla_put_failure;
852
853 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
854 if (!nest)
855 goto nla_put_failure;
856
857 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
858
859 nla_nest_end(msg, nest);
860
861 ret = nl_send_recv(ctx->sk, msg);
862 if (ret < 0) {
863 wpa_printf(MSG_ERROR,
864 DRV_PREFIX "%s: failed to communicate: %d (%s)",
865 __func__, ret, nl_geterror(-ret));
866 }
867
868 nla_put_failure:
869 nlmsg_free(msg);
870 return ret;
871 }
872
873
set_active_rx_sa(const struct macsec_genl_ctx * ctx,int ifindex,u64 sci,unsigned char an,Boolean state)874 static int set_active_rx_sa(const struct macsec_genl_ctx *ctx, int ifindex,
875 u64 sci, unsigned char an, Boolean state)
876 {
877 struct nl_msg *msg;
878 struct nlattr *nest;
879 int ret = -1;
880
881 msg = msg_prepare(MACSEC_CMD_UPD_RXSA, ctx, ifindex);
882 if (!msg)
883 return ret;
884
885 if (nla_put_rxsc_config(msg, sci))
886 goto nla_put_failure;
887
888 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
889 if (!nest)
890 goto nla_put_failure;
891
892 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, an);
893 NLA_PUT_U8(msg, MACSEC_SA_ATTR_ACTIVE, !!state);
894
895 nla_nest_end(msg, nest);
896
897 ret = nl_send_recv(ctx->sk, msg);
898 if (ret < 0)
899 wpa_printf(MSG_ERROR,
900 DRV_PREFIX "%s: failed to communicate: %d (%s)",
901 __func__, ret, nl_geterror(-ret));
902
903 nla_put_failure:
904 nlmsg_free(msg);
905 return ret;
906 }
907
908
909 /**
910 * macsec_drv_enable_receive_sa - Enable the SA for receive
911 * @priv: private driver interface data from init()
912 * @sa: secure association
913 * Returns: 0 on success, -1 on failure
914 */
macsec_drv_enable_receive_sa(void * priv,struct receive_sa * sa)915 static int macsec_drv_enable_receive_sa(void *priv, struct receive_sa *sa)
916 {
917 struct macsec_drv_data *drv = priv;
918 struct macsec_genl_ctx *ctx = &drv->ctx;
919
920 wpa_printf(MSG_DEBUG, "%s -> %d on " SCISTR, __func__, sa->an,
921 SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
922
923 return set_active_rx_sa(ctx, drv->ifi, mka_sci_u64(&sa->sc->sci),
924 sa->an, TRUE);
925 }
926
927
928 /**
929 * macsec_drv_disable_receive_sa - Disable SA for receive
930 * @priv: private driver interface data from init()
931 * @sa: secure association
932 * Returns: 0 on success, -1 on failure
933 */
macsec_drv_disable_receive_sa(void * priv,struct receive_sa * sa)934 static int macsec_drv_disable_receive_sa(void *priv, struct receive_sa *sa)
935 {
936 struct macsec_drv_data *drv = priv;
937 struct macsec_genl_ctx *ctx = &drv->ctx;
938
939 wpa_printf(MSG_DEBUG, "%s -> %d on " SCISTR, __func__, sa->an,
940 SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
941
942 return set_active_rx_sa(ctx, drv->ifi, mka_sci_u64(&sa->sc->sci),
943 sa->an, FALSE);
944 }
945
946
lookup_sc(struct nl_cache * cache,int parent,u64 sci)947 static struct rtnl_link * lookup_sc(struct nl_cache *cache, int parent, u64 sci)
948 {
949 struct rtnl_link *needle;
950 void *match;
951
952 needle = rtnl_link_macsec_alloc();
953 if (!needle)
954 return NULL;
955
956 rtnl_link_set_link(needle, parent);
957 rtnl_link_macsec_set_sci(needle, sci);
958
959 match = nl_cache_find(cache, (struct nl_object *) needle);
960 rtnl_link_put(needle);
961
962 return (struct rtnl_link *) match;
963 }
964
965
966 /**
967 * macsec_drv_create_transmit_sc - Create secure connection for transmit
968 * @priv: private driver interface data from init()
969 * @sc: secure channel
970 * @conf_offset: confidentiality offset
971 * Returns: 0 on success, -1 on failure
972 */
macsec_drv_create_transmit_sc(void * priv,struct transmit_sc * sc,enum confidentiality_offset conf_offset)973 static int macsec_drv_create_transmit_sc(
974 void *priv, struct transmit_sc *sc,
975 enum confidentiality_offset conf_offset)
976 {
977 struct macsec_drv_data *drv = priv;
978 struct rtnl_link *link;
979 char *ifname;
980 u64 sci;
981 int err;
982
983 wpa_printf(MSG_DEBUG, "%s", __func__);
984
985 link = rtnl_link_macsec_alloc();
986 if (!link) {
987 wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't allocate link");
988 return -1;
989 }
990
991 rtnl_link_set_link(link, drv->parent_ifi);
992
993 sci = mka_sci_u64(&sc->sci);
994 rtnl_link_macsec_set_sci(link, sci);
995
996 drv->created_link = TRUE;
997
998 err = rtnl_link_add(drv->sk, link, NLM_F_CREATE);
999 if (err == -NLE_BUSY) {
1000 wpa_printf(MSG_INFO,
1001 DRV_PREFIX "link already exists, using it");
1002 drv->created_link = FALSE;
1003 } else if (err < 0) {
1004 rtnl_link_put(link);
1005 wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't create link: err %d",
1006 err);
1007 return err;
1008 }
1009
1010 rtnl_link_put(link);
1011
1012 nl_cache_refill(drv->sk, drv->link_cache);
1013 link = lookup_sc(drv->link_cache, drv->parent_ifi, sci);
1014 if (!link) {
1015 wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't find link");
1016 return -1;
1017 }
1018
1019 drv->ifi = rtnl_link_get_ifindex(link);
1020 ifname = rtnl_link_get_name(link);
1021 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
1022 rtnl_link_put(link);
1023
1024 drv->link = rtnl_link_macsec_alloc();
1025 if (!drv->link) {
1026 wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't allocate link");
1027 return -1;
1028 }
1029
1030 rtnl_link_set_name(drv->link, drv->ifname);
1031
1032 /* In case some settings have already been done but we couldn't apply
1033 * them. */
1034 return try_commit(drv);
1035 }
1036
1037
1038 /**
1039 * macsec_drv_delete_transmit_sc - Delete secure connection for transmit
1040 * @priv: private driver interface data from init()
1041 * @sc: secure channel
1042 * Returns: 0 on success, -1 on failure
1043 */
macsec_drv_delete_transmit_sc(void * priv,struct transmit_sc * sc)1044 static int macsec_drv_delete_transmit_sc(void *priv, struct transmit_sc *sc)
1045 {
1046 struct macsec_drv_data *drv = priv;
1047 int err;
1048
1049 wpa_printf(MSG_DEBUG, "%s", __func__);
1050
1051 if (!drv->created_link) {
1052 rtnl_link_put(drv->link);
1053 drv->link = NULL;
1054 wpa_printf(MSG_DEBUG, DRV_PREFIX
1055 "we didn't create the link, leave it alone");
1056 return 0;
1057 }
1058
1059 err = rtnl_link_delete(drv->sk, drv->link);
1060 if (err < 0)
1061 wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't delete link");
1062 rtnl_link_put(drv->link);
1063 drv->link = NULL;
1064
1065 return err;
1066 }
1067
1068
1069 /**
1070 * macsec_drv_create_transmit_sa - Create secure association for transmit
1071 * @priv: private driver interface data from init()
1072 * @sa: secure association
1073 * Returns: 0 on success, -1 on failure
1074 */
macsec_drv_create_transmit_sa(void * priv,struct transmit_sa * sa)1075 static int macsec_drv_create_transmit_sa(void *priv, struct transmit_sa *sa)
1076 {
1077 struct macsec_drv_data *drv = priv;
1078 struct macsec_genl_ctx *ctx = &drv->ctx;
1079 struct nl_msg *msg;
1080 struct nlattr *nest;
1081 int ret = -1;
1082
1083 wpa_printf(MSG_DEBUG, "%s -> %d", __func__, sa->an);
1084
1085 msg = msg_prepare(MACSEC_CMD_ADD_TXSA, ctx, drv->ifi);
1086 if (!msg)
1087 return ret;
1088
1089 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
1090 if (!nest)
1091 goto nla_put_failure;
1092
1093 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
1094 NLA_PUT_U32(msg, MACSEC_SA_ATTR_PN, sa->next_pn);
1095 NLA_PUT(msg, MACSEC_SA_ATTR_KEYID, sizeof(sa->pkey->key_identifier),
1096 &sa->pkey->key_identifier);
1097 NLA_PUT(msg, MACSEC_SA_ATTR_KEY, sa->pkey->key_len, sa->pkey->key);
1098 NLA_PUT_U8(msg, MACSEC_SA_ATTR_ACTIVE, sa->enable_transmit);
1099
1100 nla_nest_end(msg, nest);
1101
1102 ret = nl_send_recv(ctx->sk, msg);
1103 if (ret < 0) {
1104 wpa_printf(MSG_ERROR,
1105 DRV_PREFIX "%s: failed to communicate: %d (%s)",
1106 __func__, ret, nl_geterror(-ret));
1107 }
1108
1109 nla_put_failure:
1110 nlmsg_free(msg);
1111 return ret;
1112 }
1113
1114
1115 /**
1116 * macsec_drv_delete_transmit_sa - Delete secure association for transmit
1117 * @priv: private driver interface data from init()
1118 * @sa: secure association
1119 * Returns: 0 on success, -1 on failure
1120 */
macsec_drv_delete_transmit_sa(void * priv,struct transmit_sa * sa)1121 static int macsec_drv_delete_transmit_sa(void *priv, struct transmit_sa *sa)
1122 {
1123 struct macsec_drv_data *drv = priv;
1124 struct macsec_genl_ctx *ctx = &drv->ctx;
1125 struct nl_msg *msg;
1126 struct nlattr *nest;
1127 int ret = -1;
1128
1129 wpa_printf(MSG_DEBUG, "%s -> %d", __func__, sa->an);
1130
1131 msg = msg_prepare(MACSEC_CMD_DEL_TXSA, ctx, drv->ifi);
1132 if (!msg)
1133 return ret;
1134
1135 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
1136 if (!nest)
1137 goto nla_put_failure;
1138
1139 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
1140
1141 nla_nest_end(msg, nest);
1142
1143 ret = nl_send_recv(ctx->sk, msg);
1144 if (ret < 0) {
1145 wpa_printf(MSG_ERROR,
1146 DRV_PREFIX "%s: failed to communicate: %d (%s)",
1147 __func__, ret, nl_geterror(-ret));
1148 }
1149
1150 nla_put_failure:
1151 nlmsg_free(msg);
1152 return ret;
1153 }
1154
1155
set_active_tx_sa(const struct macsec_genl_ctx * ctx,int ifindex,unsigned char an,Boolean state)1156 static int set_active_tx_sa(const struct macsec_genl_ctx *ctx, int ifindex,
1157 unsigned char an, Boolean state)
1158 {
1159 struct nl_msg *msg;
1160 struct nlattr *nest;
1161 int ret = -1;
1162
1163 msg = msg_prepare(MACSEC_CMD_UPD_TXSA, ctx, ifindex);
1164 if (!msg)
1165 return ret;
1166
1167 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
1168 if (!nest)
1169 goto nla_put_failure;
1170
1171 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, an);
1172 NLA_PUT_U8(msg, MACSEC_SA_ATTR_ACTIVE, !!state);
1173
1174 nla_nest_end(msg, nest);
1175
1176 ret = nl_send_recv(ctx->sk, msg);
1177 if (ret < 0) {
1178 wpa_printf(MSG_ERROR,
1179 DRV_PREFIX "%s: failed to communicate: %d (%s)",
1180 __func__, ret, nl_geterror(-ret));
1181 }
1182
1183 nla_put_failure:
1184 nlmsg_free(msg);
1185 return ret;
1186 }
1187
1188
1189 /**
1190 * macsec_drv_enable_transmit_sa - Enable SA for transmit
1191 * @priv: private driver interface data from init()
1192 * @sa: secure association
1193 * Returns: 0 on success, -1 on failure
1194 */
macsec_drv_enable_transmit_sa(void * priv,struct transmit_sa * sa)1195 static int macsec_drv_enable_transmit_sa(void *priv, struct transmit_sa *sa)
1196 {
1197 struct macsec_drv_data *drv = priv;
1198 struct macsec_genl_ctx *ctx = &drv->ctx;
1199 int ret;
1200
1201 wpa_printf(MSG_DEBUG, "%s -> %d", __func__, sa->an);
1202
1203 ret = set_active_tx_sa(ctx, drv->ifi, sa->an, TRUE);
1204 if (ret < 0) {
1205 wpa_printf(MSG_ERROR, DRV_PREFIX "failed to enable txsa");
1206 return ret;
1207 }
1208
1209 drv->encoding_sa_set = TRUE;
1210 drv->encoding_sa = sa->an;
1211
1212 return try_commit(drv);
1213 }
1214
1215
1216 /**
1217 * macsec_drv_disable_transmit_sa - Disable SA for transmit
1218 * @priv: private driver interface data from init()
1219 * @sa: secure association
1220 * Returns: 0 on success, -1 on failure
1221 */
macsec_drv_disable_transmit_sa(void * priv,struct transmit_sa * sa)1222 static int macsec_drv_disable_transmit_sa(void *priv, struct transmit_sa *sa)
1223 {
1224 struct macsec_drv_data *drv = priv;
1225 struct macsec_genl_ctx *ctx = &drv->ctx;
1226
1227 wpa_printf(MSG_DEBUG, "%s -> %d", __func__, sa->an);
1228
1229 return set_active_tx_sa(ctx, drv->ifi, sa->an, FALSE);
1230 }
1231
1232
1233 const struct wpa_driver_ops wpa_driver_macsec_linux_ops = {
1234 .name = "macsec_linux",
1235 .desc = "MACsec Ethernet driver for Linux",
1236 .get_ssid = driver_wired_get_ssid,
1237 .get_bssid = driver_wired_get_bssid,
1238 .get_capa = driver_wired_get_capa,
1239 .init = macsec_drv_wpa_init,
1240 .deinit = macsec_drv_wpa_deinit,
1241
1242 .macsec_init = macsec_drv_macsec_init,
1243 .macsec_deinit = macsec_drv_macsec_deinit,
1244 .macsec_get_capability = macsec_drv_get_capability,
1245 .enable_protect_frames = macsec_drv_enable_protect_frames,
1246 .enable_encrypt = macsec_drv_enable_encrypt,
1247 .set_replay_protect = macsec_drv_set_replay_protect,
1248 .set_current_cipher_suite = macsec_drv_set_current_cipher_suite,
1249 .enable_controlled_port = macsec_drv_enable_controlled_port,
1250 .get_receive_lowest_pn = macsec_drv_get_receive_lowest_pn,
1251 .get_transmit_next_pn = macsec_drv_get_transmit_next_pn,
1252 .set_transmit_next_pn = macsec_drv_set_transmit_next_pn,
1253 .create_receive_sc = macsec_drv_create_receive_sc,
1254 .delete_receive_sc = macsec_drv_delete_receive_sc,
1255 .create_receive_sa = macsec_drv_create_receive_sa,
1256 .delete_receive_sa = macsec_drv_delete_receive_sa,
1257 .enable_receive_sa = macsec_drv_enable_receive_sa,
1258 .disable_receive_sa = macsec_drv_disable_receive_sa,
1259 .create_transmit_sc = macsec_drv_create_transmit_sc,
1260 .delete_transmit_sc = macsec_drv_delete_transmit_sc,
1261 .create_transmit_sa = macsec_drv_create_transmit_sa,
1262 .delete_transmit_sa = macsec_drv_delete_transmit_sa,
1263 .enable_transmit_sa = macsec_drv_enable_transmit_sa,
1264 .disable_transmit_sa = macsec_drv_disable_transmit_sa,
1265 };
1266