Home | History | Annotate | Download | only in ap
      1 /*
      2  * hostapd - PeerKey for Direct Link Setup (DLS)
      3  * Copyright (c) 2006-2009, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License version 2 as
      7  * published by the Free Software Foundation.
      8  *
      9  * Alternatively, this software may be distributed under the terms of BSD
     10  * license.
     11  *
     12  * See README and COPYING for more details.
     13  */
     14 
     15 #include "utils/includes.h"
     16 
     17 #include "utils/common.h"
     18 #include "utils/eloop.h"
     19 #include "crypto/sha1.h"
     20 #include "crypto/sha256.h"
     21 #include "crypto/random.h"
     22 #include "wpa_auth.h"
     23 #include "wpa_auth_i.h"
     24 #include "wpa_auth_ie.h"
     25 
     26 #ifdef CONFIG_PEERKEY
     27 
     28 static void wpa_stsl_step(void *eloop_ctx, void *timeout_ctx)
     29 {
     30 #if 0
     31 	struct wpa_authenticator *wpa_auth = eloop_ctx;
     32 	struct wpa_stsl_negotiation *neg = timeout_ctx;
     33 #endif
     34 
     35 	/* TODO: ? */
     36 }
     37 
     38 
     39 struct wpa_stsl_search {
     40 	const u8 *addr;
     41 	struct wpa_state_machine *sm;
     42 };
     43 
     44 
     45 static int wpa_stsl_select_sta(struct wpa_state_machine *sm, void *ctx)
     46 {
     47 	struct wpa_stsl_search *search = ctx;
     48 	if (os_memcmp(search->addr, sm->addr, ETH_ALEN) == 0) {
     49 		search->sm = sm;
     50 		return 1;
     51 	}
     52 	return 0;
     53 }
     54 
     55 
     56 static void wpa_smk_send_error(struct wpa_authenticator *wpa_auth,
     57 			       struct wpa_state_machine *sm, const u8 *peer,
     58 			       u16 mui, u16 error_type)
     59 {
     60 	u8 kde[2 + RSN_SELECTOR_LEN + ETH_ALEN +
     61 	       2 + RSN_SELECTOR_LEN + sizeof(struct rsn_error_kde)];
     62 	u8 *pos;
     63 	struct rsn_error_kde error;
     64 
     65 	wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
     66 			"Sending SMK Error");
     67 
     68 	pos = kde;
     69 
     70 	if (peer) {
     71 		pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN,
     72 				  NULL, 0);
     73 	}
     74 
     75 	error.mui = host_to_be16(mui);
     76 	error.error_type = host_to_be16(error_type);
     77 	pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR,
     78 			  (u8 *) &error, sizeof(error), NULL, 0);
     79 
     80 	__wpa_send_eapol(wpa_auth, sm,
     81 			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
     82 			 WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_ERROR,
     83 			 NULL, NULL, kde, pos - kde, 0, 0, 0);
     84 }
     85 
     86 
     87 void wpa_smk_m1(struct wpa_authenticator *wpa_auth,
     88 		struct wpa_state_machine *sm, struct wpa_eapol_key *key)
     89 {
     90 	struct wpa_eapol_ie_parse kde;
     91 	struct wpa_stsl_search search;
     92 	u8 *buf, *pos;
     93 	size_t buf_len;
     94 
     95 	if (wpa_parse_kde_ies((const u8 *) (key + 1),
     96 			      WPA_GET_BE16(key->key_data_length), &kde) < 0) {
     97 		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M1");
     98 		return;
     99 	}
    100 
    101 	if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
    102 	    kde.mac_addr_len < ETH_ALEN) {
    103 		wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
    104 			   "SMK M1");
    105 		return;
    106 	}
    107 
    108 	/* Initiator = sm->addr; Peer = kde.mac_addr */
    109 
    110 	search.addr = kde.mac_addr;
    111 	search.sm = NULL;
    112 	if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
    113 	    0 || search.sm == NULL) {
    114 		wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
    115 			   " aborted - STA not associated anymore",
    116 			   MAC2STR(kde.mac_addr));
    117 		wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
    118 				   STK_ERR_STA_NR);
    119 		/* FIX: wpa_stsl_remove(wpa_auth, neg); */
    120 		return;
    121 	}
    122 
    123 	buf_len = kde.rsn_ie_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
    124 	buf = os_malloc(buf_len);
    125 	if (buf == NULL)
    126 		return;
    127 	/* Initiator RSN IE */
    128 	os_memcpy(buf, kde.rsn_ie, kde.rsn_ie_len);
    129 	pos = buf + kde.rsn_ie_len;
    130 	/* Initiator MAC Address */
    131 	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->addr, ETH_ALEN,
    132 			  NULL, 0);
    133 
    134 	/* SMK M2:
    135 	 * EAPOL-Key(S=1, M=1, A=1, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
    136 	 *           MIC=MIC, DataKDs=(RSNIE_I, MAC_I KDE)
    137 	 */
    138 
    139 	wpa_auth_logger(wpa_auth, search.sm->addr, LOGGER_DEBUG,
    140 			"Sending SMK M2");
    141 
    142 	__wpa_send_eapol(wpa_auth, search.sm,
    143 			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
    144 			 WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE,
    145 			 NULL, key->key_nonce, buf, pos - buf, 0, 0, 0);
    146 
    147 	os_free(buf);
    148 }
    149 
    150 
    151 static void wpa_send_smk_m4(struct wpa_authenticator *wpa_auth,
    152 			    struct wpa_state_machine *sm,
    153 			    struct wpa_eapol_key *key,
    154 			    struct wpa_eapol_ie_parse *kde,
    155 			    const u8 *smk)
    156 {
    157 	u8 *buf, *pos;
    158 	size_t buf_len;
    159 	u32 lifetime;
    160 
    161 	/* SMK M4:
    162 	 * EAPOL-Key(S=1, M=1, A=0, I=1, K=0, SM=1, KeyRSC=0, Nonce=PNonce,
    163 	 *           MIC=MIC, DataKDs=(MAC_I KDE, INonce KDE, SMK KDE,
    164 	 *           Lifetime KDE)
    165 	 */
    166 
    167 	buf_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN +
    168 		2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
    169 		2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
    170 		2 + RSN_SELECTOR_LEN + sizeof(lifetime);
    171 	pos = buf = os_malloc(buf_len);
    172 	if (buf == NULL)
    173 		return;
    174 
    175 	/* Initiator MAC Address */
    176 	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, kde->mac_addr, ETH_ALEN,
    177 			  NULL, 0);
    178 
    179 	/* Initiator Nonce */
    180 	pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, kde->nonce, WPA_NONCE_LEN,
    181 			  NULL, 0);
    182 
    183 	/* SMK with PNonce */
    184 	pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
    185 			  key->key_nonce, WPA_NONCE_LEN);
    186 
    187 	/* Lifetime */
    188 	lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
    189 	pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
    190 			  (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
    191 
    192 	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
    193 			"Sending SMK M4");
    194 
    195 	__wpa_send_eapol(wpa_auth, sm,
    196 			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
    197 			 WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_SMK_MESSAGE,
    198 			 NULL, key->key_nonce, buf, pos - buf, 0, 1, 0);
    199 
    200 	os_free(buf);
    201 }
    202 
    203 
    204 static void wpa_send_smk_m5(struct wpa_authenticator *wpa_auth,
    205 			    struct wpa_state_machine *sm,
    206 			    struct wpa_eapol_key *key,
    207 			    struct wpa_eapol_ie_parse *kde,
    208 			    const u8 *smk, const u8 *peer)
    209 {
    210 	u8 *buf, *pos;
    211 	size_t buf_len;
    212 	u32 lifetime;
    213 
    214 	/* SMK M5:
    215 	 * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
    216 	 *           MIC=MIC, DataKDs=(RSNIE_P, MAC_P KDE, PNonce, SMK KDE,
    217 	 *                             Lifetime KDE))
    218 	 */
    219 
    220 	buf_len = kde->rsn_ie_len +
    221 		2 + RSN_SELECTOR_LEN + ETH_ALEN +
    222 		2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
    223 		2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
    224 		2 + RSN_SELECTOR_LEN + sizeof(lifetime);
    225 	pos = buf = os_malloc(buf_len);
    226 	if (buf == NULL)
    227 		return;
    228 
    229 	/* Peer RSN IE */
    230 	os_memcpy(buf, kde->rsn_ie, kde->rsn_ie_len);
    231 	pos = buf + kde->rsn_ie_len;
    232 
    233 	/* Peer MAC Address */
    234 	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, NULL, 0);
    235 
    236 	/* PNonce */
    237 	pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, key->key_nonce,
    238 			  WPA_NONCE_LEN, NULL, 0);
    239 
    240 	/* SMK and INonce */
    241 	pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
    242 			  kde->nonce, WPA_NONCE_LEN);
    243 
    244 	/* Lifetime */
    245 	lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
    246 	pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
    247 			  (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
    248 
    249 	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
    250 			"Sending SMK M5");
    251 
    252 	__wpa_send_eapol(wpa_auth, sm,
    253 			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
    254 			 WPA_KEY_INFO_SMK_MESSAGE,
    255 			 NULL, kde->nonce, buf, pos - buf, 0, 1, 0);
    256 
    257 	os_free(buf);
    258 }
    259 
    260 
    261 void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
    262 		struct wpa_state_machine *sm, struct wpa_eapol_key *key)
    263 {
    264 	struct wpa_eapol_ie_parse kde;
    265 	struct wpa_stsl_search search;
    266 	u8 smk[32], buf[ETH_ALEN + 8 + 2 * WPA_NONCE_LEN], *pos;
    267 
    268 	if (wpa_parse_kde_ies((const u8 *) (key + 1),
    269 			      WPA_GET_BE16(key->key_data_length), &kde) < 0) {
    270 		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M3");
    271 		return;
    272 	}
    273 
    274 	if (kde.rsn_ie == NULL ||
    275 	    kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
    276 	    kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN) {
    277 		wpa_printf(MSG_INFO, "RSN: No RSN IE, MAC address KDE, or "
    278 			   "Nonce KDE in SMK M3");
    279 		return;
    280 	}
    281 
    282 	/* Peer = sm->addr; Initiator = kde.mac_addr;
    283 	 * Peer Nonce = key->key_nonce; Initiator Nonce = kde.nonce */
    284 
    285 	search.addr = kde.mac_addr;
    286 	search.sm = NULL;
    287 	if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
    288 	    0 || search.sm == NULL) {
    289 		wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
    290 			   " aborted - STA not associated anymore",
    291 			   MAC2STR(kde.mac_addr));
    292 		wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
    293 				   STK_ERR_STA_NR);
    294 		/* FIX: wpa_stsl_remove(wpa_auth, neg); */
    295 		return;
    296 	}
    297 
    298 	if (random_get_bytes(smk, PMK_LEN)) {
    299 		wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK");
    300 		return;
    301 	}
    302 
    303 	/* SMK = PRF-256(Random number, "SMK Derivation",
    304 	 *               AA || Time || INonce || PNonce)
    305 	 */
    306 	os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
    307 	pos = buf + ETH_ALEN;
    308 	wpa_get_ntp_timestamp(pos);
    309 	pos += 8;
    310 	os_memcpy(pos, kde.nonce, WPA_NONCE_LEN);
    311 	pos += WPA_NONCE_LEN;
    312 	os_memcpy(pos, key->key_nonce, WPA_NONCE_LEN);
    313 #ifdef CONFIG_IEEE80211W
    314 	sha256_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
    315 		   smk, PMK_LEN);
    316 #else /* CONFIG_IEEE80211W */
    317 	sha1_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
    318 		 smk, PMK_LEN);
    319 #endif /* CONFIG_IEEE80211W */
    320 
    321 	wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", smk, PMK_LEN);
    322 
    323 	wpa_send_smk_m4(wpa_auth, sm, key, &kde, smk);
    324 	wpa_send_smk_m5(wpa_auth, search.sm, key, &kde, smk, sm->addr);
    325 
    326 	/* Authenticator does not need SMK anymore and it is required to forget
    327 	 * it. */
    328 	os_memset(smk, 0, sizeof(*smk));
    329 }
    330 
    331 
    332 void wpa_smk_error(struct wpa_authenticator *wpa_auth,
    333 		   struct wpa_state_machine *sm, struct wpa_eapol_key *key)
    334 {
    335 	struct wpa_eapol_ie_parse kde;
    336 	struct wpa_stsl_search search;
    337 	struct rsn_error_kde error;
    338 	u16 mui, error_type;
    339 
    340 	if (wpa_parse_kde_ies((const u8 *) (key + 1),
    341 			      WPA_GET_BE16(key->key_data_length), &kde) < 0) {
    342 		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
    343 		return;
    344 	}
    345 
    346 	if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
    347 	    kde.error == NULL || kde.error_len < sizeof(error)) {
    348 		wpa_printf(MSG_INFO, "RSN: No MAC address or Error KDE in "
    349 			   "SMK Error");
    350 		return;
    351 	}
    352 
    353 	search.addr = kde.mac_addr;
    354 	search.sm = NULL;
    355 	if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
    356 	    0 || search.sm == NULL) {
    357 		wpa_printf(MSG_DEBUG, "RSN: Peer STA " MACSTR " not "
    358 			   "associated for SMK Error message from " MACSTR,
    359 			   MAC2STR(kde.mac_addr), MAC2STR(sm->addr));
    360 		return;
    361 	}
    362 
    363 	os_memcpy(&error, kde.error, sizeof(error));
    364 	mui = be_to_host16(error.mui);
    365 	error_type = be_to_host16(error.error_type);
    366 	wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
    367 			 "STA reported SMK Error: Peer " MACSTR
    368 			 " MUI %d Error Type %d",
    369 			 MAC2STR(kde.mac_addr), mui, error_type);
    370 
    371 	wpa_smk_send_error(wpa_auth, search.sm, sm->addr, mui, error_type);
    372 }
    373 
    374 
    375 int wpa_stsl_remove(struct wpa_authenticator *wpa_auth,
    376 		    struct wpa_stsl_negotiation *neg)
    377 {
    378 	struct wpa_stsl_negotiation *pos, *prev;
    379 
    380 	if (wpa_auth == NULL)
    381 		return -1;
    382 	pos = wpa_auth->stsl_negotiations;
    383 	prev = NULL;
    384 	while (pos) {
    385 		if (pos == neg) {
    386 			if (prev)
    387 				prev->next = pos->next;
    388 			else
    389 				wpa_auth->stsl_negotiations = pos->next;
    390 
    391 			eloop_cancel_timeout(wpa_stsl_step, wpa_auth, pos);
    392 			os_free(pos);
    393 			return 0;
    394 		}
    395 		prev = pos;
    396 		pos = pos->next;
    397 	}
    398 
    399 	return -1;
    400 }
    401 
    402 #endif /* CONFIG_PEERKEY */
    403