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
hapd_macsec_init(void * priv,struct macsec_init_params * params)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
hapd_macsec_deinit(void * priv)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
hapd_macsec_get_capability(void * priv,enum macsec_cap * cap)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
hapd_enable_protect_frames(void * priv,bool enabled)55c1d255d3SCy 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
hapd_enable_encrypt(void * priv,bool enabled)65c1d255d3SCy 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
hapd_set_replay_protect(void * priv,bool enabled,u32 window)75c1d255d3SCy 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
hapd_set_current_cipher_suite(void * priv,u64 cs)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
hapd_enable_controlled_port(void * priv,bool enabled)96c1d255d3SCy 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
hapd_get_receive_lowest_pn(void * priv,struct receive_sa * sa)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
hapd_get_transmit_next_pn(void * priv,struct transmit_sa * sa)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
hapd_set_transmit_next_pn(void * priv,struct transmit_sa * sa)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
conf_offset_val(enum confidentiality_offset co)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 case CONFIDENTIALITY_OFFSET_50:
142206b73d0SCy Schubert return 50;
143206b73d0SCy Schubert default:
144206b73d0SCy Schubert return 0;
145206b73d0SCy Schubert }
146206b73d0SCy Schubert }
147206b73d0SCy Schubert
148206b73d0SCy Schubert
hapd_create_receive_sc(void * priv,struct receive_sc * sc,enum validate_frames vf,enum confidentiality_offset co)149206b73d0SCy Schubert static int hapd_create_receive_sc(void *priv, struct receive_sc *sc,
150206b73d0SCy Schubert enum validate_frames vf,
151206b73d0SCy Schubert enum confidentiality_offset co)
152206b73d0SCy Schubert {
153206b73d0SCy Schubert struct hostapd_data *hapd = priv;
154206b73d0SCy Schubert
155206b73d0SCy Schubert if (!hapd->driver->create_receive_sc)
156206b73d0SCy Schubert return -1;
157206b73d0SCy Schubert return hapd->driver->create_receive_sc(hapd->drv_priv, sc,
158206b73d0SCy Schubert conf_offset_val(co), vf);
159206b73d0SCy Schubert }
160206b73d0SCy Schubert
161206b73d0SCy Schubert
hapd_delete_receive_sc(void * priv,struct receive_sc * sc)162206b73d0SCy Schubert static int hapd_delete_receive_sc(void *priv, struct receive_sc *sc)
163206b73d0SCy Schubert {
164206b73d0SCy Schubert struct hostapd_data *hapd = priv;
165206b73d0SCy Schubert
166206b73d0SCy Schubert if (!hapd->driver->delete_receive_sc)
167206b73d0SCy Schubert return -1;
168206b73d0SCy Schubert return hapd->driver->delete_receive_sc(hapd->drv_priv, sc);
169206b73d0SCy Schubert }
170206b73d0SCy Schubert
171206b73d0SCy Schubert
hapd_create_receive_sa(void * priv,struct receive_sa * sa)172206b73d0SCy Schubert static int hapd_create_receive_sa(void *priv, struct receive_sa *sa)
173206b73d0SCy Schubert {
174206b73d0SCy Schubert struct hostapd_data *hapd = priv;
175206b73d0SCy Schubert
176206b73d0SCy Schubert if (!hapd->driver->create_receive_sa)
177206b73d0SCy Schubert return -1;
178206b73d0SCy Schubert return hapd->driver->create_receive_sa(hapd->drv_priv, sa);
179206b73d0SCy Schubert }
180206b73d0SCy Schubert
181206b73d0SCy Schubert
hapd_delete_receive_sa(void * priv,struct receive_sa * sa)182206b73d0SCy Schubert static int hapd_delete_receive_sa(void *priv, struct receive_sa *sa)
183206b73d0SCy Schubert {
184206b73d0SCy Schubert struct hostapd_data *hapd = priv;
185206b73d0SCy Schubert
186206b73d0SCy Schubert if (!hapd->driver->delete_receive_sa)
187206b73d0SCy Schubert return -1;
188206b73d0SCy Schubert return hapd->driver->delete_receive_sa(hapd->drv_priv, sa);
189206b73d0SCy Schubert }
190206b73d0SCy Schubert
191206b73d0SCy Schubert
hapd_enable_receive_sa(void * priv,struct receive_sa * sa)192206b73d0SCy Schubert static int hapd_enable_receive_sa(void *priv, struct receive_sa *sa)
193206b73d0SCy Schubert {
194206b73d0SCy Schubert struct hostapd_data *hapd = priv;
195206b73d0SCy Schubert
196206b73d0SCy Schubert if (!hapd->driver->enable_receive_sa)
197206b73d0SCy Schubert return -1;
198206b73d0SCy Schubert return hapd->driver->enable_receive_sa(hapd->drv_priv, sa);
199206b73d0SCy Schubert }
200206b73d0SCy Schubert
201206b73d0SCy Schubert
hapd_disable_receive_sa(void * priv,struct receive_sa * sa)202206b73d0SCy Schubert static int hapd_disable_receive_sa(void *priv, struct receive_sa *sa)
203206b73d0SCy Schubert {
204206b73d0SCy Schubert struct hostapd_data *hapd = priv;
205206b73d0SCy Schubert
206206b73d0SCy Schubert if (!hapd->driver->disable_receive_sa)
207206b73d0SCy Schubert return -1;
208206b73d0SCy Schubert return hapd->driver->disable_receive_sa(hapd->drv_priv, sa);
209206b73d0SCy Schubert }
210206b73d0SCy Schubert
211206b73d0SCy Schubert
212206b73d0SCy Schubert static int
hapd_create_transmit_sc(void * priv,struct transmit_sc * sc,enum confidentiality_offset co)213206b73d0SCy Schubert hapd_create_transmit_sc(void *priv, struct transmit_sc *sc,
214206b73d0SCy Schubert enum confidentiality_offset co)
215206b73d0SCy Schubert {
216206b73d0SCy Schubert struct hostapd_data *hapd = priv;
217206b73d0SCy Schubert
218206b73d0SCy Schubert if (!hapd->driver->create_transmit_sc)
219206b73d0SCy Schubert return -1;
220206b73d0SCy Schubert return hapd->driver->create_transmit_sc(hapd->drv_priv, sc,
221206b73d0SCy Schubert conf_offset_val(co));
222206b73d0SCy Schubert }
223206b73d0SCy Schubert
224206b73d0SCy Schubert
hapd_delete_transmit_sc(void * priv,struct transmit_sc * sc)225206b73d0SCy Schubert static int hapd_delete_transmit_sc(void *priv, struct transmit_sc *sc)
226206b73d0SCy Schubert {
227206b73d0SCy Schubert struct hostapd_data *hapd = priv;
228206b73d0SCy Schubert
229206b73d0SCy Schubert if (!hapd->driver->delete_transmit_sc)
230206b73d0SCy Schubert return -1;
231206b73d0SCy Schubert return hapd->driver->delete_transmit_sc(hapd->drv_priv, sc);
232206b73d0SCy Schubert }
233206b73d0SCy Schubert
234206b73d0SCy Schubert
hapd_create_transmit_sa(void * priv,struct transmit_sa * sa)235206b73d0SCy Schubert static int hapd_create_transmit_sa(void *priv, struct transmit_sa *sa)
236206b73d0SCy Schubert {
237206b73d0SCy Schubert struct hostapd_data *hapd = priv;
238206b73d0SCy Schubert
239206b73d0SCy Schubert if (!hapd->driver->create_transmit_sa)
240206b73d0SCy Schubert return -1;
241206b73d0SCy Schubert return hapd->driver->create_transmit_sa(hapd->drv_priv, sa);
242206b73d0SCy Schubert }
243206b73d0SCy Schubert
244206b73d0SCy Schubert
hapd_delete_transmit_sa(void * priv,struct transmit_sa * sa)245206b73d0SCy Schubert static int hapd_delete_transmit_sa(void *priv, struct transmit_sa *sa)
246206b73d0SCy Schubert {
247206b73d0SCy Schubert struct hostapd_data *hapd = priv;
248206b73d0SCy Schubert
249206b73d0SCy Schubert if (!hapd->driver->delete_transmit_sa)
250206b73d0SCy Schubert return -1;
251206b73d0SCy Schubert return hapd->driver->delete_transmit_sa(hapd->drv_priv, sa);
252206b73d0SCy Schubert }
253206b73d0SCy Schubert
254206b73d0SCy Schubert
hapd_enable_transmit_sa(void * priv,struct transmit_sa * sa)255206b73d0SCy Schubert static int hapd_enable_transmit_sa(void *priv, struct transmit_sa *sa)
256206b73d0SCy Schubert {
257206b73d0SCy Schubert struct hostapd_data *hapd = priv;
258206b73d0SCy Schubert
259206b73d0SCy Schubert if (!hapd->driver->enable_transmit_sa)
260206b73d0SCy Schubert return -1;
261206b73d0SCy Schubert return hapd->driver->enable_transmit_sa(hapd->drv_priv, sa);
262206b73d0SCy Schubert }
263206b73d0SCy Schubert
264206b73d0SCy Schubert
hapd_disable_transmit_sa(void * priv,struct transmit_sa * sa)265206b73d0SCy Schubert static int hapd_disable_transmit_sa(void *priv, struct transmit_sa *sa)
266206b73d0SCy Schubert {
267206b73d0SCy Schubert struct hostapd_data *hapd = priv;
268206b73d0SCy Schubert
269206b73d0SCy Schubert if (!hapd->driver->disable_transmit_sa)
270206b73d0SCy Schubert return -1;
271206b73d0SCy Schubert return hapd->driver->disable_transmit_sa(hapd->drv_priv, sa);
272206b73d0SCy Schubert }
273206b73d0SCy Schubert
274206b73d0SCy Schubert
ieee802_1x_alloc_kay_sm_hapd(struct hostapd_data * hapd,struct sta_info * sta)275206b73d0SCy Schubert int ieee802_1x_alloc_kay_sm_hapd(struct hostapd_data *hapd,
276206b73d0SCy Schubert struct sta_info *sta)
277206b73d0SCy Schubert {
278206b73d0SCy Schubert struct ieee802_1x_kay_ctx *kay_ctx;
279206b73d0SCy Schubert struct ieee802_1x_kay *res = NULL;
280206b73d0SCy Schubert enum macsec_policy policy;
281206b73d0SCy Schubert
282206b73d0SCy Schubert ieee802_1x_dealloc_kay_sm_hapd(hapd);
283206b73d0SCy Schubert
284206b73d0SCy Schubert if (!hapd->conf || hapd->conf->macsec_policy == 0)
285206b73d0SCy Schubert return 0;
286206b73d0SCy Schubert
287206b73d0SCy Schubert if (hapd->conf->macsec_policy == 1) {
288206b73d0SCy Schubert if (hapd->conf->macsec_integ_only == 1)
289206b73d0SCy Schubert policy = SHOULD_SECURE;
290206b73d0SCy Schubert else
291206b73d0SCy Schubert policy = SHOULD_ENCRYPT;
292206b73d0SCy Schubert } else {
293206b73d0SCy Schubert policy = DO_NOT_SECURE;
294206b73d0SCy Schubert }
295206b73d0SCy Schubert
296206b73d0SCy Schubert wpa_printf(MSG_DEBUG, "%s: if_name=%s", __func__, hapd->conf->iface);
297206b73d0SCy Schubert kay_ctx = os_zalloc(sizeof(*kay_ctx));
298206b73d0SCy Schubert if (!kay_ctx)
299206b73d0SCy Schubert return -1;
300206b73d0SCy Schubert
301206b73d0SCy Schubert kay_ctx->ctx = hapd;
302206b73d0SCy Schubert
303206b73d0SCy Schubert kay_ctx->macsec_init = hapd_macsec_init;
304206b73d0SCy Schubert kay_ctx->macsec_deinit = hapd_macsec_deinit;
305206b73d0SCy Schubert kay_ctx->macsec_get_capability = hapd_macsec_get_capability;
306206b73d0SCy Schubert kay_ctx->enable_protect_frames = hapd_enable_protect_frames;
307206b73d0SCy Schubert kay_ctx->enable_encrypt = hapd_enable_encrypt;
308206b73d0SCy Schubert kay_ctx->set_replay_protect = hapd_set_replay_protect;
309206b73d0SCy Schubert kay_ctx->set_current_cipher_suite = hapd_set_current_cipher_suite;
310206b73d0SCy Schubert kay_ctx->enable_controlled_port = hapd_enable_controlled_port;
311206b73d0SCy Schubert kay_ctx->get_receive_lowest_pn = hapd_get_receive_lowest_pn;
312206b73d0SCy Schubert kay_ctx->get_transmit_next_pn = hapd_get_transmit_next_pn;
313206b73d0SCy Schubert kay_ctx->set_transmit_next_pn = hapd_set_transmit_next_pn;
314206b73d0SCy Schubert kay_ctx->create_receive_sc = hapd_create_receive_sc;
315206b73d0SCy Schubert kay_ctx->delete_receive_sc = hapd_delete_receive_sc;
316206b73d0SCy Schubert kay_ctx->create_receive_sa = hapd_create_receive_sa;
317206b73d0SCy Schubert kay_ctx->delete_receive_sa = hapd_delete_receive_sa;
318206b73d0SCy Schubert kay_ctx->enable_receive_sa = hapd_enable_receive_sa;
319206b73d0SCy Schubert kay_ctx->disable_receive_sa = hapd_disable_receive_sa;
320206b73d0SCy Schubert kay_ctx->create_transmit_sc = hapd_create_transmit_sc;
321206b73d0SCy Schubert kay_ctx->delete_transmit_sc = hapd_delete_transmit_sc;
322206b73d0SCy Schubert kay_ctx->create_transmit_sa = hapd_create_transmit_sa;
323206b73d0SCy Schubert kay_ctx->delete_transmit_sa = hapd_delete_transmit_sa;
324206b73d0SCy Schubert kay_ctx->enable_transmit_sa = hapd_enable_transmit_sa;
325206b73d0SCy Schubert kay_ctx->disable_transmit_sa = hapd_disable_transmit_sa;
326206b73d0SCy Schubert
327206b73d0SCy Schubert res = ieee802_1x_kay_init(kay_ctx, policy,
328206b73d0SCy Schubert hapd->conf->macsec_replay_protect,
329206b73d0SCy Schubert hapd->conf->macsec_replay_window,
330*a90b9d01SCy Schubert hapd->conf->macsec_offload,
331206b73d0SCy Schubert hapd->conf->macsec_port,
332*a90b9d01SCy Schubert hapd->conf->mka_priority,
333*a90b9d01SCy Schubert hapd->conf->macsec_csindex,
334*a90b9d01SCy Schubert hapd->conf->iface,
335206b73d0SCy Schubert hapd->own_addr);
336206b73d0SCy Schubert /* ieee802_1x_kay_init() frees kay_ctx on failure */
337206b73d0SCy Schubert if (!res)
338206b73d0SCy Schubert return -1;
339206b73d0SCy Schubert
340206b73d0SCy Schubert hapd->kay = res;
341206b73d0SCy Schubert
342206b73d0SCy Schubert return 0;
343206b73d0SCy Schubert }
344206b73d0SCy Schubert
345206b73d0SCy Schubert
ieee802_1x_dealloc_kay_sm_hapd(struct hostapd_data * hapd)346206b73d0SCy Schubert void ieee802_1x_dealloc_kay_sm_hapd(struct hostapd_data *hapd)
347206b73d0SCy Schubert {
348206b73d0SCy Schubert if (!hapd->kay)
349206b73d0SCy Schubert return;
350206b73d0SCy Schubert
351206b73d0SCy Schubert ieee802_1x_kay_deinit(hapd->kay);
352206b73d0SCy Schubert hapd->kay = NULL;
353206b73d0SCy Schubert }
354206b73d0SCy Schubert
355206b73d0SCy Schubert
ieee802_1x_auth_get_msk(struct hostapd_data * hapd,struct sta_info * sta,u8 * msk,size_t * len)356206b73d0SCy Schubert static int ieee802_1x_auth_get_msk(struct hostapd_data *hapd,
357206b73d0SCy Schubert struct sta_info *sta, u8 *msk, size_t *len)
358206b73d0SCy Schubert {
359206b73d0SCy Schubert const u8 *key;
360206b73d0SCy Schubert size_t keylen;
361206b73d0SCy Schubert
362206b73d0SCy Schubert if (!sta->eapol_sm)
363206b73d0SCy Schubert return -1;
364206b73d0SCy Schubert
365206b73d0SCy Schubert key = ieee802_1x_get_key(sta->eapol_sm, &keylen);
366206b73d0SCy Schubert if (key == NULL) {
367206b73d0SCy Schubert wpa_printf(MSG_DEBUG,
368206b73d0SCy Schubert "MACsec: Failed to get MSK from EAPOL state machines");
369206b73d0SCy Schubert return -1;
370206b73d0SCy Schubert }
371206b73d0SCy Schubert wpa_printf(MSG_DEBUG, "MACsec: Successfully fetched key (len=%lu)",
372206b73d0SCy Schubert (unsigned long) keylen);
373206b73d0SCy Schubert wpa_hexdump_key(MSG_DEBUG, "MSK: ", key, keylen);
374206b73d0SCy Schubert
375206b73d0SCy Schubert if (keylen > *len)
376206b73d0SCy Schubert keylen = *len;
377206b73d0SCy Schubert os_memcpy(msk, key, keylen);
378206b73d0SCy Schubert *len = keylen;
379206b73d0SCy Schubert
380206b73d0SCy Schubert return 0;
381206b73d0SCy Schubert }
382206b73d0SCy Schubert
383206b73d0SCy Schubert
ieee802_1x_notify_create_actor_hapd(struct hostapd_data * hapd,struct sta_info * sta)384206b73d0SCy Schubert void * ieee802_1x_notify_create_actor_hapd(struct hostapd_data *hapd,
385206b73d0SCy Schubert struct sta_info *sta)
386206b73d0SCy Schubert {
387*a90b9d01SCy Schubert const u8 *sid;
388*a90b9d01SCy Schubert size_t sid_len;
389206b73d0SCy Schubert struct mka_key_name *ckn;
390206b73d0SCy Schubert struct mka_key *cak;
391206b73d0SCy Schubert struct mka_key *msk;
392206b73d0SCy Schubert void *res = NULL;
393206b73d0SCy Schubert
394206b73d0SCy Schubert if (!hapd->kay || hapd->kay->policy == DO_NOT_SECURE)
395206b73d0SCy Schubert return NULL;
396206b73d0SCy Schubert
397206b73d0SCy Schubert wpa_printf(MSG_DEBUG,
398206b73d0SCy Schubert "IEEE 802.1X: External notification - Create MKA for "
399206b73d0SCy Schubert MACSTR, MAC2STR(sta->addr));
400206b73d0SCy Schubert
401206b73d0SCy Schubert msk = os_zalloc(sizeof(*msk));
402206b73d0SCy Schubert ckn = os_zalloc(sizeof(*ckn));
403206b73d0SCy Schubert cak = os_zalloc(sizeof(*cak));
404*a90b9d01SCy Schubert if (!msk || !ckn || !cak)
405206b73d0SCy Schubert goto fail;
406206b73d0SCy Schubert
407206b73d0SCy Schubert msk->len = DEFAULT_KEY_LEN;
408206b73d0SCy Schubert if (ieee802_1x_auth_get_msk(hapd, sta, msk->key, &msk->len)) {
409206b73d0SCy Schubert wpa_printf(MSG_ERROR, "IEEE 802.1X: Could not get MSK");
410206b73d0SCy Schubert goto fail;
411206b73d0SCy Schubert }
412206b73d0SCy Schubert
413*a90b9d01SCy Schubert sid = ieee802_1x_get_session_id(sta->eapol_sm, &sid_len);
414*a90b9d01SCy Schubert if (!sid) {
415206b73d0SCy Schubert wpa_printf(MSG_ERROR,
416206b73d0SCy Schubert "IEEE 802.1X: Could not get EAP Session Id");
417206b73d0SCy Schubert goto fail;
418206b73d0SCy Schubert }
419206b73d0SCy Schubert
420206b73d0SCy Schubert wpa_hexdump(MSG_DEBUG, "own_addr", hapd->own_addr, ETH_ALEN);
421206b73d0SCy Schubert wpa_hexdump(MSG_DEBUG, "sta_addr", sta->addr, ETH_ALEN);
422206b73d0SCy Schubert
423206b73d0SCy Schubert /* Derive CAK from MSK */
424206b73d0SCy Schubert cak->len = DEFAULT_KEY_LEN;
425206b73d0SCy Schubert if (ieee802_1x_cak_aes_cmac(msk->key, msk->len, hapd->own_addr,
426206b73d0SCy Schubert sta->addr, cak->key, cak->len)) {
427206b73d0SCy Schubert wpa_printf(MSG_ERROR, "IEEE 802.1X: Deriving CAK failed");
428206b73d0SCy Schubert goto fail;
429206b73d0SCy Schubert }
430206b73d0SCy Schubert wpa_hexdump_key(MSG_DEBUG, "Derived CAK", cak->key, cak->len);
431206b73d0SCy Schubert
432206b73d0SCy Schubert /* Derive CKN from MSK */
433206b73d0SCy Schubert ckn->len = DEFAULT_CKN_LEN;
434206b73d0SCy Schubert if (ieee802_1x_ckn_aes_cmac(msk->key, msk->len, hapd->own_addr,
435206b73d0SCy Schubert sta->addr, sid, sid_len, ckn->name)) {
436206b73d0SCy Schubert wpa_printf(MSG_ERROR, "IEEE 802.1X: Deriving CKN failed");
437206b73d0SCy Schubert goto fail;
438206b73d0SCy Schubert }
439206b73d0SCy Schubert wpa_hexdump(MSG_DEBUG, "Derived CKN", ckn->name, ckn->len);
440206b73d0SCy Schubert
441206b73d0SCy Schubert res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, EAP_EXCHANGE,
442c1d255d3SCy Schubert true);
443206b73d0SCy Schubert
444206b73d0SCy Schubert fail:
445206b73d0SCy Schubert bin_clear_free(msk, sizeof(*msk));
446206b73d0SCy Schubert os_free(ckn);
447206b73d0SCy Schubert bin_clear_free(cak, sizeof(*cak));
448206b73d0SCy Schubert
449206b73d0SCy Schubert return res;
450206b73d0SCy Schubert }
451206b73d0SCy Schubert
452206b73d0SCy Schubert
ieee802_1x_create_preshared_mka_hapd(struct hostapd_data * hapd,struct sta_info * sta)453206b73d0SCy Schubert void * ieee802_1x_create_preshared_mka_hapd(struct hostapd_data *hapd,
454206b73d0SCy Schubert struct sta_info *sta)
455206b73d0SCy Schubert {
456206b73d0SCy Schubert struct mka_key *cak;
457206b73d0SCy Schubert struct mka_key_name *ckn;
458206b73d0SCy Schubert void *res = NULL;
459206b73d0SCy Schubert
460206b73d0SCy Schubert if ((hapd->conf->mka_psk_set & MKA_PSK_SET) != MKA_PSK_SET)
461206b73d0SCy Schubert goto end;
462206b73d0SCy Schubert
463206b73d0SCy Schubert ckn = os_zalloc(sizeof(*ckn));
464206b73d0SCy Schubert if (!ckn)
465206b73d0SCy Schubert goto end;
466206b73d0SCy Schubert
467206b73d0SCy Schubert cak = os_zalloc(sizeof(*cak));
468206b73d0SCy Schubert if (!cak)
469206b73d0SCy Schubert goto free_ckn;
470206b73d0SCy Schubert
471206b73d0SCy Schubert if (ieee802_1x_alloc_kay_sm_hapd(hapd, sta) < 0 || !hapd->kay)
472206b73d0SCy Schubert goto free_cak;
473206b73d0SCy Schubert
474206b73d0SCy Schubert if (hapd->kay->policy == DO_NOT_SECURE)
475206b73d0SCy Schubert goto dealloc;
476206b73d0SCy Schubert
477206b73d0SCy Schubert cak->len = hapd->conf->mka_cak_len;
478206b73d0SCy Schubert os_memcpy(cak->key, hapd->conf->mka_cak, cak->len);
479206b73d0SCy Schubert
480206b73d0SCy Schubert ckn->len = hapd->conf->mka_ckn_len;;
481206b73d0SCy Schubert os_memcpy(ckn->name, hapd->conf->mka_ckn, ckn->len);
482206b73d0SCy Schubert
483c1d255d3SCy Schubert res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, PSK, true);
484206b73d0SCy Schubert if (res)
485206b73d0SCy Schubert goto free_cak;
486206b73d0SCy Schubert
487206b73d0SCy Schubert dealloc:
488206b73d0SCy Schubert /* Failed to create MKA */
489206b73d0SCy Schubert ieee802_1x_dealloc_kay_sm_hapd(hapd);
490206b73d0SCy Schubert free_cak:
491206b73d0SCy Schubert os_free(cak);
492206b73d0SCy Schubert free_ckn:
493206b73d0SCy Schubert os_free(ckn);
494206b73d0SCy Schubert end:
495206b73d0SCy Schubert return res;
496206b73d0SCy Schubert }
497