• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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->sk)
172 		return 0;
173 
174 	if (!drv->link)
175 		return 0;
176 
177 	if (drv->controlled_port_enabled_set) {
178 		struct rtnl_link *change = rtnl_link_alloc();
179 
180 		wpa_printf(MSG_DEBUG, DRV_PREFIX
181 			   "%s: try_commit controlled_port_enabled=%d",
182 			   drv->ifname, drv->controlled_port_enabled);
183 		if (!change)
184 			return -1;
185 
186 		rtnl_link_set_name(change, drv->ifname);
187 
188 		if (drv->controlled_port_enabled)
189 			rtnl_link_set_flags(change, IFF_UP);
190 		else
191 			rtnl_link_unset_flags(change, IFF_UP);
192 
193 		err = rtnl_link_change(drv->sk, change, change, 0);
194 		if (err < 0)
195 			return err;
196 
197 		rtnl_link_put(change);
198 
199 		drv->controlled_port_enabled_set = FALSE;
200 	}
201 
202 	if (drv->protect_frames_set) {
203 		wpa_printf(MSG_DEBUG, DRV_PREFIX
204 			   "%s: try_commit protect_frames=%d",
205 			   drv->ifname, drv->protect_frames);
206 		rtnl_link_macsec_set_protect(drv->link, drv->protect_frames);
207 	}
208 
209 	if (drv->encrypt_set) {
210 		wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: try_commit encrypt=%d",
211 			   drv->ifname, drv->encrypt);
212 		rtnl_link_macsec_set_encrypt(drv->link, drv->encrypt);
213 	}
214 
215 	if (drv->replay_protect_set) {
216 		wpa_printf(MSG_DEBUG, DRV_PREFIX
217 			   "%s: try_commit replay_protect=%d replay_window=%d",
218 			   drv->ifname, drv->replay_protect,
219 			   drv->replay_window);
220 		rtnl_link_macsec_set_replay_protect(drv->link,
221 						    drv->replay_protect);
222 		if (drv->replay_protect)
223 			rtnl_link_macsec_set_window(drv->link,
224 						    drv->replay_window);
225 	}
226 
227 	if (drv->encoding_sa_set) {
228 		wpa_printf(MSG_DEBUG, DRV_PREFIX
229 			   "%s: try_commit encoding_sa=%d",
230 			   drv->ifname, drv->encoding_sa);
231 		rtnl_link_macsec_set_encoding_sa(drv->link, drv->encoding_sa);
232 	}
233 
234 	err = rtnl_link_add(drv->sk, drv->link, 0);
235 	if (err < 0)
236 		return err;
237 
238 	drv->protect_frames_set = FALSE;
239 	drv->encrypt_set = FALSE;
240 	drv->replay_protect_set = FALSE;
241 
242 	return 0;
243 }
244 
245 
macsec_drv_wpa_deinit(void * priv)246 static void macsec_drv_wpa_deinit(void *priv)
247 {
248 	struct macsec_drv_data *drv = priv;
249 
250 	driver_wired_deinit_common(&drv->common);
251 	os_free(drv);
252 }
253 
254 
macsec_check_macsec(void)255 static int macsec_check_macsec(void)
256 {
257 	struct nl_sock *sk;
258 	int err = -1;
259 
260 	sk = nl_socket_alloc();
261 	if (!sk) {
262 		wpa_printf(MSG_ERROR, DRV_PREFIX "failed to alloc genl socket");
263 		return -1;
264 	}
265 
266 	if (genl_connect(sk) < 0) {
267 		wpa_printf(MSG_ERROR,
268 			   DRV_PREFIX "connection to genl socket failed");
269 		goto out_free;
270 	}
271 
272 	if (genl_ctrl_resolve(sk, "macsec") < 0) {
273 		wpa_printf(MSG_ERROR,
274 			   DRV_PREFIX "genl resolve failed - macsec kernel module not present?");
275 		goto out_free;
276 	}
277 
278 	err = 0;
279 
280 out_free:
281 	nl_socket_free(sk);
282 	return err;
283 }
284 
285 
macsec_drv_wpa_init(void * ctx,const char * ifname)286 static void * macsec_drv_wpa_init(void *ctx, const char *ifname)
287 {
288 	struct macsec_drv_data *drv;
289 
290 	if (macsec_check_macsec() < 0)
291 		return NULL;
292 
293 	drv = os_zalloc(sizeof(*drv));
294 	if (!drv)
295 		return NULL;
296 
297 	if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) {
298 		os_free(drv);
299 		return NULL;
300 	}
301 
302 	return drv;
303 }
304 
305 
macsec_drv_macsec_init(void * priv,struct macsec_init_params * params)306 static int macsec_drv_macsec_init(void *priv, struct macsec_init_params *params)
307 {
308 	struct macsec_drv_data *drv = priv;
309 	int err;
310 
311 	wpa_printf(MSG_DEBUG, "%s", __func__);
312 
313 	drv->sk = nl_socket_alloc();
314 	if (!drv->sk)
315 		return -1;
316 
317 	err = nl_connect(drv->sk, NETLINK_ROUTE);
318 	if (err < 0) {
319 		wpa_printf(MSG_ERROR, DRV_PREFIX
320 			   "Unable to connect NETLINK_ROUTE socket: %s",
321 			   strerror(errno));
322 		goto sock;
323 	}
324 
325 	err = rtnl_link_alloc_cache(drv->sk, AF_UNSPEC, &drv->link_cache);
326 	if (err < 0) {
327 		wpa_printf(MSG_ERROR, DRV_PREFIX "Unable to get link cache: %s",
328 			   strerror(errno));
329 		goto sock;
330 	}
331 
332 	drv->parent_ifi = rtnl_link_name2i(drv->link_cache, drv->common.ifname);
333 	if (drv->parent_ifi == 0) {
334 		wpa_printf(MSG_ERROR, DRV_PREFIX
335 			   "couldn't find ifindex for interface %s",
336 			   drv->common.ifname);
337 		goto cache;
338 	}
339 	wpa_printf(MSG_DEBUG, DRV_PREFIX "ifname=%s parent_ifi=%d",
340 		   drv->common.ifname, drv->parent_ifi);
341 
342 	err = init_genl_ctx(drv);
343 	if (err < 0)
344 		goto cache;
345 
346 	return 0;
347 
348 cache:
349 	nl_cache_free(drv->link_cache);
350 	drv->link_cache = NULL;
351 sock:
352 	nl_socket_free(drv->sk);
353 	drv->sk = NULL;
354 	return -1;
355 }
356 
357 
macsec_drv_macsec_deinit(void * priv)358 static int macsec_drv_macsec_deinit(void *priv)
359 {
360 	struct macsec_drv_data *drv = priv;
361 
362 	wpa_printf(MSG_DEBUG, "%s", __func__);
363 
364 	if (drv->sk)
365 		nl_socket_free(drv->sk);
366 	drv->sk = NULL;
367 
368 	if (drv->link_cache)
369 		nl_cache_free(drv->link_cache);
370 	drv->link_cache = NULL;
371 
372 	if (drv->ctx.sk)
373 		nl_socket_free(drv->ctx.sk);
374 
375 	return 0;
376 }
377 
378 
macsec_drv_get_capability(void * priv,enum macsec_cap * cap)379 static int macsec_drv_get_capability(void *priv, enum macsec_cap *cap)
380 {
381 	wpa_printf(MSG_DEBUG, "%s", __func__);
382 
383 	*cap = MACSEC_CAP_INTEG_AND_CONF;
384 
385 	return 0;
386 }
387 
388 
389 /**
390  * macsec_drv_enable_protect_frames - Set protect frames status
391  * @priv: Private driver interface data
392  * @enabled: TRUE = protect frames enabled
393  *           FALSE = protect frames disabled
394  * Returns: 0 on success, -1 on failure (or if not supported)
395  */
macsec_drv_enable_protect_frames(void * priv,Boolean enabled)396 static int macsec_drv_enable_protect_frames(void *priv, Boolean enabled)
397 {
398 	struct macsec_drv_data *drv = priv;
399 
400 	wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE");
401 
402 	drv->protect_frames_set = TRUE;
403 	drv->protect_frames = enabled;
404 
405 	return try_commit(drv);
406 }
407 
408 
409 /**
410  * macsec_drv_enable_encrypt - Set protect frames status
411  * @priv: Private driver interface data
412  * @enabled: TRUE = protect frames enabled
413  *           FALSE = protect frames disabled
414  * Returns: 0 on success, -1 on failure (or if not supported)
415  */
macsec_drv_enable_encrypt(void * priv,Boolean enabled)416 static int macsec_drv_enable_encrypt(void *priv, Boolean enabled)
417 {
418 	struct macsec_drv_data *drv = priv;
419 
420 	wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE");
421 
422 	drv->encrypt_set = TRUE;
423 	drv->encrypt = enabled;
424 
425 	return try_commit(drv);
426 }
427 
428 
429 /**
430  * macsec_drv_set_replay_protect - Set replay protect status and window size
431  * @priv: Private driver interface data
432  * @enabled: TRUE = replay protect enabled
433  *           FALSE = replay protect disabled
434  * @window: replay window size, valid only when replay protect enabled
435  * Returns: 0 on success, -1 on failure (or if not supported)
436  */
macsec_drv_set_replay_protect(void * priv,Boolean enabled,u32 window)437 static int macsec_drv_set_replay_protect(void *priv, Boolean enabled,
438 					 u32 window)
439 {
440 	struct macsec_drv_data *drv = priv;
441 
442 	wpa_printf(MSG_DEBUG, "%s -> %s, %u", __func__,
443 		   enabled ? "TRUE" : "FALSE", window);
444 
445 	drv->replay_protect_set = TRUE;
446 	drv->replay_protect = enabled;
447 	if (enabled)
448 		drv->replay_window = window;
449 
450 	return try_commit(drv);
451 }
452 
453 
454 /**
455  * macsec_drv_set_current_cipher_suite - Set current cipher suite
456  * @priv: Private driver interface data
457  * @cs: EUI64 identifier
458  * Returns: 0 on success, -1 on failure (or if not supported)
459  */
macsec_drv_set_current_cipher_suite(void * priv,u64 cs)460 static int macsec_drv_set_current_cipher_suite(void *priv, u64 cs)
461 {
462 	wpa_printf(MSG_DEBUG, "%s -> %016" PRIx64, __func__, cs);
463 	return 0;
464 }
465 
466 
467 /**
468  * macsec_drv_enable_controlled_port - Set controlled port status
469  * @priv: Private driver interface data
470  * @enabled: TRUE = controlled port enabled
471  *           FALSE = controlled port disabled
472  * Returns: 0 on success, -1 on failure (or if not supported)
473  */
macsec_drv_enable_controlled_port(void * priv,Boolean enabled)474 static int macsec_drv_enable_controlled_port(void *priv, Boolean enabled)
475 {
476 	struct macsec_drv_data *drv = priv;
477 
478 	wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE");
479 
480 	drv->controlled_port_enabled = enabled;
481 	drv->controlled_port_enabled_set = TRUE;
482 
483 	return try_commit(drv);
484 }
485 
486 
487 static struct nla_policy sa_policy[MACSEC_SA_ATTR_MAX + 1] = {
488 	[MACSEC_SA_ATTR_AN] = { .type = NLA_U8 },
489 	[MACSEC_SA_ATTR_ACTIVE] = { .type = NLA_U8 },
490 	[MACSEC_SA_ATTR_PN] = { .type = NLA_U32 },
491 	[MACSEC_SA_ATTR_KEYID] = { .type = NLA_BINARY },
492 };
493 
494 static struct nla_policy sc_policy[MACSEC_RXSC_ATTR_MAX + 1] = {
495 	[MACSEC_RXSC_ATTR_SCI] = { .type = NLA_U64 },
496 	[MACSEC_RXSC_ATTR_ACTIVE] = { .type = NLA_U8 },
497 	[MACSEC_RXSC_ATTR_SA_LIST] = { .type = NLA_NESTED },
498 };
499 
500 static struct nla_policy main_policy[MACSEC_ATTR_MAX + 1] = {
501 	[MACSEC_ATTR_IFINDEX] = { .type = NLA_U32 },
502 	[MACSEC_ATTR_SECY] = { .type = NLA_NESTED },
503 	[MACSEC_ATTR_TXSA_LIST] = { .type = NLA_NESTED },
504 	[MACSEC_ATTR_RXSC_LIST] = { .type = NLA_NESTED },
505 };
506 
dump_callback(struct nl_msg * msg,void * argp)507 static int dump_callback(struct nl_msg *msg, void *argp)
508 {
509 	struct nlmsghdr *ret_hdr = nlmsg_hdr(msg);
510 	struct nlattr *tb_msg[MACSEC_ATTR_MAX + 1];
511 	struct cb_arg *arg = (struct cb_arg *) argp;
512 	struct genlmsghdr *gnlh = (struct genlmsghdr *) nlmsg_data(ret_hdr);
513 	int err;
514 
515 	if (ret_hdr->nlmsg_type != arg->drv->ctx.macsec_genl_id)
516 		return 0;
517 
518 	err = nla_parse(tb_msg, MACSEC_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
519 			genlmsg_attrlen(gnlh, 0), main_policy);
520 	if (err < 0)
521 		return 0;
522 
523 	if (!tb_msg[MACSEC_ATTR_IFINDEX])
524 		return 0;
525 
526 	if (nla_get_u32(tb_msg[MACSEC_ATTR_IFINDEX]) != (u32) arg->ifindex)
527 		return 0;
528 
529 	if (arg->txsa < 4 && !tb_msg[MACSEC_ATTR_TXSA_LIST]) {
530 		return 0;
531 	} else if (arg->txsa < 4) {
532 		struct nlattr *nla;
533 		int rem;
534 
535 		nla_for_each_nested(nla, tb_msg[MACSEC_ATTR_TXSA_LIST], rem) {
536 			struct nlattr *tb[MACSEC_SA_ATTR_MAX + 1];
537 
538 			err = nla_parse_nested(tb, MACSEC_SA_ATTR_MAX, nla,
539 					       sa_policy);
540 			if (err < 0)
541 				continue;
542 			if (!tb[MACSEC_SA_ATTR_AN])
543 				continue;
544 			if (nla_get_u8(tb[MACSEC_SA_ATTR_AN]) != arg->txsa)
545 				continue;
546 			if (!tb[MACSEC_SA_ATTR_PN])
547 				return 0;
548 			*arg->pn = nla_get_u32(tb[MACSEC_SA_ATTR_PN]);
549 			return 0;
550 		}
551 
552 		return 0;
553 	}
554 
555 	if (arg->rxsci == UNUSED_SCI)
556 		return 0;
557 
558 	if (tb_msg[MACSEC_ATTR_RXSC_LIST]) {
559 		struct nlattr *nla;
560 		int rem;
561 
562 		nla_for_each_nested(nla, tb_msg[MACSEC_ATTR_RXSC_LIST], rem) {
563 			struct nlattr *tb[MACSEC_RXSC_ATTR_MAX + 1];
564 
565 			err = nla_parse_nested(tb, MACSEC_RXSC_ATTR_MAX, nla,
566 					       sc_policy);
567 			if (err < 0)
568 				return 0;
569 			if (!tb[MACSEC_RXSC_ATTR_SCI])
570 				continue;
571 			if (nla_get_u64(tb[MACSEC_RXSC_ATTR_SCI]) != arg->rxsci)
572 				continue;
573 			if (!tb[MACSEC_RXSC_ATTR_SA_LIST])
574 				return 0;
575 
576 			nla_for_each_nested(nla, tb[MACSEC_RXSC_ATTR_SA_LIST],
577 					    rem) {
578 				struct nlattr *tb_sa[MACSEC_SA_ATTR_MAX + 1];
579 
580 				err = nla_parse_nested(tb_sa,
581 						       MACSEC_SA_ATTR_MAX, nla,
582 						       sa_policy);
583 				if (err < 0)
584 					continue;
585 				if (!tb_sa[MACSEC_SA_ATTR_AN])
586 					continue;
587 				if (nla_get_u8(tb_sa[MACSEC_SA_ATTR_AN]) !=
588 				    arg->rxsa)
589 					continue;
590 				if (!tb_sa[MACSEC_SA_ATTR_PN])
591 					return 0;
592 				*arg->pn =
593 					nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]);
594 
595 				return 0;
596 			}
597 
598 			return 0;
599 		}
600 
601 		return 0;
602 	}
603 
604 	return 0;
605 }
606 
607 
nl_send_recv(struct nl_sock * sk,struct nl_msg * msg)608 static int nl_send_recv(struct nl_sock *sk, struct nl_msg *msg)
609 {
610 	int ret;
611 
612 	ret = nl_send_auto_complete(sk, msg);
613 	if (ret < 0) {
614 		wpa_printf(MSG_ERROR, DRV_PREFIX "%s: failed to send: %d (%s)",
615 			   __func__, ret, nl_geterror(-ret));
616 		return ret;
617 	}
618 
619 	ret = nl_recvmsgs_default(sk);
620 	if (ret < 0) {
621 		wpa_printf(MSG_ERROR, DRV_PREFIX "%s: failed to recv: %d (%s)",
622 			   __func__, ret, nl_geterror(-ret));
623 	}
624 
625 	return ret;
626 }
627 
628 
do_dump(struct macsec_drv_data * drv,u8 txsa,u64 rxsci,u8 rxsa,u32 * pn)629 static int do_dump(struct macsec_drv_data *drv, u8 txsa, u64 rxsci, u8 rxsa,
630 		   u32 *pn)
631 {
632 	struct macsec_genl_ctx *ctx = &drv->ctx;
633 	struct nl_msg *msg;
634 	int ret = 1;
635 
636 	ctx->cb_arg.ifindex = drv->ifi;
637 	ctx->cb_arg.rxsci = rxsci;
638 	ctx->cb_arg.rxsa = rxsa;
639 	ctx->cb_arg.txsa = txsa;
640 	ctx->cb_arg.pn = pn;
641 
642 	msg = nlmsg_alloc();
643 	if (!msg) {
644 		wpa_printf(MSG_ERROR, DRV_PREFIX "%s: failed to alloc message",
645 			   __func__);
646 		return 1;
647 	}
648 
649 	if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, ctx->macsec_genl_id, 0,
650 			 NLM_F_DUMP, MACSEC_CMD_GET_TXSC, 0)) {
651 		wpa_printf(MSG_ERROR, DRV_PREFIX "%s: failed to put header",
652 			   __func__);
653 		goto out_free_msg;
654 	}
655 
656 	ret = nl_send_recv(ctx->sk, msg);
657 	if (ret < 0)
658 		wpa_printf(MSG_ERROR,
659 			   DRV_PREFIX "failed to communicate: %d (%s)",
660 			   ret, nl_geterror(-ret));
661 
662 	ctx->cb_arg.pn = NULL;
663 
664 out_free_msg:
665 	nlmsg_free(msg);
666 	return ret;
667 }
668 
669 
670 /**
671  * macsec_drv_get_receive_lowest_pn - Get receive lowest PN
672  * @priv: Private driver interface data
673  * @sa: secure association
674  * Returns: 0 on success, -1 on failure (or if not supported)
675  */
macsec_drv_get_receive_lowest_pn(void * priv,struct receive_sa * sa)676 static int macsec_drv_get_receive_lowest_pn(void *priv, struct receive_sa *sa)
677 {
678 	struct macsec_drv_data *drv = priv;
679 	int err;
680 
681 	wpa_printf(MSG_DEBUG, DRV_PREFIX "%s", __func__);
682 
683 	err = do_dump(drv, 0xff, mka_sci_u64(&sa->sc->sci), sa->an,
684 		      &sa->lowest_pn);
685 	wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: result %d", __func__,
686 		   sa->lowest_pn);
687 
688 	return err;
689 }
690 
691 
692 /**
693  * macsec_drv_set_receive_lowest_pn - Set receive lowest PN
694  * @priv: Private driver interface data
695  * @sa: secure association
696  * Returns: 0 on success, -1 on failure (or if not supported)
697  */
macsec_drv_set_receive_lowest_pn(void * priv,struct receive_sa * sa)698 static int macsec_drv_set_receive_lowest_pn(void *priv, struct receive_sa *sa)
699 {
700 	struct macsec_drv_data *drv = priv;
701 	struct macsec_genl_ctx *ctx = &drv->ctx;
702 	struct nl_msg *msg;
703 	struct nlattr *nest;
704 	int ret = -1;
705 
706 	wpa_printf(MSG_DEBUG,
707 		   DRV_PREFIX "%s: set_receive_lowest_pn -> %d: %d",
708 		   drv->ifname, sa->an, sa->next_pn);
709 
710 	msg = msg_prepare(MACSEC_CMD_UPD_RXSA, ctx, drv->ifi);
711 	if (!msg)
712 		return ret;
713 
714 	nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
715 	if (!nest)
716 		goto nla_put_failure;
717 
718 	NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
719 	NLA_PUT_U32(msg, MACSEC_SA_ATTR_PN, sa->next_pn);
720 
721 	nla_nest_end(msg, nest);
722 
723 	ret = nl_send_recv(ctx->sk, msg);
724 	if (ret < 0) {
725 		wpa_printf(MSG_ERROR,
726 			   DRV_PREFIX "failed to communicate: %d (%s)",
727 			   ret, nl_geterror(-ret));
728 	}
729 
730 nla_put_failure:
731 	nlmsg_free(msg);
732 	return ret;
733 }
734 
735 
736 /**
737  * macsec_drv_get_transmit_next_pn - Get transmit next PN
738  * @priv: Private driver interface data
739  * @sa: secure association
740  * Returns: 0 on success, -1 on failure (or if not supported)
741  */
macsec_drv_get_transmit_next_pn(void * priv,struct transmit_sa * sa)742 static int macsec_drv_get_transmit_next_pn(void *priv, struct transmit_sa *sa)
743 {
744 	struct macsec_drv_data *drv = priv;
745 	int err;
746 
747 	wpa_printf(MSG_DEBUG, "%s", __func__);
748 
749 	err = do_dump(drv, sa->an, UNUSED_SCI, 0xff, &sa->next_pn);
750 	wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: err %d result %d", __func__, err,
751 		   sa->next_pn);
752 	return err;
753 }
754 
755 
756 /**
757  * macsec_drv_set_transmit_next_pn - Set transmit next pn
758  * @priv: Private driver interface data
759  * @sa: secure association
760  * Returns: 0 on success, -1 on failure (or if not supported)
761  */
macsec_drv_set_transmit_next_pn(void * priv,struct transmit_sa * sa)762 static int macsec_drv_set_transmit_next_pn(void *priv, struct transmit_sa *sa)
763 {
764 	struct macsec_drv_data *drv = priv;
765 	struct macsec_genl_ctx *ctx = &drv->ctx;
766 	struct nl_msg *msg;
767 	struct nlattr *nest;
768 	int ret = -1;
769 
770 	wpa_printf(MSG_DEBUG, "%s -> %d: %d", __func__, sa->an, sa->next_pn);
771 
772 	msg = msg_prepare(MACSEC_CMD_UPD_TXSA, ctx, drv->ifi);
773 	if (!msg)
774 		return ret;
775 
776 	nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
777 	if (!nest)
778 		goto nla_put_failure;
779 
780 	NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
781 	NLA_PUT_U32(msg, MACSEC_SA_ATTR_PN, sa->next_pn);
782 
783 	nla_nest_end(msg, nest);
784 
785 	ret = nl_send_recv(ctx->sk, msg);
786 	if (ret < 0) {
787 		wpa_printf(MSG_ERROR,
788 			   DRV_PREFIX "failed to communicate: %d (%s)",
789 			   ret, nl_geterror(-ret));
790 	}
791 
792 nla_put_failure:
793 	nlmsg_free(msg);
794 	return ret;
795 }
796 
797 
798 #define SCISTR MACSTR "::%hx"
799 #define SCI2STR(addr, port) MAC2STR(addr), htons(port)
800 
801 /**
802  * macsec_drv_create_receive_sc - Create secure channel for receiving
803  * @priv: Private driver interface data
804  * @sc: secure channel
805  * @sci_addr: secure channel identifier - address
806  * @sci_port: secure channel identifier - port
807  * @conf_offset: confidentiality offset (0, 30, or 50)
808  * @validation: frame validation policy (0 = Disabled, 1 = Checked,
809  *	2 = Strict)
810  * Returns: 0 on success, -1 on failure (or if not supported)
811  */
macsec_drv_create_receive_sc(void * priv,struct receive_sc * sc,unsigned int conf_offset,int validation)812 static int macsec_drv_create_receive_sc(void *priv, struct receive_sc *sc,
813 					unsigned int conf_offset,
814 					int validation)
815 {
816 	struct macsec_drv_data *drv = priv;
817 	struct macsec_genl_ctx *ctx = &drv->ctx;
818 	struct nl_msg *msg;
819 	int ret = -1;
820 
821 	wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: create_receive_sc -> " SCISTR
822 		   " (conf_offset=%u validation=%d)",
823 		   drv->ifname, SCI2STR(sc->sci.addr, sc->sci.port),
824 		   conf_offset, validation);
825 
826 	msg = msg_prepare(MACSEC_CMD_ADD_RXSC, ctx, drv->ifi);
827 	if (!msg)
828 		return ret;
829 
830 	if (nla_put_rxsc_config(msg, mka_sci_u64(&sc->sci)))
831 		goto nla_put_failure;
832 
833 	ret = nl_send_recv(ctx->sk, msg);
834 	if (ret < 0) {
835 		wpa_printf(MSG_ERROR,
836 			   DRV_PREFIX "%s: failed to communicate: %d (%s)",
837 			   __func__, ret, nl_geterror(-ret));
838 	}
839 
840 nla_put_failure:
841 	nlmsg_free(msg);
842 	return ret;
843 }
844 
845 
846 /**
847  * macsec_drv_delete_receive_sc - Delete secure connection for receiving
848  * @priv: private driver interface data from init()
849  * @sc: secure channel
850  * Returns: 0 on success, -1 on failure
851  */
macsec_drv_delete_receive_sc(void * priv,struct receive_sc * sc)852 static int macsec_drv_delete_receive_sc(void *priv, struct receive_sc *sc)
853 {
854 	struct macsec_drv_data *drv = priv;
855 	struct macsec_genl_ctx *ctx = &drv->ctx;
856 	struct nl_msg *msg;
857 	int ret = -1;
858 
859 	wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: delete_receive_sc -> " SCISTR,
860 		   drv->ifname, SCI2STR(sc->sci.addr, sc->sci.port));
861 
862 	msg = msg_prepare(MACSEC_CMD_DEL_RXSC, ctx, drv->ifi);
863 	if (!msg)
864 		return ret;
865 
866 	if (nla_put_rxsc_config(msg, mka_sci_u64(&sc->sci)))
867 		goto nla_put_failure;
868 
869 	ret = nl_send_recv(ctx->sk, msg);
870 	if (ret < 0) {
871 		wpa_printf(MSG_ERROR,
872 			   DRV_PREFIX "%s: failed to communicate: %d (%s)",
873 			   __func__, ret, nl_geterror(-ret));
874 	}
875 
876 nla_put_failure:
877 	nlmsg_free(msg);
878 	return ret;
879 }
880 
881 
882 /**
883  * macsec_drv_create_receive_sa - Create secure association for receive
884  * @priv: private driver interface data from init()
885  * @sa: secure association
886  * Returns: 0 on success, -1 on failure
887  */
macsec_drv_create_receive_sa(void * priv,struct receive_sa * sa)888 static int macsec_drv_create_receive_sa(void *priv, struct receive_sa *sa)
889 {
890 	struct macsec_drv_data *drv = priv;
891 	struct macsec_genl_ctx *ctx = &drv->ctx;
892 	struct nl_msg *msg;
893 	struct nlattr *nest;
894 	int ret = -1;
895 
896 	wpa_printf(MSG_DEBUG,
897 		   DRV_PREFIX "%s: create_receive_sa -> %d on " SCISTR
898 		   " (enable_receive=%d next_pn=%u)",
899 		   drv->ifname, sa->an,
900 		   SCI2STR(sa->sc->sci.addr, sa->sc->sci.port),
901 		   sa->enable_receive, sa->next_pn);
902 	wpa_hexdump(MSG_DEBUG, DRV_PREFIX "SA keyid",
903 		    &sa->pkey->key_identifier,
904 		    sizeof(sa->pkey->key_identifier));
905 	wpa_hexdump_key(MSG_DEBUG, DRV_PREFIX "SA key",
906 			sa->pkey->key, sa->pkey->key_len);
907 
908 	msg = msg_prepare(MACSEC_CMD_ADD_RXSA, ctx, drv->ifi);
909 	if (!msg)
910 		return ret;
911 
912 	if (nla_put_rxsc_config(msg, mka_sci_u64(&sa->sc->sci)))
913 		goto nla_put_failure;
914 
915 	nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
916 	if (!nest)
917 		goto nla_put_failure;
918 
919 	NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
920 	NLA_PUT_U8(msg, MACSEC_SA_ATTR_ACTIVE, sa->enable_receive);
921 	NLA_PUT_U32(msg, MACSEC_SA_ATTR_PN, sa->next_pn);
922 	NLA_PUT(msg, MACSEC_SA_ATTR_KEYID, sizeof(sa->pkey->key_identifier),
923 		&sa->pkey->key_identifier);
924 	NLA_PUT(msg, MACSEC_SA_ATTR_KEY, sa->pkey->key_len, sa->pkey->key);
925 
926 	nla_nest_end(msg, nest);
927 
928 	ret = nl_send_recv(ctx->sk, msg);
929 	if (ret < 0) {
930 		wpa_printf(MSG_ERROR,
931 			   DRV_PREFIX "%s: failed to communicate: %d (%s)",
932 			   __func__, ret, nl_geterror(-ret));
933 	}
934 
935 nla_put_failure:
936 	nlmsg_free(msg);
937 	return ret;
938 }
939 
940 
941 /**
942  * macsec_drv_delete_receive_sa - Delete secure association for receive
943  * @priv: private driver interface data from init()
944  * @sa: secure association
945  * Returns: 0 on success, -1 on failure
946  */
macsec_drv_delete_receive_sa(void * priv,struct receive_sa * sa)947 static int macsec_drv_delete_receive_sa(void *priv, struct receive_sa *sa)
948 {
949 	struct macsec_drv_data *drv = priv;
950 	struct macsec_genl_ctx *ctx = &drv->ctx;
951 	struct nl_msg *msg;
952 	struct nlattr *nest;
953 	int ret = -1;
954 
955 	wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: delete_receive_sa -> %d on "
956 		   SCISTR, drv->ifname, sa->an,
957 		   SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
958 
959 	msg = msg_prepare(MACSEC_CMD_DEL_RXSA, ctx, drv->ifi);
960 	if (!msg)
961 		return ret;
962 
963 	if (nla_put_rxsc_config(msg, mka_sci_u64(&sa->sc->sci)))
964 		goto nla_put_failure;
965 
966 	nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
967 	if (!nest)
968 		goto nla_put_failure;
969 
970 	NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
971 
972 	nla_nest_end(msg, nest);
973 
974 	ret = nl_send_recv(ctx->sk, msg);
975 	if (ret < 0) {
976 		wpa_printf(MSG_ERROR,
977 			   DRV_PREFIX "%s: failed to communicate: %d (%s)",
978 			   __func__, ret, nl_geterror(-ret));
979 	}
980 
981 nla_put_failure:
982 	nlmsg_free(msg);
983 	return ret;
984 }
985 
986 
set_active_rx_sa(const struct macsec_genl_ctx * ctx,int ifindex,u64 sci,unsigned char an,Boolean state)987 static int set_active_rx_sa(const struct macsec_genl_ctx *ctx, int ifindex,
988 			    u64 sci, unsigned char an, Boolean state)
989 {
990 	struct nl_msg *msg;
991 	struct nlattr *nest;
992 	int ret = -1;
993 
994 	msg = msg_prepare(MACSEC_CMD_UPD_RXSA, ctx, ifindex);
995 	if (!msg)
996 		return ret;
997 
998 	if (nla_put_rxsc_config(msg, sci))
999 		goto nla_put_failure;
1000 
1001 	nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
1002 	if (!nest)
1003 		goto nla_put_failure;
1004 
1005 	NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, an);
1006 	NLA_PUT_U8(msg, MACSEC_SA_ATTR_ACTIVE, !!state);
1007 
1008 	nla_nest_end(msg, nest);
1009 
1010 	ret = nl_send_recv(ctx->sk, msg);
1011 	if (ret < 0)
1012 		wpa_printf(MSG_ERROR,
1013 			   DRV_PREFIX "%s: failed to communicate: %d (%s)",
1014 			   __func__, ret, nl_geterror(-ret));
1015 
1016 nla_put_failure:
1017 	nlmsg_free(msg);
1018 	return ret;
1019 }
1020 
1021 
1022 /**
1023  * macsec_drv_enable_receive_sa - Enable the SA for receive
1024  * @priv: private driver interface data from init()
1025  * @sa: secure association
1026  * Returns: 0 on success, -1 on failure
1027  */
macsec_drv_enable_receive_sa(void * priv,struct receive_sa * sa)1028 static int macsec_drv_enable_receive_sa(void *priv, struct receive_sa *sa)
1029 {
1030 	struct macsec_drv_data *drv = priv;
1031 	struct macsec_genl_ctx *ctx = &drv->ctx;
1032 
1033 	wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: enable_receive_sa -> %d on "
1034 		   SCISTR, drv->ifname, sa->an,
1035 		   SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
1036 
1037 	return set_active_rx_sa(ctx, drv->ifi, mka_sci_u64(&sa->sc->sci),
1038 				sa->an, TRUE);
1039 }
1040 
1041 
1042 /**
1043  * macsec_drv_disable_receive_sa - Disable SA for receive
1044  * @priv: private driver interface data from init()
1045  * @sa: secure association
1046  * Returns: 0 on success, -1 on failure
1047  */
macsec_drv_disable_receive_sa(void * priv,struct receive_sa * sa)1048 static int macsec_drv_disable_receive_sa(void *priv, struct receive_sa *sa)
1049 {
1050 	struct macsec_drv_data *drv = priv;
1051 	struct macsec_genl_ctx *ctx = &drv->ctx;
1052 
1053 	wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: disable_receive_sa -> %d on "
1054 		   SCISTR, drv->ifname, sa->an,
1055 		   SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
1056 
1057 	return set_active_rx_sa(ctx, drv->ifi, mka_sci_u64(&sa->sc->sci),
1058 				sa->an, FALSE);
1059 }
1060 
1061 
lookup_sc(struct nl_cache * cache,int parent,u64 sci)1062 static struct rtnl_link * lookup_sc(struct nl_cache *cache, int parent, u64 sci)
1063 {
1064 	struct rtnl_link *needle;
1065 	void *match;
1066 
1067 	needle = rtnl_link_macsec_alloc();
1068 	if (!needle)
1069 		return NULL;
1070 
1071 	rtnl_link_set_link(needle, parent);
1072 	rtnl_link_macsec_set_sci(needle, sci);
1073 
1074 	match = nl_cache_find(cache, (struct nl_object *) needle);
1075 	rtnl_link_put(needle);
1076 
1077 	return (struct rtnl_link *) match;
1078 }
1079 
1080 
1081 /**
1082  * macsec_drv_create_transmit_sc - Create secure connection for transmit
1083  * @priv: private driver interface data from init()
1084  * @sc: secure channel
1085  * @conf_offset: confidentiality offset
1086  * Returns: 0 on success, -1 on failure
1087  */
macsec_drv_create_transmit_sc(void * priv,struct transmit_sc * sc,unsigned int conf_offset)1088 static int macsec_drv_create_transmit_sc(
1089 	void *priv, struct transmit_sc *sc,
1090 	unsigned int conf_offset)
1091 {
1092 	struct macsec_drv_data *drv = priv;
1093 	struct rtnl_link *link;
1094 	char *ifname;
1095 	u64 sci;
1096 	int err;
1097 
1098 	wpa_printf(MSG_DEBUG, DRV_PREFIX
1099 		   "%s: create_transmit_sc -> " SCISTR " (conf_offset=%d)",
1100 		   drv->common.ifname, SCI2STR(sc->sci.addr, sc->sci.port),
1101 		   conf_offset);
1102 
1103 	if (!drv->sk) {
1104 		wpa_printf(MSG_ERROR, DRV_PREFIX "NULL rtnl socket");
1105 		return -1;
1106 	}
1107 
1108 	link = rtnl_link_macsec_alloc();
1109 	if (!link) {
1110 		wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't allocate link");
1111 		return -1;
1112 	}
1113 
1114 	rtnl_link_set_link(link, drv->parent_ifi);
1115 
1116 	sci = mka_sci_u64(&sc->sci);
1117 	rtnl_link_macsec_set_sci(link, sci);
1118 
1119 	drv->created_link = TRUE;
1120 
1121 	err = rtnl_link_add(drv->sk, link, NLM_F_CREATE);
1122 	if (err == -NLE_BUSY) {
1123 		wpa_printf(MSG_INFO,
1124 			   DRV_PREFIX "link already exists, using it");
1125 		drv->created_link = FALSE;
1126 	} else if (err < 0) {
1127 		rtnl_link_put(link);
1128 		wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't create link: err %d",
1129 			   err);
1130 		return err;
1131 	}
1132 
1133 	rtnl_link_put(link);
1134 
1135 	nl_cache_refill(drv->sk, drv->link_cache);
1136 	link = lookup_sc(drv->link_cache, drv->parent_ifi, sci);
1137 	if (!link) {
1138 		wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't find link");
1139 		return -1;
1140 	}
1141 
1142 	drv->ifi = rtnl_link_get_ifindex(link);
1143 	ifname = rtnl_link_get_name(link);
1144 	wpa_printf(MSG_DEBUG,
1145 		   DRV_PREFIX "%s: create_transmit_sc: ifi=%d ifname=%s",
1146 		   drv->common.ifname, drv->ifi, ifname);
1147 	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
1148 	rtnl_link_put(link);
1149 
1150 	drv->link = rtnl_link_macsec_alloc();
1151 	if (!drv->link) {
1152 		wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't allocate link");
1153 		return -1;
1154 	}
1155 
1156 	rtnl_link_set_name(drv->link, drv->ifname);
1157 
1158 	/* In case some settings have already been done but we couldn't apply
1159 	 * them. */
1160 	return try_commit(drv);
1161 }
1162 
1163 
1164 /**
1165  * macsec_drv_delete_transmit_sc - Delete secure connection for transmit
1166  * @priv: private driver interface data from init()
1167  * @sc: secure channel
1168  * Returns: 0 on success, -1 on failure
1169  */
macsec_drv_delete_transmit_sc(void * priv,struct transmit_sc * sc)1170 static int macsec_drv_delete_transmit_sc(void *priv, struct transmit_sc *sc)
1171 {
1172 	struct macsec_drv_data *drv = priv;
1173 	int err;
1174 
1175 	wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: delete_transmit_sc -> " SCISTR,
1176 		   drv->ifname, SCI2STR(sc->sci.addr, sc->sci.port));
1177 
1178 	if (!drv->sk)
1179 		return 0;
1180 
1181 	if (!drv->created_link) {
1182 		rtnl_link_put(drv->link);
1183 		drv->link = NULL;
1184 		wpa_printf(MSG_DEBUG, DRV_PREFIX
1185 			   "we didn't create the link, leave it alone");
1186 		return 0;
1187 	}
1188 
1189 	err = rtnl_link_delete(drv->sk, drv->link);
1190 	if (err < 0)
1191 		wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't delete link");
1192 	rtnl_link_put(drv->link);
1193 	drv->link = NULL;
1194 
1195 	return err;
1196 }
1197 
1198 
1199 /**
1200  * macsec_drv_create_transmit_sa - Create secure association for transmit
1201  * @priv: private driver interface data from init()
1202  * @sa: secure association
1203  * Returns: 0 on success, -1 on failure
1204  */
macsec_drv_create_transmit_sa(void * priv,struct transmit_sa * sa)1205 static int macsec_drv_create_transmit_sa(void *priv, struct transmit_sa *sa)
1206 {
1207 	struct macsec_drv_data *drv = priv;
1208 	struct macsec_genl_ctx *ctx = &drv->ctx;
1209 	struct nl_msg *msg;
1210 	struct nlattr *nest;
1211 	int ret = -1;
1212 
1213 	wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: create_transmit_sa -> %d on "
1214 		   SCISTR " (enable_transmit=%d next_pn=%u)",
1215 		   drv->ifname, sa->an,
1216 		   SCI2STR(sa->sc->sci.addr, sa->sc->sci.port),
1217 		   sa->enable_transmit, sa->next_pn);
1218 	wpa_hexdump(MSG_DEBUG, DRV_PREFIX "SA keyid",
1219 		    &sa->pkey->key_identifier,
1220 		    sizeof(sa->pkey->key_identifier));
1221 	wpa_hexdump_key(MSG_DEBUG, DRV_PREFIX "SA key",
1222 			sa->pkey->key, sa->pkey->key_len);
1223 
1224 	msg = msg_prepare(MACSEC_CMD_ADD_TXSA, ctx, drv->ifi);
1225 	if (!msg)
1226 		return ret;
1227 
1228 	nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
1229 	if (!nest)
1230 		goto nla_put_failure;
1231 
1232 	NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
1233 	NLA_PUT_U32(msg, MACSEC_SA_ATTR_PN, sa->next_pn);
1234 	NLA_PUT(msg, MACSEC_SA_ATTR_KEYID, sizeof(sa->pkey->key_identifier),
1235 		&sa->pkey->key_identifier);
1236 	NLA_PUT(msg, MACSEC_SA_ATTR_KEY, sa->pkey->key_len, sa->pkey->key);
1237 	NLA_PUT_U8(msg, MACSEC_SA_ATTR_ACTIVE, sa->enable_transmit);
1238 
1239 	nla_nest_end(msg, nest);
1240 
1241 	ret = nl_send_recv(ctx->sk, msg);
1242 	if (ret < 0) {
1243 		wpa_printf(MSG_ERROR,
1244 			   DRV_PREFIX "%s: failed to communicate: %d (%s)",
1245 			   __func__, ret, nl_geterror(-ret));
1246 	}
1247 
1248 nla_put_failure:
1249 	nlmsg_free(msg);
1250 	return ret;
1251 }
1252 
1253 
1254 /**
1255  * macsec_drv_delete_transmit_sa - Delete secure association for transmit
1256  * @priv: private driver interface data from init()
1257  * @sa: secure association
1258  * Returns: 0 on success, -1 on failure
1259  */
macsec_drv_delete_transmit_sa(void * priv,struct transmit_sa * sa)1260 static int macsec_drv_delete_transmit_sa(void *priv, struct transmit_sa *sa)
1261 {
1262 	struct macsec_drv_data *drv = priv;
1263 	struct macsec_genl_ctx *ctx = &drv->ctx;
1264 	struct nl_msg *msg;
1265 	struct nlattr *nest;
1266 	int ret = -1;
1267 
1268 	wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: delete_transmit_sa -> %d on "
1269 		   SCISTR, drv->ifname, sa->an,
1270 		   SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
1271 
1272 	msg = msg_prepare(MACSEC_CMD_DEL_TXSA, ctx, drv->ifi);
1273 	if (!msg)
1274 		return ret;
1275 
1276 	nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
1277 	if (!nest)
1278 		goto nla_put_failure;
1279 
1280 	NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
1281 
1282 	nla_nest_end(msg, nest);
1283 
1284 	ret = nl_send_recv(ctx->sk, msg);
1285 	if (ret < 0) {
1286 		wpa_printf(MSG_ERROR,
1287 			   DRV_PREFIX "%s: failed to communicate: %d (%s)",
1288 			   __func__, ret, nl_geterror(-ret));
1289 	}
1290 
1291 nla_put_failure:
1292 	nlmsg_free(msg);
1293 	return ret;
1294 }
1295 
1296 
set_active_tx_sa(const struct macsec_genl_ctx * ctx,int ifindex,unsigned char an,Boolean state)1297 static int set_active_tx_sa(const struct macsec_genl_ctx *ctx, int ifindex,
1298 			    unsigned char an, Boolean state)
1299 {
1300 	struct nl_msg *msg;
1301 	struct nlattr *nest;
1302 	int ret = -1;
1303 
1304 	msg = msg_prepare(MACSEC_CMD_UPD_TXSA, ctx, ifindex);
1305 	if (!msg)
1306 		return ret;
1307 
1308 	nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
1309 	if (!nest)
1310 		goto nla_put_failure;
1311 
1312 	NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, an);
1313 	NLA_PUT_U8(msg, MACSEC_SA_ATTR_ACTIVE, !!state);
1314 
1315 	nla_nest_end(msg, nest);
1316 
1317 	ret = nl_send_recv(ctx->sk, msg);
1318 	if (ret < 0) {
1319 		wpa_printf(MSG_ERROR,
1320 			   DRV_PREFIX "%s: failed to communicate: %d (%s)",
1321 			   __func__, ret, nl_geterror(-ret));
1322 	}
1323 
1324 nla_put_failure:
1325 	nlmsg_free(msg);
1326 	return ret;
1327 }
1328 
1329 
1330 /**
1331  * macsec_drv_enable_transmit_sa - Enable SA for transmit
1332  * @priv: private driver interface data from init()
1333  * @sa: secure association
1334  * Returns: 0 on success, -1 on failure
1335  */
macsec_drv_enable_transmit_sa(void * priv,struct transmit_sa * sa)1336 static int macsec_drv_enable_transmit_sa(void *priv, struct transmit_sa *sa)
1337 {
1338 	struct macsec_drv_data *drv = priv;
1339 	struct macsec_genl_ctx *ctx = &drv->ctx;
1340 	int ret;
1341 
1342 	wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: enable_transmit_sa -> %d on "
1343 		   SCISTR, drv->ifname, sa->an,
1344 		   SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
1345 
1346 	ret = set_active_tx_sa(ctx, drv->ifi, sa->an, TRUE);
1347 	if (ret < 0) {
1348 		wpa_printf(MSG_ERROR, DRV_PREFIX "failed to enable txsa");
1349 		return ret;
1350 	}
1351 
1352 	drv->encoding_sa_set = TRUE;
1353 	drv->encoding_sa = sa->an;
1354 
1355 	return try_commit(drv);
1356 }
1357 
1358 
1359 /**
1360  * macsec_drv_disable_transmit_sa - Disable SA for transmit
1361  * @priv: private driver interface data from init()
1362  * @sa: secure association
1363  * Returns: 0 on success, -1 on failure
1364  */
macsec_drv_disable_transmit_sa(void * priv,struct transmit_sa * sa)1365 static int macsec_drv_disable_transmit_sa(void *priv, struct transmit_sa *sa)
1366 {
1367 	struct macsec_drv_data *drv = priv;
1368 	struct macsec_genl_ctx *ctx = &drv->ctx;
1369 
1370 	wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: disable_transmit_sa -> %d on "
1371 		   SCISTR, drv->ifname, sa->an,
1372 		   SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
1373 
1374 	return set_active_tx_sa(ctx, drv->ifi, sa->an, FALSE);
1375 }
1376 
1377 
macsec_drv_status(void * priv,char * buf,size_t buflen)1378 static int macsec_drv_status(void *priv, char *buf, size_t buflen)
1379 {
1380 	struct macsec_drv_data *drv = priv;
1381 	int res;
1382 	char *pos, *end;
1383 
1384 	pos = buf;
1385 	end = buf + buflen;
1386 
1387 	res = os_snprintf(pos, end - pos,
1388 			  "ifname=%s\n"
1389 			  "ifi=%d\n"
1390 			  "parent_ifname=%s\n"
1391 			  "parent_ifi=%d\n",
1392 			  drv->common.ifname, drv->ifi,
1393 			  drv->ifname, drv->parent_ifi);
1394 	if (os_snprintf_error(end - pos, res))
1395 		return pos - buf;
1396 	pos += res;
1397 
1398 	return pos - buf;
1399 }
1400 
1401 
1402 const struct wpa_driver_ops wpa_driver_macsec_linux_ops = {
1403 	.name = "macsec_linux",
1404 	.desc = "MACsec Ethernet driver for Linux",
1405 	.get_ssid = driver_wired_get_ssid,
1406 	.get_bssid = driver_wired_get_bssid,
1407 	.get_capa = driver_wired_get_capa,
1408 	.init = macsec_drv_wpa_init,
1409 	.deinit = macsec_drv_wpa_deinit,
1410 
1411 	.macsec_init = macsec_drv_macsec_init,
1412 	.macsec_deinit = macsec_drv_macsec_deinit,
1413 	.macsec_get_capability = macsec_drv_get_capability,
1414 	.enable_protect_frames = macsec_drv_enable_protect_frames,
1415 	.enable_encrypt = macsec_drv_enable_encrypt,
1416 	.set_replay_protect = macsec_drv_set_replay_protect,
1417 	.set_current_cipher_suite = macsec_drv_set_current_cipher_suite,
1418 	.enable_controlled_port = macsec_drv_enable_controlled_port,
1419 	.get_receive_lowest_pn = macsec_drv_get_receive_lowest_pn,
1420 	.set_receive_lowest_pn = macsec_drv_set_receive_lowest_pn,
1421 	.get_transmit_next_pn = macsec_drv_get_transmit_next_pn,
1422 	.set_transmit_next_pn = macsec_drv_set_transmit_next_pn,
1423 	.create_receive_sc = macsec_drv_create_receive_sc,
1424 	.delete_receive_sc = macsec_drv_delete_receive_sc,
1425 	.create_receive_sa = macsec_drv_create_receive_sa,
1426 	.delete_receive_sa = macsec_drv_delete_receive_sa,
1427 	.enable_receive_sa = macsec_drv_enable_receive_sa,
1428 	.disable_receive_sa = macsec_drv_disable_receive_sa,
1429 	.create_transmit_sc = macsec_drv_create_transmit_sc,
1430 	.delete_transmit_sc = macsec_drv_delete_transmit_sc,
1431 	.create_transmit_sa = macsec_drv_create_transmit_sa,
1432 	.delete_transmit_sa = macsec_drv_delete_transmit_sa,
1433 	.enable_transmit_sa = macsec_drv_enable_transmit_sa,
1434 	.disable_transmit_sa = macsec_drv_disable_transmit_sa,
1435 
1436 	.status = macsec_drv_status,
1437 };
1438