1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * WPA Supplicant - PeerKey for Direct Link Setup (DLS) 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi> 4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify 6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation. 8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license. 11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details. 13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_PEERKEY 18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 20b349ef9e9f3f5399bf96b3c1c663cb9e547f50a1Dmitry Shmidt#include "crypto/sha1.h" 21b349ef9e9f3f5399bf96b3c1c663cb9e547f50a1Dmitry Shmidt#include "crypto/sha256.h" 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eloop.h" 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wpa.h" 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wpa_i.h" 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wpa_ie.h" 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "ieee802_11_defs.h" 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "peerkey.h" 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len) 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, ie, ie_len); 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return pos + ie_len; 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len) 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = WLAN_EID_VENDOR_SPECIFIC; 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = RSN_SELECTOR_LEN + data_len; 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RSN_SELECTOR_PUT(pos, kde); 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += RSN_SELECTOR_LEN; 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, data, data_len); 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += data_len; 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return pos; 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_smk_timeout(void *eloop_ctx, void *timeout_ctx) 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#if 0 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_sm *sm = eloop_ctx; 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey = timeout_ctx; 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: time out SMK and any STK that was generated using this SMK */ 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_peerkey_free(struct wpa_sm *sm, 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey) 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey); 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(peerkey); 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst, 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *peer, 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 mui, u16 error_type, int ver) 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t rlen; 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_key *err; 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct rsn_error_kde error; 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *rbuf, *pos; 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t kde_len; 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 key_info; 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error); 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peer) 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN; 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt NULL, sizeof(*err) + kde_len, &rlen, 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (void *) &err); 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (rbuf == NULL) 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt err->type = EAPOL_KEY_TYPE_RSN; 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR | 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_KEY_INFO_REQUEST; 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(err->key_info, key_info); 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(err->key_length, 0); 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(err->replay_counter, sm->request_counter, 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_REPLAY_COUNTER_LEN); 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(err->key_data_length, (u16) kde_len); 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = (u8 *) (err + 1); 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peer) { 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Peer MAC Address KDE */ 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Error KDE */ 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt error.mui = host_to_be16(mui); 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt error.error_type = host_to_be16(error_type); 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error)); 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peer) { 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer " 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MACSTR " mui %d error_type %d)", 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MAC2STR(peer), mui, error_type); 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error " 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(mui %d error_type %d)", mui, error_type); 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL, 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rbuf, rlen, err->key_mic); 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_supplicant_send_smk_m3(struct wpa_sm *sm, 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const unsigned char *src_addr, 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpa_eapol_key *key, 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ver, struct wpa_peerkey *peerkey) 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t rlen; 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_key *reply; 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *rbuf, *pos; 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t kde_len; 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 key_info; 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */ 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde_len = peerkey->rsnie_p_len + 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 2 + RSN_SELECTOR_LEN + ETH_ALEN + 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN; 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt NULL, sizeof(*reply) + kde_len, &rlen, 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (void *) &reply); 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (rbuf == NULL) 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt reply->type = EAPOL_KEY_TYPE_RSN; 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_KEY_INFO_SECURE; 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(reply->key_info, key_info); 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(reply->key_length, 0); 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(reply->replay_counter, key->replay_counter, 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_REPLAY_COUNTER_LEN); 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN); 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(reply->key_data_length, (u16) kde_len); 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = (u8 *) (reply + 1); 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Peer RSN IE */ 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len); 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Initiator MAC Address KDE */ 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN); 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Initiator Nonce */ 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN); 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3"); 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL, 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rbuf, rlen, reply->key_mic); 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_supplicant_process_smk_m2( 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_sm *sm, const unsigned char *src_addr, 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpa_eapol_key *key, size_t extra_len, int ver) 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey; 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_ie_parse kde; 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ie_data ie; 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int cipher; 187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct rsn_ie_hdr *hdr; 188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *pos; 189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK M2"); 191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { 193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: SMK handshake not allowed for " 194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "the current network"); 195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < 199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 0) { 200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M2"); 201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (kde.rsn_ie == NULL || kde.mac_addr == NULL || 205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde.mac_addr_len < ETH_ALEN) { 206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in " 207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "SMK M2"); 208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK M2 - SMK initiator " MACSTR, 212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MAC2STR(kde.mac_addr)); 213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (kde.rsn_ie_len > PEERKEY_MAX_IE_LEN) { 215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: Too long Initiator RSN IE in SMK " 216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "M2"); 217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) { 221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse RSN IE in SMK M2"); 222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher; 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (cipher & WPA_CIPHER_CCMP) { 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey"); 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cipher = WPA_CIPHER_CCMP; 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (cipher & WPA_CIPHER_TKIP) { 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey"); 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cipher = WPA_CIPHER_TKIP; 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2"); 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr, 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt STK_MUI_SMK, STK_ERR_CPHR_NS, 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ver); 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: find existing entry and if found, use that instead of adding 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * a new one; how to handle the case where both ends initiate at the 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * same time? */ 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey = os_zalloc(sizeof(*peerkey)); 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peerkey == NULL) 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN); 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN); 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len); 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->rsnie_i_len = kde.rsn_ie_len; 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->cipher = cipher; 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211W 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ie.key_mgmt & (WPA_KEY_MGMT_IEEE8021X_SHA256 | 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_KEY_MGMT_PSK_SHA256)) 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->use_sha256 = 1; 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_get_random(peerkey->pnonce, WPA_NONCE_LEN)) { 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_msg(sm->ctx->ctx, MSG_WARNING, 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "WPA: Failed to get random data for PNonce"); 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_peerkey_free(sm, peerkey); 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr = (struct rsn_ie_hdr *) peerkey->rsnie_p; 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_LE16(hdr->version, RSN_VERSION); 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = (u8 *) (hdr + 1); 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Group Suite can be anything for SMK RSN IE; receiver will just 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * ignore it. */ 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += RSN_SELECTOR_LEN; 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Include only the selected cipher in pairwise cipher suite */ 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_LE16(pos, 1); 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (cipher == WPA_CIPHER_CCMP) 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else if (cipher == WPA_CIPHER_TKIP) 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += RSN_SELECTOR_LEN; 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr->len = (pos - peerkey->rsnie_p) - 2; 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->rsnie_p_len = pos - peerkey->rsnie_p; 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake", 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->rsnie_p, peerkey->rsnie_p_len); 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_send_smk_m3(sm, src_addr, key, ver, peerkey); 287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->next = sm->peerkey; 289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->peerkey = peerkey; 290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * rsn_smkid - Derive SMK identifier 297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @smk: Station master key (32 bytes) 298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @pnonce: Peer Nonce 299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @mac_p: Peer MAC address 300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @inonce: Initiator Nonce 301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @mac_i: Initiator MAC address 302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @use_sha256: Whether to use SHA256-based KDF 303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 8.5.1.4 Station to station (STK) key hierarchy 305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I) 306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p, 308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *inonce, const u8 *mac_i, u8 *smkid, 309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int use_sha256) 310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *title = "SMK Name"; 312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *addr[5]; 313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const size_t len[5] = { 8, WPA_NONCE_LEN, ETH_ALEN, WPA_NONCE_LEN, 314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ETH_ALEN }; 315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unsigned char hash[SHA256_MAC_LEN]; 316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[0] = (u8 *) title; 318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[1] = pnonce; 319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[2] = mac_p; 320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[3] = inonce; 321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[4] = mac_i; 322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211W 324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (use_sha256) 325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash); 326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash); 329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(smkid, hash, PMKID_LEN); 330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm, 334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey) 335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t mlen; 337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_key *msg; 338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *mbuf; 339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t kde_len; 340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 key_info, ver; 341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; 343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(*msg) + kde_len, &mlen, 346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (void *) &msg); 347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (mbuf == NULL) 348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg->type = EAPOL_KEY_TYPE_RSN; 351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peerkey->cipher == WPA_CIPHER_CCMP) 353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK; 358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(msg->key_info, key_info); 359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peerkey->cipher == WPA_CIPHER_CCMP) 361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(msg->key_length, 16); 362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(msg->key_length, 32); 364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(msg->replay_counter, peerkey->replay_counter, 366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_REPLAY_COUNTER_LEN); 367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); 368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(msg->key_data_length, kde_len); 370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_add_kde((u8 *) (msg + 1), RSN_KEY_DATA_PMKID, 371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->smkid, PMKID_LEN); 372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_get_random(peerkey->inonce, WPA_NONCE_LEN)) { 374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_msg(sm->ctx->ctx, MSG_WARNING, 375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "RSN: Failed to get random data for INonce (STK)"); 376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(mbuf); 377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: INonce for STK 4-Way Handshake", 380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->inonce, WPA_NONCE_LEN); 381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN); 382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR, 384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MAC2STR(peerkey->addr)); 385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_eapol_key_send(sm, NULL, ver, peerkey->addr, ETH_P_EAPOL, 386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt mbuf, mlen, NULL); 387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm, 391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey) 392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t mlen; 394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_key *msg; 395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *mbuf, *pos; 396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t kde_len; 397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 key_info, ver; 398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt be32 lifetime; 399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde_len = peerkey->rsnie_i_len + 401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 2 + RSN_SELECTOR_LEN + sizeof(lifetime); 402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(*msg) + kde_len, &mlen, 405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (void *) &msg); 406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (mbuf == NULL) 407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg->type = EAPOL_KEY_TYPE_RSN; 410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peerkey->cipher == WPA_CIPHER_CCMP) 412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK | 417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; 418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(msg->key_info, key_info); 419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peerkey->cipher == WPA_CIPHER_CCMP) 421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(msg->key_length, 16); 422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(msg->key_length, 32); 424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(msg->replay_counter, peerkey->replay_counter, 426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_REPLAY_COUNTER_LEN); 427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); 428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(msg->key_data_length, kde_len); 430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = (u8 *) (msg + 1); 431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); 432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt lifetime = host_to_be32(peerkey->lifetime); 433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, 434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (u8 *) &lifetime, sizeof(lifetime)); 435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN); 437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR, 439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MAC2STR(peerkey->addr)); 440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_eapol_key_send(sm, peerkey->stk.kck, ver, peerkey->addr, 441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ETH_P_EAPOL, mbuf, mlen, msg->key_mic); 442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_supplicant_process_smk_m4(struct wpa_peerkey *peerkey, 446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_ie_parse *kde) 447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK M4 (Initiator " MACSTR ")", 449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MAC2STR(kde->mac_addr)); 450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(kde->smk + PMK_LEN, peerkey->pnonce, WPA_NONCE_LEN) != 0) 452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt { 453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: PNonce in SMK KDE does not " 454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "match with the one used in SMK M3"); 455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(kde->nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) { 459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: INonce in SMK M4 did not " 460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "match with the one received in SMK M2"); 461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_supplicant_process_smk_m5(struct wpa_sm *sm, 469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const unsigned char *src_addr, 470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpa_eapol_key *key, 471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ver, 472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey, 473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_ie_parse *kde) 474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int cipher; 476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ie_data ie; 477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK M5 (Peer " MACSTR ")", 479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MAC2STR(kde->mac_addr)); 480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (kde->rsn_ie == NULL || kde->rsn_ie_len > PEERKEY_MAX_IE_LEN || 481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0) { 482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: No RSN IE in SMK M5"); 483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: abort negotiation */ 484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(key->key_nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) { 488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: Key Nonce in SMK M5 does " 489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "not match with INonce used in SMK M1"); 490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(kde->smk + PMK_LEN, peerkey->inonce, WPA_NONCE_LEN) != 0) 494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt { 495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: INonce in SMK KDE does not " 496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "match with the one used in SMK M1"); 497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(peerkey->rsnie_p, kde->rsn_ie, kde->rsn_ie_len); 501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->rsnie_p_len = kde->rsn_ie_len; 502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(peerkey->pnonce, kde->nonce, WPA_NONCE_LEN); 503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher; 505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (cipher & WPA_CIPHER_CCMP) { 506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey"); 507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->cipher = WPA_CIPHER_CCMP; 508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (cipher & WPA_CIPHER_TKIP) { 509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey"); 510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->cipher = WPA_CIPHER_TKIP; 511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: SMK Peer STA " MACSTR " selected " 513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "unacceptable cipher", MAC2STR(kde->mac_addr)); 514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_send_smk_error(sm, src_addr, kde->mac_addr, 515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt STK_MUI_SMK, STK_ERR_CPHR_NS, 516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ver); 517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: abort negotiation */ 518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_supplicant_process_smk_m45( 526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_sm *sm, const unsigned char *src_addr, 527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpa_eapol_key *key, size_t extra_len, int ver) 528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey; 530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_ie_parse kde; 531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 lifetime; 532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct os_time now; 533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { 535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for " 536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "the current network"); 537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < 541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 0) { 542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5"); 543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || 547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN || 548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN || 549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde.lifetime == NULL || kde.lifetime_len < 4) { 550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or " 551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Lifetime KDE in SMK M4/M5"); 552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { 556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 && 557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(peerkey->initiator ? peerkey->inonce : 558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->pnonce, 559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key->key_nonce, WPA_NONCE_LEN) == 0) 560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peerkey == NULL) { 563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found " 564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "for SMK M4/M5: peer " MACSTR, 565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MAC2STR(kde.mac_addr)); 566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peerkey->initiator) { 570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_supplicant_process_smk_m5(sm, src_addr, key, ver, 571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey, &kde) < 0) 572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_supplicant_process_smk_m4(peerkey, &kde) < 0) 575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(peerkey->smk, kde.smk, PMK_LEN); 579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->smk_complete = 1; 580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN); 581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt lifetime = WPA_GET_BE32(kde.lifetime); 582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime); 583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (lifetime > 1000000000) 584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt lifetime = 1000000000; /* avoid overflowing expiration time */ 585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->lifetime = lifetime; 586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_get_time(&now); 587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->expiration = now.sec + lifetime; 588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout, 589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm, peerkey); 590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peerkey->initiator) { 592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr, 593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->inonce, sm->own_addr, peerkey->smkid, 594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->use_sha256); 595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_send_stk_1_of_4(sm, peerkey); 596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr, 598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->inonce, peerkey->addr, peerkey->smkid, 599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->use_sha256); 600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN); 602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_supplicant_process_smk_error( 608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_sm *sm, const unsigned char *src_addr, 609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpa_eapol_key *key, size_t extra_len) 610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_ie_parse kde; 612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct rsn_error_kde error; 613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 peer[ETH_ALEN]; 614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 error_type; 615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK Error"); 617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { 619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for " 620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "the current network"); 621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < 625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 0) { 626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error"); 627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (kde.error == NULL || kde.error_len < sizeof(error)) { 631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: No Error KDE in SMK Error"); 632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN) 636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(peer, kde.mac_addr, ETH_ALEN); 637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(&error, kde.error, sizeof(error)); 638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt error_type = be_to_host16(error.error_type); 639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_msg(sm->ctx->ctx, MSG_INFO, 640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "RSN: SMK Error KDE received: MUI %d error_type %d peer " 641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MACSTR, 642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt be_to_host16(error.mui), error_type, 643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MAC2STR(peer)); 644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (kde.mac_addr && 646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (error_type == STK_ERR_STA_NR || error_type == STK_ERR_STA_NRSN || 647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt error_type == STK_ERR_CPHR_NS)) { 648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey; 649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { 651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 0) 653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peerkey == NULL) { 656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No matching SMK handshake " 657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "found for SMK Error"); 658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: abort SMK/STK handshake and remove all related keys */ 661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm, 668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey, 669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpa_eapol_key *key, 670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 ver) 671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_ie_parse ie; 673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *kde; 674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len, kde_buf_len; 675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ptk *stk; 676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 buf[8], *kde_buf, *pos; 677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt be32 lifetime; 678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 1 of STK 4-Way Handshake from " 680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&ie, 0, sizeof(ie)); 683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* RSN: msg 1/4 should contain SMKID for the selected SMK */ 685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde = (const u8 *) (key + 1); 686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = WPA_GET_BE16(key->key_data_length); 687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", kde, len); 688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_supplicant_parse_ies(kde, len, &ie) < 0 || ie.pmkid == NULL) { 689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No SMKID in STK 1/4"); 690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) { 693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 1/4", 694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ie.pmkid, PMKID_LEN); 695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_get_random(peerkey->pnonce, WPA_NONCE_LEN)) { 699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_msg(sm->ctx->ctx, MSG_WARNING, 700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "RSN: Failed to get random data for PNonce"); 701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Renewed PNonce", 704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->pnonce, WPA_NONCE_LEN); 705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Calculate STK which will be stored as a temporary STK until it has 707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * been verified when processing message 3/4. */ 708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt stk = &peerkey->tstk; 709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", 710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->own_addr, peerkey->addr, 711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->pnonce, key->key_nonce, 712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (u8 *) stk, sizeof(*stk), 713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->use_sha256); 714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Supplicant: swap tx/rx Mic keys */ 715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(buf, stk->u.auth.tx_mic_key, 8); 716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(stk->u.auth.tx_mic_key, stk->u.auth.rx_mic_key, 8); 717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(stk->u.auth.rx_mic_key, buf, 8); 718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->tstk_set = 1; 719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde_buf_len = peerkey->rsnie_p_len + 721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 2 + RSN_SELECTOR_LEN + sizeof(lifetime) + 722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 2 + RSN_SELECTOR_LEN + PMKID_LEN; 723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde_buf = os_malloc(kde_buf_len); 724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (kde_buf == NULL) 725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = kde_buf; 727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len); 728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt lifetime = host_to_be32(peerkey->lifetime); 729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, 730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (u8 *) &lifetime, sizeof(lifetime)); 731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_PMKID, peerkey->smkid, PMKID_LEN); 732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_supplicant_send_2_of_4(sm, peerkey->addr, key, ver, 734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->pnonce, kde_buf, kde_buf_len, 735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt stk)) { 736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(kde_buf); 737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(kde_buf); 740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN); 742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_update_smk_lifetime(struct wpa_sm *sm, 746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey, 747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_ie_parse *kde) 748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 lifetime; 750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct os_time now; 751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (kde->lifetime == NULL || kde->lifetime_len < sizeof(lifetime)) 753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt lifetime = WPA_GET_BE32(kde->lifetime); 756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (lifetime >= peerkey->lifetime) { 758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Peer used SMK lifetime %u seconds " 759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "which is larger than or equal to own value %u " 760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "seconds - ignored", lifetime, peerkey->lifetime); 761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Peer used shorter SMK lifetime %u seconds " 765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(own was %u seconds) - updated", 766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt lifetime, peerkey->lifetime); 767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->lifetime = lifetime; 768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_get_time(&now); 770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->expiration = now.sec + lifetime; 771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey); 772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout, 773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm, peerkey); 774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_process_stk_2_of_4(struct wpa_sm *sm, 778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey, 779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpa_eapol_key *key, 780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 ver) 781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_ie_parse kde; 783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *keydata; 784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 2 of STK 4-Way Handshake from " 787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&kde, 0, sizeof(kde)); 790526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE 792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * from the peer. It may also include Lifetime KDE. */ 793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keydata = (const u8 *) (key + 1); 794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = WPA_GET_BE16(key->key_data_length); 795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 2/4 key data", keydata, len); 796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0 || 797526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde.pmkid == NULL || kde.rsn_ie == NULL) { 798526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No SMKID or RSN IE in STK 2/4"); 799526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 800526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 801526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 802526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(kde.pmkid, peerkey->smkid, PMKID_LEN) != 0) { 803526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 2/4", 804526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde.pmkid, PMKID_LEN); 805526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 806526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 807526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 808526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (kde.rsn_ie_len != peerkey->rsnie_p_len || 809526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(kde.rsn_ie, peerkey->rsnie_p, kde.rsn_ie_len) != 0) { 810526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: Peer RSN IE in SMK and STK " 811526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "handshakes did not match"); 812526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in SMK handshake", 813526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->rsnie_p, peerkey->rsnie_p_len); 814526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in STK handshake", 815526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 816526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 817526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 818526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 819526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde); 820526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 821526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_send_stk_3_of_4(sm, peerkey); 822526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(peerkey->pnonce, key->key_nonce, WPA_NONCE_LEN); 823526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 824526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 825526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 826526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm, 827526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey, 828526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpa_eapol_key *key, 829526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 ver) 830526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 831526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_ie_parse kde; 832526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *keydata; 833526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len, key_len; 834526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *_key; 835526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 key_buf[32], rsc[6]; 836526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 837526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 3 of STK 4-Way Handshake from " 838526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 839526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 840526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&kde, 0, sizeof(kde)); 841526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 842526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* RSN: msg 3/4 should contain Initiator RSN IE. It may also include 843526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Lifetime KDE. */ 844526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keydata = (const u8 *) (key + 1); 845526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = WPA_GET_BE16(key->key_data_length); 846526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", keydata, len); 847526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0) { 848526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Failed to parse key data in " 849526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "STK 3/4"); 850526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 851526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 852526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 853526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (kde.rsn_ie_len != peerkey->rsnie_i_len || 854526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(kde.rsn_ie, peerkey->rsnie_i, kde.rsn_ie_len) != 0) { 855526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: Initiator RSN IE in SMK and STK " 856526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "handshakes did not match"); 857526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in SMK " 858526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "handshake", 859526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->rsnie_i, peerkey->rsnie_i_len); 860526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in STK " 861526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "handshake", 862526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 863526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 864526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 865526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 866526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN) != 0) { 867526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_WARNING, "RSN: INonce from message 1 of STK " 868526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "4-Way Handshake differs from 3 of STK 4-Way " 869526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Handshake - drop packet (src=" MACSTR ")", 870526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MAC2STR(peerkey->addr)); 871526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 872526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 873526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 874526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde); 875526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 876526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_supplicant_send_4_of_4(sm, peerkey->addr, key, ver, 877526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_GET_BE16(key->key_info), 878526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt NULL, 0, &peerkey->stk)) 879526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 880526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 881526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt _key = (u8 *) peerkey->stk.tk1; 882526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peerkey->cipher == WPA_CIPHER_TKIP) { 883526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Swap Tx/Rx keys for Michael MIC */ 884526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(key_buf, _key, 16); 885526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(key_buf + 16, peerkey->stk.u.auth.rx_mic_key, 8); 886526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(key_buf + 24, peerkey->stk.u.auth.tx_mic_key, 8); 887526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt _key = key_buf; 888526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key_len = 32; 889526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 890526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key_len = 16; 891526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 892526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(rsc, 0, 6); 893526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, 894526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rsc, sizeof(rsc), _key, key_len) < 0) { 895526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " 896526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "driver."); 897526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 898526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 899526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 900526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 901526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 902526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm, 903526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey, 904526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpa_eapol_key *key, 905526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 ver) 906526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 907526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 rsc[6]; 908526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 909526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 4 of STK 4-Way Handshake from " 910526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 911526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 912526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(rsc, 0, 6); 913526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, 914526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rsc, sizeof(rsc), (u8 *) peerkey->stk.tk1, 915526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->cipher == WPA_CIPHER_TKIP ? 32 : 16) < 0) { 916526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " 917526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "driver."); 918526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 919526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 920526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 921526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 922526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 923526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 924526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * peerkey_verify_eapol_key_mic - Verify PeerKey MIC 925526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 926526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @peerkey: Pointer to the PeerKey data for the peer 927526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @key: Pointer to the EAPOL-Key frame header 928526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info 929526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @buf: Pointer to the beginning of EAPOL-Key frame 930526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @len: Length of the EAPOL-Key frame 931526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: 0 on success, -1 on failure 932526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 933526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint peerkey_verify_eapol_key_mic(struct wpa_sm *sm, 934526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey, 935526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_key *key, u16 ver, 936526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *buf, size_t len) 937526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 938526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 mic[16]; 939526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ok = 0; 940526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 941526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peerkey->initiator && !peerkey->stk_set) { 942526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", 943526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->own_addr, peerkey->addr, 944526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->inonce, key->key_nonce, 945526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (u8 *) &peerkey->stk, sizeof(peerkey->stk), 946526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->use_sha256); 947526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->stk_set = 1; 948526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 949526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 950526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(mic, key->key_mic, 16); 951526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peerkey->tstk_set) { 952526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(key->key_mic, 0, 16); 953526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_eapol_key_mic(peerkey->tstk.kck, ver, buf, len, 954526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key->key_mic); 955526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(mic, key->key_mic, 16) != 0) { 956526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " 957526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "when using TSTK - ignoring TSTK"); 958526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 959526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ok = 1; 960526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->tstk_set = 0; 961526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->stk_set = 1; 962526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(&peerkey->stk, &peerkey->tstk, 963526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(peerkey->stk)); 964526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 965526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 966526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 967526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!ok && peerkey->stk_set) { 968526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(key->key_mic, 0, 16); 969526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_eapol_key_mic(peerkey->stk.kck, ver, buf, len, 970526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key->key_mic); 971526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(mic, key->key_mic, 16) != 0) { 972526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " 973526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "- dropping packet"); 974526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 975526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 976526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ok = 1; 977526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 978526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 979526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!ok) { 980526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Could not verify EAPOL-Key MIC " 981526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "- dropping packet"); 982526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 983526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 984526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 985526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(peerkey->replay_counter, key->replay_counter, 986526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_REPLAY_COUNTER_LEN); 987526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->replay_counter_set = 1; 988526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 989526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 990526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 991526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 992526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 993526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1) 994526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 995526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @peer: MAC address of the peer STA 996526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: 0 on success, or -1 on failure 997526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 998526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Send an EAPOL-Key Request to the current authenticator to start STK 999526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * handshake with the peer. 1000526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 1001526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) 1002526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1003526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t rlen, kde_len; 1004526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_key *req; 1005526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int key_info, ver; 1006526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos; 1007526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 count; 1008526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct rsn_ie_hdr *hdr; 1009526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *peerkey; 1010526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ie_data ie; 1011526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1012526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set || !sm->peerkey_enabled) 1013526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1014526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1015526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->ap_rsn_ie && 1016526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 && 1017526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) { 1018526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK"); 1019526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1020526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1021526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1022526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->pairwise_cipher == WPA_CIPHER_CCMP) 1023526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 1024526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 1025526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 1026526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1027526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_sm_get_bssid(sm, bssid) < 0) { 1028526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key " 1029526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "SMK M1"); 1030526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1031526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1032526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1033526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: find existing entry and if found, use that instead of adding 1034526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * a new one */ 1035526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey = os_zalloc(sizeof(*peerkey)); 1036526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peerkey == NULL) 1037526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1038526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->initiator = 1; 1039526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(peerkey->addr, peer, ETH_ALEN); 1040526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211W 1041526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_key_mgmt_sha256(sm->key_mgmt)) 1042526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->use_sha256 = 1; 1043526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 1044526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1045526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* SMK M1: 1046526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, 1047526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE)) 1048526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 1049526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1050526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr = (struct rsn_ie_hdr *) peerkey->rsnie_i; 1051526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 1052526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_LE16(hdr->version, RSN_VERSION); 1053526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = (u8 *) (hdr + 1); 1054526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Group Suite can be anything for SMK RSN IE; receiver will just 1055526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * ignore it. */ 1056526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 1057526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += RSN_SELECTOR_LEN; 1058526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt count_pos = pos; 1059526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 1060526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1061526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt count = 0; 1062526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->allowed_pairwise_cipher & WPA_CIPHER_CCMP) { 1063526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 1064526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += RSN_SELECTOR_LEN; 1065526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt count++; 1066526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1067526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->allowed_pairwise_cipher & WPA_CIPHER_TKIP) { 1068526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); 1069526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += RSN_SELECTOR_LEN; 1070526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt count++; 1071526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1072526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_LE16(count_pos, count); 1073526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1074526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr->len = (pos - peerkey->rsnie_i) - 2; 1075526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->rsnie_i_len = pos - peerkey->rsnie_i; 1076526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake", 1077526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->rsnie_i, peerkey->rsnie_i_len); 1078526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1079526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN; 1080526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1081526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 1082526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(*req) + kde_len, &rlen, 1083526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (void *) &req); 1084526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (rbuf == NULL) { 1085526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_peerkey_free(sm, peerkey); 1086526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1087526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1088526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1089526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req->type = EAPOL_KEY_TYPE_RSN; 1090526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | 1091526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver; 1092526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(req->key_info, key_info); 1093526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(req->key_length, 0); 1094526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(req->replay_counter, sm->request_counter, 1095526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_REPLAY_COUNTER_LEN); 1096526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); 1097526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1098526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_get_random(peerkey->inonce, WPA_NONCE_LEN)) { 1099526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_msg(sm->ctx->ctx, MSG_WARNING, 1100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "WPA: Failed to get random data for INonce"); 1101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(rbuf); 1102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_peerkey_free(sm, peerkey); 1103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN); 1106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake", 1107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req->key_nonce, WPA_NONCE_LEN); 1108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(req->key_data_length, (u16) kde_len); 1110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = (u8 *) (req + 1); 1111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Initiator RSN IE */ 1113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); 1114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Peer MAC address KDE */ 1115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); 1116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer " 1118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MACSTR ")", MAC2STR(peer)); 1119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL, 1120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rbuf, rlen, req->key_mic); 1121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey->next = sm->peerkey; 1123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->peerkey = peerkey; 1124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 1126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 1130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * peerkey_deinit - Free PeerKey values 1131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 1132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 1133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid peerkey_deinit(struct wpa_sm *sm) 1134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_peerkey *prev, *peerkey = sm->peerkey; 1136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (peerkey) { 1137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = peerkey; 1138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peerkey = peerkey->next; 1139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(prev); 1140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, 1145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_key *key, u16 key_info, u16 ver) 1146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if ((key_info & (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) == 1148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) { 1149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 3/4 STK 4-Way Handshake */ 1150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_process_stk_3_of_4(sm, peerkey, key, ver); 1151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (key_info & WPA_KEY_INFO_ACK) { 1152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 1/4 STK 4-Way Handshake */ 1153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_process_stk_1_of_4(sm, peerkey, key, ver); 1154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (key_info & WPA_KEY_INFO_SECURE) { 1155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 4/4 STK 4-Way Handshake */ 1156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_process_stk_4_of_4(sm, peerkey, key, ver); 1157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 1158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 2/4 STK 4-Way Handshake */ 1159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_process_stk_2_of_4(sm, peerkey, key, ver); 1160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr, 1165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_eapol_key *key, size_t extra_len, 1166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 key_info, u16 ver) 1167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (key_info & WPA_KEY_INFO_ERROR) { 1169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* SMK Error */ 1170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_process_smk_error(sm, src_addr, key, extra_len); 1171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (key_info & WPA_KEY_INFO_ACK) { 1172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* SMK M2 */ 1173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_process_smk_m2(sm, src_addr, key, extra_len, 1174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ver); 1175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 1176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* SMK M4 or M5 */ 1177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_process_smk_m45(sm, src_addr, key, extra_len, 1178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ver); 1179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_PEERKEY */ 1183