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