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