1/* 2 * hostapd - PeerKey for Direct Link Setup (DLS) 3 * Copyright (c) 2006-2009, Jouni Malinen <j@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 22static 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 33struct wpa_stsl_search { 34 const u8 *addr; 35 struct wpa_state_machine *sm; 36}; 37 38 39static 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 50static 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 81void 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 145static 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 198static 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 255void 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 326void 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 369int 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