Home | History | Annotate | Line # | Download | only in wpa_supplicant
wpas_kay.c revision 1.1.1.5
      1 /*
      2  * IEEE 802.1X-2010 KaY Interface
      3  * Copyright (c) 2013-2014, Qualcomm Atheros, 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 "utils/includes.h"
     10 
     11 #include "utils/common.h"
     12 #include "eap_peer/eap.h"
     13 #include "eap_peer/eap_i.h"
     14 #include "eapol_supp/eapol_supp_sm.h"
     15 #include "pae/ieee802_1x_key.h"
     16 #include "pae/ieee802_1x_kay.h"
     17 #include "wpa_supplicant_i.h"
     18 #include "config.h"
     19 #include "config_ssid.h"
     20 #include "driver_i.h"
     21 #include "wpas_kay.h"
     22 
     23 
     24 #define DEFAULT_KEY_LEN		16
     25 /* secure Connectivity Association Key Name (CKN) */
     26 #define DEFAULT_CKN_LEN		16
     27 
     28 
     29 static int wpas_macsec_init(void *priv, struct macsec_init_params *params)
     30 {
     31 	return wpa_drv_macsec_init(priv, params);
     32 }
     33 
     34 
     35 static int wpas_macsec_deinit(void *priv)
     36 {
     37 	return wpa_drv_macsec_deinit(priv);
     38 }
     39 
     40 
     41 static int wpas_macsec_get_capability(void *priv, enum macsec_cap *cap)
     42 {
     43 	return wpa_drv_macsec_get_capability(priv, cap);
     44 }
     45 
     46 
     47 static int wpas_enable_protect_frames(void *wpa_s, bool enabled)
     48 {
     49 	return wpa_drv_enable_protect_frames(wpa_s, enabled);
     50 }
     51 
     52 
     53 static int wpas_enable_encrypt(void *wpa_s, bool enabled)
     54 {
     55 	return wpa_drv_enable_encrypt(wpa_s, enabled);
     56 }
     57 
     58 
     59 static int wpas_set_replay_protect(void *wpa_s, bool enabled, u32 window)
     60 {
     61 	return wpa_drv_set_replay_protect(wpa_s, enabled, window);
     62 }
     63 
     64 
     65 static int wpas_set_current_cipher_suite(void *wpa_s, u64 cs)
     66 {
     67 	return wpa_drv_set_current_cipher_suite(wpa_s, cs);
     68 }
     69 
     70 
     71 static int wpas_enable_controlled_port(void *wpa_s, bool enabled)
     72 {
     73 	return wpa_drv_enable_controlled_port(wpa_s, enabled);
     74 }
     75 
     76 
     77 static int wpas_get_receive_lowest_pn(void *wpa_s, struct receive_sa *sa)
     78 {
     79 	return wpa_drv_get_receive_lowest_pn(wpa_s, sa);
     80 }
     81 
     82 
     83 static int wpas_get_transmit_next_pn(void *wpa_s, struct transmit_sa *sa)
     84 {
     85 	return wpa_drv_get_transmit_next_pn(wpa_s, sa);
     86 }
     87 
     88 
     89 static int wpas_set_transmit_next_pn(void *wpa_s, struct transmit_sa *sa)
     90 {
     91 	return wpa_drv_set_transmit_next_pn(wpa_s, sa);
     92 }
     93 
     94 
     95 static int wpas_set_receive_lowest_pn(void *wpa_s, struct receive_sa *sa)
     96 {
     97 	return wpa_drv_set_receive_lowest_pn(wpa_s, sa);
     98 }
     99 
    100 
    101 static int wpas_set_offload(void *wpa_s, u8 offload)
    102 {
    103 	return wpa_drv_set_offload(wpa_s, offload);
    104 }
    105 
    106 
    107 static unsigned int conf_offset_val(enum confidentiality_offset co)
    108 {
    109 	switch (co) {
    110 	case CONFIDENTIALITY_OFFSET_30:
    111 		return 30;
    112 	case CONFIDENTIALITY_OFFSET_50:
    113 		return 50;
    114 	default:
    115 		return 0;
    116 	}
    117 }
    118 
    119 
    120 static int wpas_create_receive_sc(void *wpa_s, struct receive_sc *sc,
    121 				  enum validate_frames vf,
    122 				  enum confidentiality_offset co)
    123 {
    124 	return wpa_drv_create_receive_sc(wpa_s, sc, conf_offset_val(co), vf);
    125 }
    126 
    127 
    128 static int wpas_delete_receive_sc(void *wpa_s, struct receive_sc *sc)
    129 {
    130 	return wpa_drv_delete_receive_sc(wpa_s, sc);
    131 }
    132 
    133 
    134 static int wpas_create_receive_sa(void *wpa_s, struct receive_sa *sa)
    135 {
    136 	return wpa_drv_create_receive_sa(wpa_s, sa);
    137 }
    138 
    139 
    140 static int wpas_delete_receive_sa(void *wpa_s, struct receive_sa *sa)
    141 {
    142 	return wpa_drv_delete_receive_sa(wpa_s, sa);
    143 }
    144 
    145 
    146 static int wpas_enable_receive_sa(void *wpa_s, struct receive_sa *sa)
    147 {
    148 	return wpa_drv_enable_receive_sa(wpa_s, sa);
    149 }
    150 
    151 
    152 static int wpas_disable_receive_sa(void *wpa_s, struct receive_sa *sa)
    153 {
    154 	return wpa_drv_disable_receive_sa(wpa_s, sa);
    155 }
    156 
    157 
    158 static int
    159 wpas_create_transmit_sc(void *wpa_s, struct transmit_sc *sc,
    160 			enum confidentiality_offset co)
    161 {
    162 	return wpa_drv_create_transmit_sc(wpa_s, sc, conf_offset_val(co));
    163 }
    164 
    165 
    166 static int wpas_delete_transmit_sc(void *wpa_s, struct transmit_sc *sc)
    167 {
    168 	return wpa_drv_delete_transmit_sc(wpa_s, sc);
    169 }
    170 
    171 
    172 static int wpas_create_transmit_sa(void *wpa_s, struct transmit_sa *sa)
    173 {
    174 	return wpa_drv_create_transmit_sa(wpa_s, sa);
    175 }
    176 
    177 
    178 static int wpas_delete_transmit_sa(void *wpa_s, struct transmit_sa *sa)
    179 {
    180 	return wpa_drv_delete_transmit_sa(wpa_s, sa);
    181 }
    182 
    183 
    184 static int wpas_enable_transmit_sa(void *wpa_s, struct transmit_sa *sa)
    185 {
    186 	return wpa_drv_enable_transmit_sa(wpa_s, sa);
    187 }
    188 
    189 
    190 static int wpas_disable_transmit_sa(void *wpa_s, struct transmit_sa *sa)
    191 {
    192 	return wpa_drv_disable_transmit_sa(wpa_s, sa);
    193 }
    194 
    195 
    196 int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
    197 {
    198 	struct ieee802_1x_kay_ctx *kay_ctx;
    199 	struct ieee802_1x_kay *res = NULL;
    200 	enum macsec_policy policy;
    201 
    202 	ieee802_1x_dealloc_kay_sm(wpa_s);
    203 
    204 	if (!ssid || ssid->macsec_policy == 0)
    205 		return 0;
    206 
    207 	if (ssid->macsec_policy == 1) {
    208 		if (ssid->macsec_integ_only == 1)
    209 			policy = SHOULD_SECURE;
    210 		else
    211 			policy = SHOULD_ENCRYPT;
    212 	} else {
    213 		policy = DO_NOT_SECURE;
    214 	}
    215 
    216 	kay_ctx = os_zalloc(sizeof(*kay_ctx));
    217 	if (!kay_ctx)
    218 		return -1;
    219 
    220 	kay_ctx->ctx = wpa_s;
    221 
    222 	kay_ctx->macsec_init = wpas_macsec_init;
    223 	kay_ctx->macsec_deinit = wpas_macsec_deinit;
    224 	kay_ctx->macsec_get_capability = wpas_macsec_get_capability;
    225 	kay_ctx->enable_protect_frames = wpas_enable_protect_frames;
    226 	kay_ctx->enable_encrypt = wpas_enable_encrypt;
    227 	kay_ctx->set_replay_protect = wpas_set_replay_protect;
    228 	kay_ctx->set_offload = wpas_set_offload;
    229 	kay_ctx->set_current_cipher_suite = wpas_set_current_cipher_suite;
    230 	kay_ctx->enable_controlled_port = wpas_enable_controlled_port;
    231 	kay_ctx->get_receive_lowest_pn = wpas_get_receive_lowest_pn;
    232 	kay_ctx->get_transmit_next_pn = wpas_get_transmit_next_pn;
    233 	kay_ctx->set_transmit_next_pn = wpas_set_transmit_next_pn;
    234 	kay_ctx->set_receive_lowest_pn = wpas_set_receive_lowest_pn;
    235 	kay_ctx->create_receive_sc = wpas_create_receive_sc;
    236 	kay_ctx->delete_receive_sc = wpas_delete_receive_sc;
    237 	kay_ctx->create_receive_sa = wpas_create_receive_sa;
    238 	kay_ctx->delete_receive_sa = wpas_delete_receive_sa;
    239 	kay_ctx->enable_receive_sa = wpas_enable_receive_sa;
    240 	kay_ctx->disable_receive_sa = wpas_disable_receive_sa;
    241 	kay_ctx->create_transmit_sc = wpas_create_transmit_sc;
    242 	kay_ctx->delete_transmit_sc = wpas_delete_transmit_sc;
    243 	kay_ctx->create_transmit_sa = wpas_create_transmit_sa;
    244 	kay_ctx->delete_transmit_sa = wpas_delete_transmit_sa;
    245 	kay_ctx->enable_transmit_sa = wpas_enable_transmit_sa;
    246 	kay_ctx->disable_transmit_sa = wpas_disable_transmit_sa;
    247 
    248 	res = ieee802_1x_kay_init(kay_ctx, policy, ssid->macsec_replay_protect,
    249 				  ssid->macsec_replay_window,
    250 				  ssid->macsec_offload, ssid->macsec_port,
    251 				  ssid->mka_priority, ssid->macsec_csindex,
    252 				  wpa_s->ifname, wpa_s->own_addr);
    253 	/* ieee802_1x_kay_init() frees kay_ctx on failure */
    254 	if (res == NULL)
    255 		return -1;
    256 
    257 	wpa_s->kay = res;
    258 
    259 	return 0;
    260 }
    261 
    262 
    263 void ieee802_1x_dealloc_kay_sm(struct wpa_supplicant *wpa_s)
    264 {
    265 	if (!wpa_s->kay)
    266 		return;
    267 
    268 	ieee802_1x_kay_deinit(wpa_s->kay);
    269 	wpa_s->kay = NULL;
    270 }
    271 
    272 
    273 static int ieee802_1x_auth_get_msk(struct wpa_supplicant *wpa_s, const u8 *addr,
    274 				   u8 *msk, size_t *len)
    275 {
    276 	u8 key[EAP_MSK_LEN];
    277 	size_t keylen;
    278 	struct eapol_sm *sm;
    279 	int res;
    280 
    281 	sm = wpa_s->eapol;
    282 	if (sm == NULL)
    283 		return -1;
    284 
    285 	keylen = EAP_MSK_LEN;
    286 	res = eapol_sm_get_key(sm, key, keylen);
    287 	if (res) {
    288 		wpa_printf(MSG_DEBUG,
    289 			   "Failed to get MSK from EAPOL state machines");
    290 		return -1;
    291 	}
    292 
    293 	if (keylen > *len)
    294 		keylen = *len;
    295 	os_memcpy(msk, key, keylen);
    296 	*len = keylen;
    297 
    298 	return 0;
    299 }
    300 
    301 
    302 void * ieee802_1x_notify_create_actor(struct wpa_supplicant *wpa_s,
    303 				      const u8 *peer_addr)
    304 {
    305 	const u8 *sid;
    306 	size_t sid_len;
    307 	struct mka_key_name *ckn;
    308 	struct mka_key *cak;
    309 	struct mka_key *msk;
    310 	void *res = NULL;
    311 
    312 	if (!wpa_s->kay || wpa_s->kay->policy == DO_NOT_SECURE)
    313 		return NULL;
    314 
    315 	wpa_printf(MSG_DEBUG,
    316 		   "IEEE 802.1X: External notification - Create MKA for "
    317 		   MACSTR, MAC2STR(peer_addr));
    318 
    319 	msk = os_zalloc(sizeof(*msk));
    320 	ckn = os_zalloc(sizeof(*ckn));
    321 	cak = os_zalloc(sizeof(*cak));
    322 	if (!msk || !ckn || !cak)
    323 		goto fail;
    324 
    325 	msk->len = DEFAULT_KEY_LEN;
    326 	if (ieee802_1x_auth_get_msk(wpa_s, wpa_s->bssid, msk->key, &msk->len)) {
    327 		wpa_printf(MSG_ERROR, "IEEE 802.1X: Could not get MSK");
    328 		goto fail;
    329 	}
    330 
    331 	sid = eapol_sm_get_session_id(wpa_s->eapol, &sid_len);
    332 	if (!sid) {
    333 		wpa_printf(MSG_ERROR,
    334 			   "IEEE 802.1X: Could not get EAP Session Id");
    335 		goto fail;
    336 	}
    337 
    338 	/* Derive CAK from MSK */
    339 	cak->len = DEFAULT_KEY_LEN;
    340 	if (ieee802_1x_cak_aes_cmac(msk->key, msk->len, wpa_s->own_addr,
    341 				    peer_addr, cak->key, cak->len)) {
    342 		wpa_printf(MSG_ERROR,
    343 			   "IEEE 802.1X: Deriving CAK failed");
    344 		goto fail;
    345 	}
    346 	wpa_hexdump_key(MSG_DEBUG, "Derived CAK", cak->key, cak->len);
    347 
    348 	/* Derive CKN from MSK */
    349 	ckn->len = DEFAULT_CKN_LEN;
    350 	if (ieee802_1x_ckn_aes_cmac(msk->key, msk->len, wpa_s->own_addr,
    351 				    peer_addr, sid, sid_len, ckn->name)) {
    352 		wpa_printf(MSG_ERROR,
    353 			   "IEEE 802.1X: Deriving CKN failed");
    354 		goto fail;
    355 	}
    356 	wpa_hexdump(MSG_DEBUG, "Derived CKN", ckn->name, ckn->len);
    357 
    358 	res = ieee802_1x_kay_create_mka(wpa_s->kay, ckn, cak, 0,
    359 					EAP_EXCHANGE, false);
    360 
    361 fail:
    362 	if (msk) {
    363 		os_memset(msk, 0, sizeof(*msk));
    364 		os_free(msk);
    365 	}
    366 	os_free(ckn);
    367 	if (cak) {
    368 		os_memset(cak, 0, sizeof(*cak));
    369 		os_free(cak);
    370 	}
    371 
    372 	return res;
    373 }
    374 
    375 
    376 void * ieee802_1x_create_preshared_mka(struct wpa_supplicant *wpa_s,
    377 				       struct wpa_ssid *ssid)
    378 {
    379 	struct mka_key *cak;
    380 	struct mka_key_name *ckn;
    381 	void *res = NULL;
    382 
    383 	if ((ssid->mka_psk_set & MKA_PSK_SET) != MKA_PSK_SET)
    384 		goto end;
    385 
    386 	ckn = os_zalloc(sizeof(*ckn));
    387 	if (!ckn)
    388 		goto end;
    389 
    390 	cak = os_zalloc(sizeof(*cak));
    391 	if (!cak)
    392 		goto free_ckn;
    393 
    394 	if (ieee802_1x_alloc_kay_sm(wpa_s, ssid) < 0 || !wpa_s->kay)
    395 		goto free_cak;
    396 
    397 	if (wpa_s->kay->policy == DO_NOT_SECURE)
    398 		goto dealloc;
    399 
    400 	cak->len = ssid->mka_cak_len;
    401 	os_memcpy(cak->key, ssid->mka_cak, cak->len);
    402 
    403 	ckn->len = ssid->mka_ckn_len;
    404 	os_memcpy(ckn->name, ssid->mka_ckn, ckn->len);
    405 
    406 	res = ieee802_1x_kay_create_mka(wpa_s->kay, ckn, cak, 0, PSK, false);
    407 	if (res)
    408 		goto free_cak;
    409 
    410 dealloc:
    411 	/* Failed to create MKA */
    412 	ieee802_1x_dealloc_kay_sm(wpa_s);
    413 free_cak:
    414 	os_free(cak);
    415 free_ckn:
    416 	os_free(ckn);
    417 end:
    418 	return res;
    419 }
    420