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