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