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