xref: /freebsd/contrib/wpa/src/ap/wpa_auth_kay.c (revision c1d255d3ffdbe447de3ab875bf4e7d7accc5bfc5)
1206b73d0SCy Schubert /*
2206b73d0SCy Schubert  * IEEE 802.1X-2010 KaY Interface
3206b73d0SCy Schubert  * Copyright (c) 2019, The Linux Foundation
4206b73d0SCy Schubert  *
5206b73d0SCy Schubert  * This software may be distributed under the terms of the BSD license.
6206b73d0SCy Schubert  * See README for more details.
7206b73d0SCy Schubert  */
8206b73d0SCy Schubert 
9206b73d0SCy Schubert #include "utils/includes.h"
10206b73d0SCy Schubert 
11206b73d0SCy Schubert #include "utils/common.h"
12206b73d0SCy Schubert #include "pae/ieee802_1x_key.h"
13206b73d0SCy Schubert #include "pae/ieee802_1x_kay.h"
14206b73d0SCy Schubert #include "hostapd.h"
15206b73d0SCy Schubert #include "sta_info.h"
16206b73d0SCy Schubert #include "wpa_auth_kay.h"
17206b73d0SCy Schubert #include "ieee802_1x.h"
18206b73d0SCy Schubert 
19206b73d0SCy Schubert 
20206b73d0SCy Schubert #define DEFAULT_KEY_LEN		16
21206b73d0SCy Schubert /* secure Connectivity Association Key Name (CKN) */
22206b73d0SCy Schubert #define DEFAULT_CKN_LEN		16
23206b73d0SCy Schubert 
24206b73d0SCy Schubert 
25206b73d0SCy Schubert static int hapd_macsec_init(void *priv, struct macsec_init_params *params)
26206b73d0SCy Schubert {
27206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
28206b73d0SCy Schubert 
29206b73d0SCy Schubert 	if (!hapd->driver->macsec_init)
30206b73d0SCy Schubert 		return -1;
31206b73d0SCy Schubert 	return hapd->driver->macsec_init(hapd->drv_priv, params);
32206b73d0SCy Schubert }
33206b73d0SCy Schubert 
34206b73d0SCy Schubert 
35206b73d0SCy Schubert static int hapd_macsec_deinit(void *priv)
36206b73d0SCy Schubert {
37206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
38206b73d0SCy Schubert 
39206b73d0SCy Schubert 	if (!hapd->driver->macsec_deinit)
40206b73d0SCy Schubert 		return -1;
41206b73d0SCy Schubert 	return hapd->driver->macsec_deinit(hapd->drv_priv);
42206b73d0SCy Schubert }
43206b73d0SCy Schubert 
44206b73d0SCy Schubert 
45206b73d0SCy Schubert static int hapd_macsec_get_capability(void *priv, enum macsec_cap *cap)
46206b73d0SCy Schubert {
47206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
48206b73d0SCy Schubert 
49206b73d0SCy Schubert 	if (!hapd->driver->macsec_get_capability)
50206b73d0SCy Schubert 		return -1;
51206b73d0SCy Schubert 	return hapd->driver->macsec_get_capability(hapd->drv_priv, cap);
52206b73d0SCy Schubert }
53206b73d0SCy Schubert 
54206b73d0SCy Schubert 
55*c1d255d3SCy Schubert static int hapd_enable_protect_frames(void *priv, bool enabled)
56206b73d0SCy Schubert {
57206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
58206b73d0SCy Schubert 
59206b73d0SCy Schubert 	if (!hapd->driver->enable_protect_frames)
60206b73d0SCy Schubert 		return -1;
61206b73d0SCy Schubert 	return hapd->driver->enable_protect_frames(hapd->drv_priv, enabled);
62206b73d0SCy Schubert }
63206b73d0SCy Schubert 
64206b73d0SCy Schubert 
65*c1d255d3SCy Schubert static int hapd_enable_encrypt(void *priv, bool enabled)
66206b73d0SCy Schubert {
67206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
68206b73d0SCy Schubert 
69206b73d0SCy Schubert 	if (!hapd->driver->enable_encrypt)
70206b73d0SCy Schubert 		return -1;
71206b73d0SCy Schubert 	return hapd->driver->enable_encrypt(hapd->drv_priv, enabled);
72206b73d0SCy Schubert }
73206b73d0SCy Schubert 
74206b73d0SCy Schubert 
75*c1d255d3SCy Schubert static int hapd_set_replay_protect(void *priv, bool enabled, u32 window)
76206b73d0SCy Schubert {
77206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
78206b73d0SCy Schubert 
79206b73d0SCy Schubert 	if (!hapd->driver->set_replay_protect)
80206b73d0SCy Schubert 		return -1;
81206b73d0SCy Schubert 	return hapd->driver->set_replay_protect(hapd->drv_priv, enabled,
82206b73d0SCy Schubert 						 window);
83206b73d0SCy Schubert }
84206b73d0SCy Schubert 
85206b73d0SCy Schubert 
86206b73d0SCy Schubert static int hapd_set_current_cipher_suite(void *priv, u64 cs)
87206b73d0SCy Schubert {
88206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
89206b73d0SCy Schubert 
90206b73d0SCy Schubert 	if (!hapd->driver->set_current_cipher_suite)
91206b73d0SCy Schubert 		return -1;
92206b73d0SCy Schubert 	return hapd->driver->set_current_cipher_suite(hapd->drv_priv, cs);
93206b73d0SCy Schubert }
94206b73d0SCy Schubert 
95206b73d0SCy Schubert 
96*c1d255d3SCy Schubert static int hapd_enable_controlled_port(void *priv, bool enabled)
97206b73d0SCy Schubert {
98206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
99206b73d0SCy Schubert 
100206b73d0SCy Schubert 	if (!hapd->driver->enable_controlled_port)
101206b73d0SCy Schubert 		return -1;
102206b73d0SCy Schubert 	return hapd->driver->enable_controlled_port(hapd->drv_priv, enabled);
103206b73d0SCy Schubert }
104206b73d0SCy Schubert 
105206b73d0SCy Schubert 
106206b73d0SCy Schubert static int hapd_get_receive_lowest_pn(void *priv, struct receive_sa *sa)
107206b73d0SCy Schubert {
108206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
109206b73d0SCy Schubert 
110206b73d0SCy Schubert 	if (!hapd->driver->get_receive_lowest_pn)
111206b73d0SCy Schubert 		return -1;
112206b73d0SCy Schubert 	return hapd->driver->get_receive_lowest_pn(hapd->drv_priv, sa);
113206b73d0SCy Schubert }
114206b73d0SCy Schubert 
115206b73d0SCy Schubert 
116206b73d0SCy Schubert static int hapd_get_transmit_next_pn(void *priv, struct transmit_sa *sa)
117206b73d0SCy Schubert {
118206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
119206b73d0SCy Schubert 
120206b73d0SCy Schubert 	if (!hapd->driver->get_transmit_next_pn)
121206b73d0SCy Schubert 		return -1;
122206b73d0SCy Schubert 	return hapd->driver->get_transmit_next_pn(hapd->drv_priv, sa);
123206b73d0SCy Schubert }
124206b73d0SCy Schubert 
125206b73d0SCy Schubert 
126206b73d0SCy Schubert static int hapd_set_transmit_next_pn(void *priv, struct transmit_sa *sa)
127206b73d0SCy Schubert {
128206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
129206b73d0SCy Schubert 
130206b73d0SCy Schubert 	if (!hapd->driver->set_transmit_next_pn)
131206b73d0SCy Schubert 		return -1;
132206b73d0SCy Schubert 	return hapd->driver->set_transmit_next_pn(hapd->drv_priv, sa);
133206b73d0SCy Schubert }
134206b73d0SCy Schubert 
135206b73d0SCy Schubert 
136206b73d0SCy Schubert static unsigned int conf_offset_val(enum confidentiality_offset co)
137206b73d0SCy Schubert {
138206b73d0SCy Schubert 	switch (co) {
139206b73d0SCy Schubert 	case CONFIDENTIALITY_OFFSET_30:
140206b73d0SCy Schubert 		return 30;
141206b73d0SCy Schubert 		break;
142206b73d0SCy Schubert 	case CONFIDENTIALITY_OFFSET_50:
143206b73d0SCy Schubert 		return 50;
144206b73d0SCy Schubert 	default:
145206b73d0SCy Schubert 		return 0;
146206b73d0SCy Schubert 	}
147206b73d0SCy Schubert }
148206b73d0SCy Schubert 
149206b73d0SCy Schubert 
150206b73d0SCy Schubert static int hapd_create_receive_sc(void *priv, struct receive_sc *sc,
151206b73d0SCy Schubert 				  enum validate_frames vf,
152206b73d0SCy Schubert 				  enum confidentiality_offset co)
153206b73d0SCy Schubert {
154206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
155206b73d0SCy Schubert 
156206b73d0SCy Schubert 	if (!hapd->driver->create_receive_sc)
157206b73d0SCy Schubert 		return -1;
158206b73d0SCy Schubert 	return hapd->driver->create_receive_sc(hapd->drv_priv, sc,
159206b73d0SCy Schubert 					       conf_offset_val(co), vf);
160206b73d0SCy Schubert }
161206b73d0SCy Schubert 
162206b73d0SCy Schubert 
163206b73d0SCy Schubert static int hapd_delete_receive_sc(void *priv, struct receive_sc *sc)
164206b73d0SCy Schubert {
165206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
166206b73d0SCy Schubert 
167206b73d0SCy Schubert 	if (!hapd->driver->delete_receive_sc)
168206b73d0SCy Schubert 		return -1;
169206b73d0SCy Schubert 	return hapd->driver->delete_receive_sc(hapd->drv_priv, sc);
170206b73d0SCy Schubert }
171206b73d0SCy Schubert 
172206b73d0SCy Schubert 
173206b73d0SCy Schubert static int hapd_create_receive_sa(void *priv, struct receive_sa *sa)
174206b73d0SCy Schubert {
175206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
176206b73d0SCy Schubert 
177206b73d0SCy Schubert 	if (!hapd->driver->create_receive_sa)
178206b73d0SCy Schubert 		return -1;
179206b73d0SCy Schubert 	return hapd->driver->create_receive_sa(hapd->drv_priv, sa);
180206b73d0SCy Schubert }
181206b73d0SCy Schubert 
182206b73d0SCy Schubert 
183206b73d0SCy Schubert static int hapd_delete_receive_sa(void *priv, struct receive_sa *sa)
184206b73d0SCy Schubert {
185206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
186206b73d0SCy Schubert 
187206b73d0SCy Schubert 	if (!hapd->driver->delete_receive_sa)
188206b73d0SCy Schubert 		return -1;
189206b73d0SCy Schubert 	return hapd->driver->delete_receive_sa(hapd->drv_priv, sa);
190206b73d0SCy Schubert }
191206b73d0SCy Schubert 
192206b73d0SCy Schubert 
193206b73d0SCy Schubert static int hapd_enable_receive_sa(void *priv, struct receive_sa *sa)
194206b73d0SCy Schubert {
195206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
196206b73d0SCy Schubert 
197206b73d0SCy Schubert 	if (!hapd->driver->enable_receive_sa)
198206b73d0SCy Schubert 		return -1;
199206b73d0SCy Schubert 	return hapd->driver->enable_receive_sa(hapd->drv_priv, sa);
200206b73d0SCy Schubert }
201206b73d0SCy Schubert 
202206b73d0SCy Schubert 
203206b73d0SCy Schubert static int hapd_disable_receive_sa(void *priv, struct receive_sa *sa)
204206b73d0SCy Schubert {
205206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
206206b73d0SCy Schubert 
207206b73d0SCy Schubert 	if (!hapd->driver->disable_receive_sa)
208206b73d0SCy Schubert 		return -1;
209206b73d0SCy Schubert 	return hapd->driver->disable_receive_sa(hapd->drv_priv, sa);
210206b73d0SCy Schubert }
211206b73d0SCy Schubert 
212206b73d0SCy Schubert 
213206b73d0SCy Schubert static int
214206b73d0SCy Schubert hapd_create_transmit_sc(void *priv, struct transmit_sc *sc,
215206b73d0SCy Schubert 			enum confidentiality_offset co)
216206b73d0SCy Schubert {
217206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
218206b73d0SCy Schubert 
219206b73d0SCy Schubert 	if (!hapd->driver->create_transmit_sc)
220206b73d0SCy Schubert 		return -1;
221206b73d0SCy Schubert 	return hapd->driver->create_transmit_sc(hapd->drv_priv, sc,
222206b73d0SCy Schubert 						conf_offset_val(co));
223206b73d0SCy Schubert }
224206b73d0SCy Schubert 
225206b73d0SCy Schubert 
226206b73d0SCy Schubert static int hapd_delete_transmit_sc(void *priv, struct transmit_sc *sc)
227206b73d0SCy Schubert {
228206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
229206b73d0SCy Schubert 
230206b73d0SCy Schubert 	if (!hapd->driver->delete_transmit_sc)
231206b73d0SCy Schubert 		return -1;
232206b73d0SCy Schubert 	return hapd->driver->delete_transmit_sc(hapd->drv_priv, sc);
233206b73d0SCy Schubert }
234206b73d0SCy Schubert 
235206b73d0SCy Schubert 
236206b73d0SCy Schubert static int hapd_create_transmit_sa(void *priv, struct transmit_sa *sa)
237206b73d0SCy Schubert {
238206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
239206b73d0SCy Schubert 
240206b73d0SCy Schubert 	if (!hapd->driver->create_transmit_sa)
241206b73d0SCy Schubert 		return -1;
242206b73d0SCy Schubert 	return hapd->driver->create_transmit_sa(hapd->drv_priv, sa);
243206b73d0SCy Schubert }
244206b73d0SCy Schubert 
245206b73d0SCy Schubert 
246206b73d0SCy Schubert static int hapd_delete_transmit_sa(void *priv, struct transmit_sa *sa)
247206b73d0SCy Schubert {
248206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
249206b73d0SCy Schubert 
250206b73d0SCy Schubert 	if (!hapd->driver->delete_transmit_sa)
251206b73d0SCy Schubert 		return -1;
252206b73d0SCy Schubert 	return hapd->driver->delete_transmit_sa(hapd->drv_priv, sa);
253206b73d0SCy Schubert }
254206b73d0SCy Schubert 
255206b73d0SCy Schubert 
256206b73d0SCy Schubert static int hapd_enable_transmit_sa(void *priv, struct transmit_sa *sa)
257206b73d0SCy Schubert {
258206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
259206b73d0SCy Schubert 
260206b73d0SCy Schubert 	if (!hapd->driver->enable_transmit_sa)
261206b73d0SCy Schubert 		return -1;
262206b73d0SCy Schubert 	return hapd->driver->enable_transmit_sa(hapd->drv_priv, sa);
263206b73d0SCy Schubert }
264206b73d0SCy Schubert 
265206b73d0SCy Schubert 
266206b73d0SCy Schubert static int hapd_disable_transmit_sa(void *priv, struct transmit_sa *sa)
267206b73d0SCy Schubert {
268206b73d0SCy Schubert 	struct hostapd_data *hapd = priv;
269206b73d0SCy Schubert 
270206b73d0SCy Schubert 	if (!hapd->driver->disable_transmit_sa)
271206b73d0SCy Schubert 		return -1;
272206b73d0SCy Schubert 	return hapd->driver->disable_transmit_sa(hapd->drv_priv, sa);
273206b73d0SCy Schubert }
274206b73d0SCy Schubert 
275206b73d0SCy Schubert 
276206b73d0SCy Schubert int ieee802_1x_alloc_kay_sm_hapd(struct hostapd_data *hapd,
277206b73d0SCy Schubert 				 struct sta_info *sta)
278206b73d0SCy Schubert {
279206b73d0SCy Schubert 	struct ieee802_1x_kay_ctx *kay_ctx;
280206b73d0SCy Schubert 	struct ieee802_1x_kay *res = NULL;
281206b73d0SCy Schubert 	enum macsec_policy policy;
282206b73d0SCy Schubert 
283206b73d0SCy Schubert 	ieee802_1x_dealloc_kay_sm_hapd(hapd);
284206b73d0SCy Schubert 
285206b73d0SCy Schubert 	if (!hapd->conf || hapd->conf->macsec_policy == 0)
286206b73d0SCy Schubert 		return 0;
287206b73d0SCy Schubert 
288206b73d0SCy Schubert 	if (hapd->conf->macsec_policy == 1) {
289206b73d0SCy Schubert 		if (hapd->conf->macsec_integ_only == 1)
290206b73d0SCy Schubert 			policy = SHOULD_SECURE;
291206b73d0SCy Schubert 		else
292206b73d0SCy Schubert 			policy = SHOULD_ENCRYPT;
293206b73d0SCy Schubert 	} else {
294206b73d0SCy Schubert 		policy = DO_NOT_SECURE;
295206b73d0SCy Schubert 	}
296206b73d0SCy Schubert 
297206b73d0SCy Schubert 	wpa_printf(MSG_DEBUG, "%s: if_name=%s", __func__, hapd->conf->iface);
298206b73d0SCy Schubert 	kay_ctx = os_zalloc(sizeof(*kay_ctx));
299206b73d0SCy Schubert 	if (!kay_ctx)
300206b73d0SCy Schubert 		return -1;
301206b73d0SCy Schubert 
302206b73d0SCy Schubert 	kay_ctx->ctx = hapd;
303206b73d0SCy Schubert 
304206b73d0SCy Schubert 	kay_ctx->macsec_init = hapd_macsec_init;
305206b73d0SCy Schubert 	kay_ctx->macsec_deinit = hapd_macsec_deinit;
306206b73d0SCy Schubert 	kay_ctx->macsec_get_capability = hapd_macsec_get_capability;
307206b73d0SCy Schubert 	kay_ctx->enable_protect_frames = hapd_enable_protect_frames;
308206b73d0SCy Schubert 	kay_ctx->enable_encrypt = hapd_enable_encrypt;
309206b73d0SCy Schubert 	kay_ctx->set_replay_protect = hapd_set_replay_protect;
310206b73d0SCy Schubert 	kay_ctx->set_current_cipher_suite = hapd_set_current_cipher_suite;
311206b73d0SCy Schubert 	kay_ctx->enable_controlled_port = hapd_enable_controlled_port;
312206b73d0SCy Schubert 	kay_ctx->get_receive_lowest_pn = hapd_get_receive_lowest_pn;
313206b73d0SCy Schubert 	kay_ctx->get_transmit_next_pn = hapd_get_transmit_next_pn;
314206b73d0SCy Schubert 	kay_ctx->set_transmit_next_pn = hapd_set_transmit_next_pn;
315206b73d0SCy Schubert 	kay_ctx->create_receive_sc = hapd_create_receive_sc;
316206b73d0SCy Schubert 	kay_ctx->delete_receive_sc = hapd_delete_receive_sc;
317206b73d0SCy Schubert 	kay_ctx->create_receive_sa = hapd_create_receive_sa;
318206b73d0SCy Schubert 	kay_ctx->delete_receive_sa = hapd_delete_receive_sa;
319206b73d0SCy Schubert 	kay_ctx->enable_receive_sa = hapd_enable_receive_sa;
320206b73d0SCy Schubert 	kay_ctx->disable_receive_sa = hapd_disable_receive_sa;
321206b73d0SCy Schubert 	kay_ctx->create_transmit_sc = hapd_create_transmit_sc;
322206b73d0SCy Schubert 	kay_ctx->delete_transmit_sc = hapd_delete_transmit_sc;
323206b73d0SCy Schubert 	kay_ctx->create_transmit_sa = hapd_create_transmit_sa;
324206b73d0SCy Schubert 	kay_ctx->delete_transmit_sa = hapd_delete_transmit_sa;
325206b73d0SCy Schubert 	kay_ctx->enable_transmit_sa = hapd_enable_transmit_sa;
326206b73d0SCy Schubert 	kay_ctx->disable_transmit_sa = hapd_disable_transmit_sa;
327206b73d0SCy Schubert 
328206b73d0SCy Schubert 	res = ieee802_1x_kay_init(kay_ctx, policy,
329206b73d0SCy Schubert 				  hapd->conf->macsec_replay_protect,
330206b73d0SCy Schubert 				  hapd->conf->macsec_replay_window,
331206b73d0SCy Schubert 				  hapd->conf->macsec_port,
332206b73d0SCy Schubert 				  hapd->conf->mka_priority, hapd->conf->iface,
333206b73d0SCy Schubert 				  hapd->own_addr);
334206b73d0SCy Schubert 	/* ieee802_1x_kay_init() frees kay_ctx on failure */
335206b73d0SCy Schubert 	if (!res)
336206b73d0SCy Schubert 		return -1;
337206b73d0SCy Schubert 
338206b73d0SCy Schubert 	hapd->kay = res;
339206b73d0SCy Schubert 
340206b73d0SCy Schubert 	return 0;
341206b73d0SCy Schubert }
342206b73d0SCy Schubert 
343206b73d0SCy Schubert 
344206b73d0SCy Schubert void ieee802_1x_dealloc_kay_sm_hapd(struct hostapd_data *hapd)
345206b73d0SCy Schubert {
346206b73d0SCy Schubert 	if (!hapd->kay)
347206b73d0SCy Schubert 		return;
348206b73d0SCy Schubert 
349206b73d0SCy Schubert 	ieee802_1x_kay_deinit(hapd->kay);
350206b73d0SCy Schubert 	hapd->kay = NULL;
351206b73d0SCy Schubert }
352206b73d0SCy Schubert 
353206b73d0SCy Schubert 
354206b73d0SCy Schubert static int ieee802_1x_auth_get_session_id(struct hostapd_data *hapd,
355206b73d0SCy Schubert 					  struct sta_info *sta, u8 *sid,
356206b73d0SCy Schubert 					  size_t *len)
357206b73d0SCy Schubert {
358206b73d0SCy Schubert 	const u8 *session_id;
359206b73d0SCy Schubert 	size_t id_len, need_len;
360206b73d0SCy Schubert 
361206b73d0SCy Schubert 	session_id = ieee802_1x_get_session_id(sta->eapol_sm, &id_len);
362206b73d0SCy Schubert 	if (!session_id) {
363206b73d0SCy Schubert 		wpa_printf(MSG_DEBUG,
364206b73d0SCy Schubert 			   "MACsec: Failed to get SessionID from EAPOL state machines");
365206b73d0SCy Schubert 		return -1;
366206b73d0SCy Schubert 	}
367206b73d0SCy Schubert 
368206b73d0SCy Schubert 	need_len = 1 + 2 * 32 /* random size */;
369206b73d0SCy Schubert 	if (need_len > id_len) {
370206b73d0SCy Schubert 		wpa_printf(MSG_DEBUG, "EAP Session-Id not long enough");
371206b73d0SCy Schubert 		return -1;
372206b73d0SCy Schubert 	}
373206b73d0SCy Schubert 
374206b73d0SCy Schubert 	os_memcpy(sid, session_id, need_len);
375206b73d0SCy Schubert 	*len = need_len;
376206b73d0SCy Schubert 
377206b73d0SCy Schubert 	return 0;
378206b73d0SCy Schubert }
379206b73d0SCy Schubert 
380206b73d0SCy Schubert 
381206b73d0SCy Schubert static int ieee802_1x_auth_get_msk(struct hostapd_data *hapd,
382206b73d0SCy Schubert 				   struct sta_info *sta, u8 *msk, size_t *len)
383206b73d0SCy Schubert {
384206b73d0SCy Schubert 	const u8 *key;
385206b73d0SCy Schubert 	size_t keylen;
386206b73d0SCy Schubert 
387206b73d0SCy Schubert 	if (!sta->eapol_sm)
388206b73d0SCy Schubert 		return -1;
389206b73d0SCy Schubert 
390206b73d0SCy Schubert 	key = ieee802_1x_get_key(sta->eapol_sm, &keylen);
391206b73d0SCy Schubert 	if (key == NULL) {
392206b73d0SCy Schubert 		wpa_printf(MSG_DEBUG,
393206b73d0SCy Schubert 			   "MACsec: Failed to get MSK from EAPOL state machines");
394206b73d0SCy Schubert 		return -1;
395206b73d0SCy Schubert 	}
396206b73d0SCy Schubert 	wpa_printf(MSG_DEBUG, "MACsec: Successfully fetched key (len=%lu)",
397206b73d0SCy Schubert 		   (unsigned long) keylen);
398206b73d0SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "MSK: ", key, keylen);
399206b73d0SCy Schubert 
400206b73d0SCy Schubert 	if (keylen > *len)
401206b73d0SCy Schubert 		keylen = *len;
402206b73d0SCy Schubert 	os_memcpy(msk, key, keylen);
403206b73d0SCy Schubert 	*len = keylen;
404206b73d0SCy Schubert 
405206b73d0SCy Schubert 	return 0;
406206b73d0SCy Schubert }
407206b73d0SCy Schubert 
408206b73d0SCy Schubert 
409206b73d0SCy Schubert void * ieee802_1x_notify_create_actor_hapd(struct hostapd_data *hapd,
410206b73d0SCy Schubert 					   struct sta_info *sta)
411206b73d0SCy Schubert {
412206b73d0SCy Schubert 	u8 *sid;
413206b73d0SCy Schubert 	size_t sid_len = 128;
414206b73d0SCy Schubert 	struct mka_key_name *ckn;
415206b73d0SCy Schubert 	struct mka_key *cak;
416206b73d0SCy Schubert 	struct mka_key *msk;
417206b73d0SCy Schubert 	void *res = NULL;
418206b73d0SCy Schubert 
419206b73d0SCy Schubert 	if (!hapd->kay || hapd->kay->policy == DO_NOT_SECURE)
420206b73d0SCy Schubert 		return NULL;
421206b73d0SCy Schubert 
422206b73d0SCy Schubert 	wpa_printf(MSG_DEBUG,
423206b73d0SCy Schubert 		   "IEEE 802.1X: External notification - Create MKA for "
424206b73d0SCy Schubert 		   MACSTR, MAC2STR(sta->addr));
425206b73d0SCy Schubert 
426206b73d0SCy Schubert 	msk = os_zalloc(sizeof(*msk));
427206b73d0SCy Schubert 	sid = os_zalloc(sid_len);
428206b73d0SCy Schubert 	ckn = os_zalloc(sizeof(*ckn));
429206b73d0SCy Schubert 	cak = os_zalloc(sizeof(*cak));
430206b73d0SCy Schubert 	if (!msk || !sid || !ckn || !cak)
431206b73d0SCy Schubert 		goto fail;
432206b73d0SCy Schubert 
433206b73d0SCy Schubert 	msk->len = DEFAULT_KEY_LEN;
434206b73d0SCy Schubert 	if (ieee802_1x_auth_get_msk(hapd, sta, msk->key, &msk->len)) {
435206b73d0SCy Schubert 		wpa_printf(MSG_ERROR, "IEEE 802.1X: Could not get MSK");
436206b73d0SCy Schubert 		goto fail;
437206b73d0SCy Schubert 	}
438206b73d0SCy Schubert 
439206b73d0SCy Schubert 	if (ieee802_1x_auth_get_session_id(hapd, sta, sid, &sid_len))
440206b73d0SCy Schubert 	{
441206b73d0SCy Schubert 		wpa_printf(MSG_ERROR,
442206b73d0SCy Schubert 			   "IEEE 802.1X: Could not get EAP Session Id");
443206b73d0SCy Schubert 		goto fail;
444206b73d0SCy Schubert 	}
445206b73d0SCy Schubert 
446206b73d0SCy Schubert 	wpa_hexdump(MSG_DEBUG, "own_addr", hapd->own_addr, ETH_ALEN);
447206b73d0SCy Schubert 	wpa_hexdump(MSG_DEBUG, "sta_addr", sta->addr, ETH_ALEN);
448206b73d0SCy Schubert 
449206b73d0SCy Schubert 	/* Derive CAK from MSK */
450206b73d0SCy Schubert 	cak->len = DEFAULT_KEY_LEN;
451206b73d0SCy Schubert 	if (ieee802_1x_cak_aes_cmac(msk->key, msk->len, hapd->own_addr,
452206b73d0SCy Schubert 				    sta->addr, cak->key, cak->len)) {
453206b73d0SCy Schubert 		wpa_printf(MSG_ERROR, "IEEE 802.1X: Deriving CAK failed");
454206b73d0SCy Schubert 		goto fail;
455206b73d0SCy Schubert 	}
456206b73d0SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "Derived CAK", cak->key, cak->len);
457206b73d0SCy Schubert 
458206b73d0SCy Schubert 	/* Derive CKN from MSK */
459206b73d0SCy Schubert 	ckn->len = DEFAULT_CKN_LEN;
460206b73d0SCy Schubert 	if (ieee802_1x_ckn_aes_cmac(msk->key, msk->len, hapd->own_addr,
461206b73d0SCy Schubert 				    sta->addr, sid, sid_len, ckn->name)) {
462206b73d0SCy Schubert 		wpa_printf(MSG_ERROR, "IEEE 802.1X: Deriving CKN failed");
463206b73d0SCy Schubert 		goto fail;
464206b73d0SCy Schubert 	}
465206b73d0SCy Schubert 	wpa_hexdump(MSG_DEBUG, "Derived CKN", ckn->name, ckn->len);
466206b73d0SCy Schubert 
467206b73d0SCy Schubert 	res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, EAP_EXCHANGE,
468*c1d255d3SCy Schubert 					true);
469206b73d0SCy Schubert 
470206b73d0SCy Schubert fail:
471206b73d0SCy Schubert 	bin_clear_free(msk, sizeof(*msk));
472206b73d0SCy Schubert 	os_free(sid);
473206b73d0SCy Schubert 	os_free(ckn);
474206b73d0SCy Schubert 	bin_clear_free(cak, sizeof(*cak));
475206b73d0SCy Schubert 
476206b73d0SCy Schubert 	return res;
477206b73d0SCy Schubert }
478206b73d0SCy Schubert 
479206b73d0SCy Schubert 
480206b73d0SCy Schubert void * ieee802_1x_create_preshared_mka_hapd(struct hostapd_data *hapd,
481206b73d0SCy Schubert 					    struct sta_info *sta)
482206b73d0SCy Schubert {
483206b73d0SCy Schubert 	struct mka_key *cak;
484206b73d0SCy Schubert 	struct mka_key_name *ckn;
485206b73d0SCy Schubert 	void *res = NULL;
486206b73d0SCy Schubert 
487206b73d0SCy Schubert 	if ((hapd->conf->mka_psk_set & MKA_PSK_SET) != MKA_PSK_SET)
488206b73d0SCy Schubert 		goto end;
489206b73d0SCy Schubert 
490206b73d0SCy Schubert 	ckn = os_zalloc(sizeof(*ckn));
491206b73d0SCy Schubert 	if (!ckn)
492206b73d0SCy Schubert 		goto end;
493206b73d0SCy Schubert 
494206b73d0SCy Schubert 	cak = os_zalloc(sizeof(*cak));
495206b73d0SCy Schubert 	if (!cak)
496206b73d0SCy Schubert 		goto free_ckn;
497206b73d0SCy Schubert 
498206b73d0SCy Schubert 	if (ieee802_1x_alloc_kay_sm_hapd(hapd, sta) < 0 || !hapd->kay)
499206b73d0SCy Schubert 		goto free_cak;
500206b73d0SCy Schubert 
501206b73d0SCy Schubert 	if (hapd->kay->policy == DO_NOT_SECURE)
502206b73d0SCy Schubert 		goto dealloc;
503206b73d0SCy Schubert 
504206b73d0SCy Schubert 	cak->len = hapd->conf->mka_cak_len;
505206b73d0SCy Schubert 	os_memcpy(cak->key, hapd->conf->mka_cak, cak->len);
506206b73d0SCy Schubert 
507206b73d0SCy Schubert 	ckn->len = hapd->conf->mka_ckn_len;;
508206b73d0SCy Schubert 	os_memcpy(ckn->name, hapd->conf->mka_ckn, ckn->len);
509206b73d0SCy Schubert 
510*c1d255d3SCy Schubert 	res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, PSK, true);
511206b73d0SCy Schubert 	if (res)
512206b73d0SCy Schubert 		goto free_cak;
513206b73d0SCy Schubert 
514206b73d0SCy Schubert dealloc:
515206b73d0SCy Schubert 	/* Failed to create MKA */
516206b73d0SCy Schubert 	ieee802_1x_dealloc_kay_sm_hapd(hapd);
517206b73d0SCy Schubert free_cak:
518206b73d0SCy Schubert 	os_free(cak);
519206b73d0SCy Schubert free_ckn:
520206b73d0SCy Schubert 	os_free(ckn);
521206b73d0SCy Schubert end:
522206b73d0SCy Schubert 	return res;
523206b73d0SCy Schubert }
524