peerkey.c
Go to the documentation of this file.
00001 /*
00002  * WPA Supplicant - PeerKey for Direct Link Setup (DLS)
00003  * Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
00008  *
00009  * Alternatively, this software may be distributed under the terms of BSD
00010  * license.
00011  *
00012  * See README and COPYING for more details.
00013  */
00014 
00015 #include "includes.h"
00016 
00017 #ifdef CONFIG_PEERKEY
00018 
00019 #include "common.h"
00020 #include "eloop.h"
00021 #include "crypto/sha1.h"
00022 #include "crypto/sha256.h"
00023 #include "common/ieee802_11_defs.h"
00024 #include "wpa.h"
00025 #include "wpa_i.h"
00026 #include "wpa_ie.h"
00027 #include "peerkey.h"
00028 
00029 
00030 static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len)
00031 {
00032         os_memcpy(pos, ie, ie_len);
00033         return pos + ie_len;
00034 }
00035 
00036 
00037 static u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len)
00038 {
00039         *pos++ = WLAN_EID_VENDOR_SPECIFIC;
00040         *pos++ = RSN_SELECTOR_LEN + data_len;
00041         RSN_SELECTOR_PUT(pos, kde);
00042         pos += RSN_SELECTOR_LEN;
00043         os_memcpy(pos, data, data_len);
00044         pos += data_len;
00045         return pos;
00046 }
00047 
00048 
00049 static void wpa_supplicant_smk_timeout(void *eloop_ctx, void *timeout_ctx)
00050 {
00051 #if 0
00052         struct wpa_sm *sm = eloop_ctx;
00053         struct wpa_peerkey *peerkey = timeout_ctx;
00054 #endif
00055         /* TODO: time out SMK and any STK that was generated using this SMK */
00056 }
00057 
00058 
00059 static void wpa_supplicant_peerkey_free(struct wpa_sm *sm,
00060                                         struct wpa_peerkey *peerkey)
00061 {
00062         eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey);
00063         os_free(peerkey);
00064 }
00065 
00066 
00067 static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst,
00068                                          const u8 *peer,
00069                                          u16 mui, u16 error_type, int ver)
00070 {
00071         size_t rlen;
00072         struct wpa_eapol_key *err;
00073         struct rsn_error_kde error;
00074         u8 *rbuf, *pos;
00075         size_t kde_len;
00076         u16 key_info;
00077 
00078         kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error);
00079         if (peer)
00080                 kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN;
00081 
00082         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
00083                                   NULL, sizeof(*err) + kde_len, &rlen,
00084                                   (void *) &err);
00085         if (rbuf == NULL)
00086                 return -1;
00087 
00088         err->type = EAPOL_KEY_TYPE_RSN;
00089         key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
00090                 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR |
00091                 WPA_KEY_INFO_REQUEST;
00092         WPA_PUT_BE16(err->key_info, key_info);
00093         WPA_PUT_BE16(err->key_length, 0);
00094         os_memcpy(err->replay_counter, sm->request_counter,
00095                   WPA_REPLAY_COUNTER_LEN);
00096         inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
00097 
00098         WPA_PUT_BE16(err->key_data_length, (u16) kde_len);
00099         pos = (u8 *) (err + 1);
00100 
00101         if (peer) {
00102                 /* Peer MAC Address KDE */
00103                 pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);
00104         }
00105 
00106         /* Error KDE */
00107         error.mui = host_to_be16(mui);
00108         error.error_type = host_to_be16(error_type);
00109         wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error));
00110 
00111         if (peer) {
00112                 wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer "
00113                            MACSTR " mui %d error_type %d)",
00114                            MAC2STR(peer), mui, error_type);
00115         } else {
00116                 wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error "
00117                            "(mui %d error_type %d)", mui, error_type);
00118         }
00119 
00120         wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL,
00121                            rbuf, rlen, err->key_mic);
00122 
00123         return 0;
00124 }
00125 
00126 
00127 static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm,
00128                                       const unsigned char *src_addr,
00129                                       const struct wpa_eapol_key *key,
00130                                       int ver, struct wpa_peerkey *peerkey)
00131 {
00132         size_t rlen;
00133         struct wpa_eapol_key *reply;
00134         u8 *rbuf, *pos;
00135         size_t kde_len;
00136         u16 key_info;
00137 
00138         /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */
00139         kde_len = peerkey->rsnie_p_len +
00140                 2 + RSN_SELECTOR_LEN + ETH_ALEN +
00141                 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN;
00142 
00143         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
00144                                   NULL, sizeof(*reply) + kde_len, &rlen,
00145                                   (void *) &reply);
00146         if (rbuf == NULL)
00147                 return -1;
00148 
00149         reply->type = EAPOL_KEY_TYPE_RSN;
00150         key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
00151                 WPA_KEY_INFO_SECURE;
00152         WPA_PUT_BE16(reply->key_info, key_info);
00153         WPA_PUT_BE16(reply->key_length, 0);
00154         os_memcpy(reply->replay_counter, key->replay_counter,
00155                   WPA_REPLAY_COUNTER_LEN);
00156 
00157         os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN);
00158 
00159         WPA_PUT_BE16(reply->key_data_length, (u16) kde_len);
00160         pos = (u8 *) (reply + 1);
00161 
00162         /* Peer RSN IE */
00163         pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len);
00164 
00165         /* Initiator MAC Address KDE */
00166         pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN);
00167 
00168         /* Initiator Nonce */
00169         wpa_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN);
00170 
00171         wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3");
00172         wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL,
00173                            rbuf, rlen, reply->key_mic);
00174 
00175         return 0;
00176 }
00177 
00178 
00179 static int wpa_supplicant_process_smk_m2(
00180         struct wpa_sm *sm, const unsigned char *src_addr,
00181         const struct wpa_eapol_key *key, size_t extra_len, int ver)
00182 {
00183         struct wpa_peerkey *peerkey;
00184         struct wpa_eapol_ie_parse kde;
00185         struct wpa_ie_data ie;
00186         int cipher;
00187         struct rsn_ie_hdr *hdr;
00188         u8 *pos;
00189 
00190         wpa_printf(MSG_DEBUG, "RSN: Received SMK M2");
00191 
00192         if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
00193                 wpa_printf(MSG_INFO, "RSN: SMK handshake not allowed for "
00194                            "the current network");
00195                 return -1;
00196         }
00197 
00198         if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
00199             0) {
00200                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M2");
00201                 return -1;
00202         }
00203 
00204         if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
00205             kde.mac_addr_len < ETH_ALEN) {
00206                 wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
00207                            "SMK M2");
00208                 return -1;
00209         }
00210 
00211         wpa_printf(MSG_DEBUG, "RSN: SMK M2 - SMK initiator " MACSTR,
00212                    MAC2STR(kde.mac_addr));
00213 
00214         if (kde.rsn_ie_len > PEERKEY_MAX_IE_LEN) {
00215                 wpa_printf(MSG_INFO, "RSN: Too long Initiator RSN IE in SMK "
00216                            "M2");
00217                 return -1;
00218         }
00219 
00220         if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
00221                 wpa_printf(MSG_INFO, "RSN: Failed to parse RSN IE in SMK M2");
00222                 return -1;
00223         }
00224 
00225         cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher;
00226         if (cipher & WPA_CIPHER_CCMP) {
00227                 wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey");
00228                 cipher = WPA_CIPHER_CCMP;
00229         } else if (cipher & WPA_CIPHER_TKIP) {
00230                 wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey");
00231                 cipher = WPA_CIPHER_TKIP;
00232         } else {
00233                 wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2");
00234                 wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr,
00235                                               STK_MUI_SMK, STK_ERR_CPHR_NS,
00236                                               ver);
00237                 return -1;
00238         }
00239 
00240         /* TODO: find existing entry and if found, use that instead of adding
00241          * a new one; how to handle the case where both ends initiate at the
00242          * same time? */
00243         peerkey = os_zalloc(sizeof(*peerkey));
00244         if (peerkey == NULL)
00245                 return -1;
00246         os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN);
00247         os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN);
00248         os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);
00249         peerkey->rsnie_i_len = kde.rsn_ie_len;
00250         peerkey->cipher = cipher;
00251 #ifdef CONFIG_IEEE80211W
00252         if (ie.key_mgmt & (WPA_KEY_MGMT_IEEE8021X_SHA256 |
00253                            WPA_KEY_MGMT_PSK_SHA256))
00254                 peerkey->use_sha256 = 1;
00255 #endif /* CONFIG_IEEE80211W */
00256 
00257         if (os_get_random(peerkey->pnonce, WPA_NONCE_LEN)) {
00258                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
00259                         "WPA: Failed to get random data for PNonce");
00260                 wpa_supplicant_peerkey_free(sm, peerkey);
00261                 return -1;
00262         }
00263 
00264         hdr = (struct rsn_ie_hdr *) peerkey->rsnie_p;
00265         hdr->elem_id = WLAN_EID_RSN;
00266         WPA_PUT_LE16(hdr->version, RSN_VERSION);
00267         pos = (u8 *) (hdr + 1);
00268         /* Group Suite can be anything for SMK RSN IE; receiver will just
00269          * ignore it. */
00270         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
00271         pos += RSN_SELECTOR_LEN;
00272         /* Include only the selected cipher in pairwise cipher suite */
00273         WPA_PUT_LE16(pos, 1);
00274         pos += 2;
00275         if (cipher == WPA_CIPHER_CCMP)
00276                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
00277         else if (cipher == WPA_CIPHER_TKIP)
00278                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
00279         pos += RSN_SELECTOR_LEN;
00280 
00281         hdr->len = (pos - peerkey->rsnie_p) - 2;
00282         peerkey->rsnie_p_len = pos - peerkey->rsnie_p;
00283         wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",
00284                     peerkey->rsnie_p, peerkey->rsnie_p_len);
00285 
00286         wpa_supplicant_send_smk_m3(sm, src_addr, key, ver, peerkey);
00287 
00288         peerkey->next = sm->peerkey;
00289         sm->peerkey = peerkey;
00290 
00291         return 0;
00292 }
00293 
00294 
00307 static void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p,
00308                       const u8 *inonce, const u8 *mac_i, u8 *smkid,
00309                       int use_sha256)
00310 {
00311         char *title = "SMK Name";
00312         const u8 *addr[5];
00313         const size_t len[5] = { 8, WPA_NONCE_LEN, ETH_ALEN, WPA_NONCE_LEN,
00314                                 ETH_ALEN };
00315         unsigned char hash[SHA256_MAC_LEN];
00316 
00317         addr[0] = (u8 *) title;
00318         addr[1] = pnonce;
00319         addr[2] = mac_p;
00320         addr[3] = inonce;
00321         addr[4] = mac_i;
00322 
00323 #ifdef CONFIG_IEEE80211W
00324         if (use_sha256)
00325                 hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash);
00326         else
00327 #endif /* CONFIG_IEEE80211W */
00328                 hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash);
00329         os_memcpy(smkid, hash, PMKID_LEN);
00330 }
00331 
00332 
00333 static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm,
00334                                            struct wpa_peerkey *peerkey)
00335 {
00336         size_t mlen;
00337         struct wpa_eapol_key *msg;
00338         u8 *mbuf;
00339         size_t kde_len;
00340         u16 key_info, ver;
00341 
00342         kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
00343 
00344         mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
00345                                   sizeof(*msg) + kde_len, &mlen,
00346                                   (void *) &msg);
00347         if (mbuf == NULL)
00348                 return;
00349 
00350         msg->type = EAPOL_KEY_TYPE_RSN;
00351 
00352         if (peerkey->cipher == WPA_CIPHER_CCMP)
00353                 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
00354         else
00355                 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
00356 
00357         key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK;
00358         WPA_PUT_BE16(msg->key_info, key_info);
00359 
00360         if (peerkey->cipher == WPA_CIPHER_CCMP)
00361                 WPA_PUT_BE16(msg->key_length, 16);
00362         else
00363                 WPA_PUT_BE16(msg->key_length, 32);
00364 
00365         os_memcpy(msg->replay_counter, peerkey->replay_counter,
00366                   WPA_REPLAY_COUNTER_LEN);
00367         inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN);
00368 
00369         WPA_PUT_BE16(msg->key_data_length, kde_len);
00370         wpa_add_kde((u8 *) (msg + 1), RSN_KEY_DATA_PMKID,
00371                     peerkey->smkid, PMKID_LEN);
00372 
00373         if (os_get_random(peerkey->inonce, WPA_NONCE_LEN)) {
00374                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
00375                         "RSN: Failed to get random data for INonce (STK)");
00376                 os_free(mbuf);
00377                 return;
00378         }
00379         wpa_hexdump(MSG_DEBUG, "RSN: INonce for STK 4-Way Handshake",
00380                     peerkey->inonce, WPA_NONCE_LEN);
00381         os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
00382 
00383         wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR,
00384                    MAC2STR(peerkey->addr));
00385         wpa_eapol_key_send(sm, NULL, ver, peerkey->addr, ETH_P_EAPOL,
00386                            mbuf, mlen, NULL);
00387 }
00388 
00389 
00390 static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm,
00391                                            struct wpa_peerkey *peerkey)
00392 {
00393         size_t mlen;
00394         struct wpa_eapol_key *msg;
00395         u8 *mbuf, *pos;
00396         size_t kde_len;
00397         u16 key_info, ver;
00398         be32 lifetime;
00399 
00400         kde_len = peerkey->rsnie_i_len +
00401                 2 + RSN_SELECTOR_LEN + sizeof(lifetime);
00402 
00403         mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
00404                                   sizeof(*msg) + kde_len, &mlen,
00405                                   (void *) &msg);
00406         if (mbuf == NULL)
00407                 return;
00408 
00409         msg->type = EAPOL_KEY_TYPE_RSN;
00410 
00411         if (peerkey->cipher == WPA_CIPHER_CCMP)
00412                 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
00413         else
00414                 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
00415 
00416         key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK |
00417                 WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
00418         WPA_PUT_BE16(msg->key_info, key_info);
00419 
00420         if (peerkey->cipher == WPA_CIPHER_CCMP)
00421                 WPA_PUT_BE16(msg->key_length, 16);
00422         else
00423                 WPA_PUT_BE16(msg->key_length, 32);
00424 
00425         os_memcpy(msg->replay_counter, peerkey->replay_counter,
00426                   WPA_REPLAY_COUNTER_LEN);
00427         inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN);
00428 
00429         WPA_PUT_BE16(msg->key_data_length, kde_len);
00430         pos = (u8 *) (msg + 1);
00431         pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);
00432         lifetime = host_to_be32(peerkey->lifetime);
00433         wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
00434                     (u8 *) &lifetime, sizeof(lifetime));
00435 
00436         os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
00437 
00438         wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR,
00439                    MAC2STR(peerkey->addr));
00440         wpa_eapol_key_send(sm, peerkey->stk.kck, ver, peerkey->addr,
00441                            ETH_P_EAPOL, mbuf, mlen, msg->key_mic);
00442 }
00443 
00444 
00445 static int wpa_supplicant_process_smk_m4(struct wpa_peerkey *peerkey,
00446                                          struct wpa_eapol_ie_parse *kde)
00447 {
00448         wpa_printf(MSG_DEBUG, "RSN: Received SMK M4 (Initiator " MACSTR ")",
00449                    MAC2STR(kde->mac_addr));
00450 
00451         if (os_memcmp(kde->smk + PMK_LEN, peerkey->pnonce, WPA_NONCE_LEN) != 0)
00452         {
00453                 wpa_printf(MSG_INFO, "RSN: PNonce in SMK KDE does not "
00454                            "match with the one used in SMK M3");
00455                 return -1;
00456         }
00457 
00458         if (os_memcmp(kde->nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) {
00459                 wpa_printf(MSG_INFO, "RSN: INonce in SMK M4 did not "
00460                            "match with the one received in SMK M2");
00461                 return -1;
00462         }
00463 
00464         return 0;
00465 }
00466 
00467 
00468 static int wpa_supplicant_process_smk_m5(struct wpa_sm *sm,
00469                                          const unsigned char *src_addr,
00470                                          const struct wpa_eapol_key *key,
00471                                          int ver,
00472                                          struct wpa_peerkey *peerkey,
00473                                          struct wpa_eapol_ie_parse *kde)
00474 {
00475         int cipher;
00476         struct wpa_ie_data ie;
00477 
00478         wpa_printf(MSG_DEBUG, "RSN: Received SMK M5 (Peer " MACSTR ")",
00479                    MAC2STR(kde->mac_addr));
00480         if (kde->rsn_ie == NULL || kde->rsn_ie_len > PEERKEY_MAX_IE_LEN ||
00481             wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0) {
00482                 wpa_printf(MSG_INFO, "RSN: No RSN IE in SMK M5");
00483                 /* TODO: abort negotiation */
00484                 return -1;
00485         }
00486 
00487         if (os_memcmp(key->key_nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) {
00488                 wpa_printf(MSG_INFO, "RSN: Key Nonce in SMK M5 does "
00489                            "not match with INonce used in SMK M1");
00490                 return -1;
00491         }
00492 
00493         if (os_memcmp(kde->smk + PMK_LEN, peerkey->inonce, WPA_NONCE_LEN) != 0)
00494         {
00495                 wpa_printf(MSG_INFO, "RSN: INonce in SMK KDE does not "
00496                            "match with the one used in SMK M1");
00497                 return -1;
00498         }
00499 
00500         os_memcpy(peerkey->rsnie_p, kde->rsn_ie, kde->rsn_ie_len);
00501         peerkey->rsnie_p_len = kde->rsn_ie_len;
00502         os_memcpy(peerkey->pnonce, kde->nonce, WPA_NONCE_LEN);
00503 
00504         cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher;
00505         if (cipher & WPA_CIPHER_CCMP) {
00506                 wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey");
00507                 peerkey->cipher = WPA_CIPHER_CCMP;
00508         } else if (cipher & WPA_CIPHER_TKIP) {
00509                 wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey");
00510                 peerkey->cipher = WPA_CIPHER_TKIP;
00511         } else {
00512                 wpa_printf(MSG_INFO, "RSN: SMK Peer STA " MACSTR " selected "
00513                            "unacceptable cipher", MAC2STR(kde->mac_addr));
00514                 wpa_supplicant_send_smk_error(sm, src_addr, kde->mac_addr,
00515                                               STK_MUI_SMK, STK_ERR_CPHR_NS,
00516                                               ver);
00517                 /* TODO: abort negotiation */
00518                 return -1;
00519         }
00520 
00521         return 0;
00522 }
00523 
00524 
00525 static int wpa_supplicant_process_smk_m45(
00526         struct wpa_sm *sm, const unsigned char *src_addr,
00527         const struct wpa_eapol_key *key, size_t extra_len, int ver)
00528 {
00529         struct wpa_peerkey *peerkey;
00530         struct wpa_eapol_ie_parse kde;
00531         u32 lifetime;
00532         struct os_time now;
00533 
00534         if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
00535                 wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
00536                            "the current network");
00537                 return -1;
00538         }
00539 
00540         if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
00541             0) {
00542                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5");
00543                 return -1;
00544         }
00545 
00546         if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
00547             kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN ||
00548             kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN ||
00549             kde.lifetime == NULL || kde.lifetime_len < 4) {
00550                 wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or "
00551                            "Lifetime KDE in SMK M4/M5");
00552                 return -1;
00553         }
00554 
00555         for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
00556                 if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 &&
00557                     os_memcmp(peerkey->initiator ? peerkey->inonce :
00558                            peerkey->pnonce,
00559                            key->key_nonce, WPA_NONCE_LEN) == 0)
00560                         break;
00561         }
00562         if (peerkey == NULL) {
00563                 wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found "
00564                            "for SMK M4/M5: peer " MACSTR,
00565                            MAC2STR(kde.mac_addr));
00566                 return -1;
00567         }
00568 
00569         if (peerkey->initiator) {
00570                 if (wpa_supplicant_process_smk_m5(sm, src_addr, key, ver,
00571                                                   peerkey, &kde) < 0)
00572                         return -1;
00573         } else {
00574                 if (wpa_supplicant_process_smk_m4(peerkey, &kde) < 0)
00575                         return -1;
00576         }
00577 
00578         os_memcpy(peerkey->smk, kde.smk, PMK_LEN);
00579         peerkey->smk_complete = 1;
00580         wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN);
00581         lifetime = WPA_GET_BE32(kde.lifetime);
00582         wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime);
00583         if (lifetime > 1000000000)
00584                 lifetime = 1000000000; /* avoid overflowing expiration time */
00585         peerkey->lifetime = lifetime;
00586         os_get_time(&now);
00587         peerkey->expiration = now.sec + lifetime;
00588         eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout,
00589                                sm, peerkey);
00590 
00591         if (peerkey->initiator) {
00592                 rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr,
00593                           peerkey->inonce, sm->own_addr, peerkey->smkid,
00594                           peerkey->use_sha256);
00595                 wpa_supplicant_send_stk_1_of_4(sm, peerkey);
00596         } else {
00597                 rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr,
00598                           peerkey->inonce, peerkey->addr, peerkey->smkid,
00599                           peerkey->use_sha256);
00600         }
00601         wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN);
00602 
00603         return 0;
00604 }
00605 
00606 
00607 static int wpa_supplicant_process_smk_error(
00608         struct wpa_sm *sm, const unsigned char *src_addr,
00609         const struct wpa_eapol_key *key, size_t extra_len)
00610 {
00611         struct wpa_eapol_ie_parse kde;
00612         struct rsn_error_kde error;
00613         u8 peer[ETH_ALEN];
00614         u16 error_type;
00615 
00616         wpa_printf(MSG_DEBUG, "RSN: Received SMK Error");
00617 
00618         if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
00619                 wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
00620                            "the current network");
00621                 return -1;
00622         }
00623 
00624         if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
00625             0) {
00626                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
00627                 return -1;
00628         }
00629 
00630         if (kde.error == NULL || kde.error_len < sizeof(error)) {
00631                 wpa_printf(MSG_INFO, "RSN: No Error KDE in SMK Error");
00632                 return -1;
00633         }
00634 
00635         if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN)
00636                 os_memcpy(peer, kde.mac_addr, ETH_ALEN);
00637         else
00638                 os_memset(peer, 0, ETH_ALEN);
00639         os_memcpy(&error, kde.error, sizeof(error));
00640         error_type = be_to_host16(error.error_type);
00641         wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
00642                 "RSN: SMK Error KDE received: MUI %d error_type %d peer "
00643                 MACSTR,
00644                 be_to_host16(error.mui), error_type,
00645                 MAC2STR(peer));
00646 
00647         if (kde.mac_addr &&
00648             (error_type == STK_ERR_STA_NR || error_type == STK_ERR_STA_NRSN ||
00649              error_type == STK_ERR_CPHR_NS)) {
00650                 struct wpa_peerkey *peerkey;
00651 
00652                 for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
00653                         if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) ==
00654                             0)
00655                                 break;
00656                 }
00657                 if (peerkey == NULL) {
00658                         wpa_printf(MSG_DEBUG, "RSN: No matching SMK handshake "
00659                                    "found for SMK Error");
00660                         return -1;
00661                 }
00662                 /* TODO: abort SMK/STK handshake and remove all related keys */
00663         }
00664 
00665         return 0;
00666 }
00667 
00668 
00669 static void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm,
00670                                               struct wpa_peerkey *peerkey,
00671                                               const struct wpa_eapol_key *key,
00672                                               u16 ver)
00673 {
00674         struct wpa_eapol_ie_parse ie;
00675         const u8 *kde;
00676         size_t len, kde_buf_len;
00677         struct wpa_ptk *stk;
00678         u8 buf[8], *kde_buf, *pos;
00679         be32 lifetime;
00680 
00681         wpa_printf(MSG_DEBUG, "RSN: RX message 1 of STK 4-Way Handshake from "
00682                    MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
00683 
00684         os_memset(&ie, 0, sizeof(ie));
00685 
00686         /* RSN: msg 1/4 should contain SMKID for the selected SMK */
00687         kde = (const u8 *) (key + 1);
00688         len = WPA_GET_BE16(key->key_data_length);
00689         wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", kde, len);
00690         if (wpa_supplicant_parse_ies(kde, len, &ie) < 0 || ie.pmkid == NULL) {
00691                 wpa_printf(MSG_DEBUG, "RSN: No SMKID in STK 1/4");
00692                 return;
00693         }
00694         if (os_memcmp(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) {
00695                 wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 1/4",
00696                             ie.pmkid, PMKID_LEN);
00697                 return;
00698         }
00699 
00700         if (os_get_random(peerkey->pnonce, WPA_NONCE_LEN)) {
00701                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
00702                         "RSN: Failed to get random data for PNonce");
00703                 return;
00704         }
00705         wpa_hexdump(MSG_DEBUG, "WPA: Renewed PNonce",
00706                     peerkey->pnonce, WPA_NONCE_LEN);
00707 
00708         /* Calculate STK which will be stored as a temporary STK until it has
00709          * been verified when processing message 3/4. */
00710         stk = &peerkey->tstk;
00711         wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion",
00712                        sm->own_addr, peerkey->addr,
00713                        peerkey->pnonce, key->key_nonce,
00714                        (u8 *) stk, sizeof(*stk),
00715                        peerkey->use_sha256);
00716         /* Supplicant: swap tx/rx Mic keys */
00717         os_memcpy(buf, stk->u.auth.tx_mic_key, 8);
00718         os_memcpy(stk->u.auth.tx_mic_key, stk->u.auth.rx_mic_key, 8);
00719         os_memcpy(stk->u.auth.rx_mic_key, buf, 8);
00720         peerkey->tstk_set = 1;
00721 
00722         kde_buf_len = peerkey->rsnie_p_len +
00723                 2 + RSN_SELECTOR_LEN + sizeof(lifetime) +
00724                 2 + RSN_SELECTOR_LEN + PMKID_LEN;
00725         kde_buf = os_malloc(kde_buf_len);
00726         if (kde_buf == NULL)
00727                 return;
00728         pos = kde_buf;
00729         pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len);
00730         lifetime = host_to_be32(peerkey->lifetime);
00731         pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
00732                           (u8 *) &lifetime, sizeof(lifetime));
00733         wpa_add_kde(pos, RSN_KEY_DATA_PMKID, peerkey->smkid, PMKID_LEN);
00734 
00735         if (wpa_supplicant_send_2_of_4(sm, peerkey->addr, key, ver,
00736                                        peerkey->pnonce, kde_buf, kde_buf_len,
00737                                        stk)) {
00738                 os_free(kde_buf);
00739                 return;
00740         }
00741         os_free(kde_buf);
00742 
00743         os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN);
00744 }
00745 
00746 
00747 static void wpa_supplicant_update_smk_lifetime(struct wpa_sm *sm,
00748                                                struct wpa_peerkey *peerkey,
00749                                                struct wpa_eapol_ie_parse *kde)
00750 {
00751         u32 lifetime;
00752         struct os_time now;
00753 
00754         if (kde->lifetime == NULL || kde->lifetime_len < sizeof(lifetime))
00755                 return;
00756 
00757         lifetime = WPA_GET_BE32(kde->lifetime);
00758 
00759         if (lifetime >= peerkey->lifetime) {
00760                 wpa_printf(MSG_DEBUG, "RSN: Peer used SMK lifetime %u seconds "
00761                            "which is larger than or equal to own value %u "
00762                            "seconds - ignored", lifetime, peerkey->lifetime);
00763                 return;
00764         }
00765 
00766         wpa_printf(MSG_DEBUG, "RSN: Peer used shorter SMK lifetime %u seconds "
00767                    "(own was %u seconds) - updated",
00768                    lifetime, peerkey->lifetime);
00769         peerkey->lifetime = lifetime;
00770 
00771         os_get_time(&now);
00772         peerkey->expiration = now.sec + lifetime;
00773         eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey);
00774         eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout,
00775                                sm, peerkey);
00776 }
00777 
00778 
00779 static void wpa_supplicant_process_stk_2_of_4(struct wpa_sm *sm,
00780                                               struct wpa_peerkey *peerkey,
00781                                               const struct wpa_eapol_key *key,
00782                                               u16 ver)
00783 {
00784         struct wpa_eapol_ie_parse kde;
00785         const u8 *keydata;
00786         size_t len;
00787 
00788         wpa_printf(MSG_DEBUG, "RSN: RX message 2 of STK 4-Way Handshake from "
00789                    MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
00790 
00791         os_memset(&kde, 0, sizeof(kde));
00792 
00793         /* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE
00794          * from the peer. It may also include Lifetime KDE. */
00795         keydata = (const u8 *) (key + 1);
00796         len = WPA_GET_BE16(key->key_data_length);
00797         wpa_hexdump(MSG_DEBUG, "RSN: msg 2/4 key data", keydata, len);
00798         if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0 ||
00799             kde.pmkid == NULL || kde.rsn_ie == NULL) {
00800                 wpa_printf(MSG_DEBUG, "RSN: No SMKID or RSN IE in STK 2/4");
00801                 return;
00802         }
00803 
00804         if (os_memcmp(kde.pmkid, peerkey->smkid, PMKID_LEN) != 0) {
00805                 wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 2/4",
00806                             kde.pmkid, PMKID_LEN);
00807                 return;
00808         }
00809 
00810         if (kde.rsn_ie_len != peerkey->rsnie_p_len ||
00811             os_memcmp(kde.rsn_ie, peerkey->rsnie_p, kde.rsn_ie_len) != 0) {
00812                 wpa_printf(MSG_INFO, "RSN: Peer RSN IE in SMK and STK "
00813                            "handshakes did not match");
00814                 wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in SMK handshake",
00815                             peerkey->rsnie_p, peerkey->rsnie_p_len);
00816                 wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in STK handshake",
00817                             kde.rsn_ie, kde.rsn_ie_len);
00818                 return;
00819         }
00820 
00821         wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde);
00822 
00823         wpa_supplicant_send_stk_3_of_4(sm, peerkey);
00824         os_memcpy(peerkey->pnonce, key->key_nonce, WPA_NONCE_LEN);
00825 }
00826 
00827 
00828 static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm,
00829                                               struct wpa_peerkey *peerkey,
00830                                               const struct wpa_eapol_key *key,
00831                                               u16 ver)
00832 {
00833         struct wpa_eapol_ie_parse kde;
00834         const u8 *keydata;
00835         size_t len, key_len;
00836         const u8 *_key;
00837         u8 key_buf[32], rsc[6];
00838 
00839         wpa_printf(MSG_DEBUG, "RSN: RX message 3 of STK 4-Way Handshake from "
00840                    MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
00841 
00842         os_memset(&kde, 0, sizeof(kde));
00843 
00844         /* RSN: msg 3/4 should contain Initiator RSN IE. It may also include
00845          * Lifetime KDE. */
00846         keydata = (const u8 *) (key + 1);
00847         len = WPA_GET_BE16(key->key_data_length);
00848         wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", keydata, len);
00849         if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0) {
00850                 wpa_printf(MSG_DEBUG, "RSN: Failed to parse key data in "
00851                            "STK 3/4");
00852                 return;
00853         }
00854 
00855         if (kde.rsn_ie_len != peerkey->rsnie_i_len ||
00856             os_memcmp(kde.rsn_ie, peerkey->rsnie_i, kde.rsn_ie_len) != 0) {
00857                 wpa_printf(MSG_INFO, "RSN: Initiator RSN IE in SMK and STK "
00858                            "handshakes did not match");
00859                 wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in SMK "
00860                             "handshake",
00861                             peerkey->rsnie_i, peerkey->rsnie_i_len);
00862                 wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in STK "
00863                             "handshake",
00864                             kde.rsn_ie, kde.rsn_ie_len);
00865                 return;
00866         }
00867 
00868         if (os_memcmp(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
00869                 wpa_printf(MSG_WARNING, "RSN: INonce from message 1 of STK "
00870                            "4-Way Handshake differs from 3 of STK 4-Way "
00871                            "Handshake - drop packet (src=" MACSTR ")",
00872                            MAC2STR(peerkey->addr));
00873                 return;
00874         }
00875 
00876         wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde);
00877 
00878         if (wpa_supplicant_send_4_of_4(sm, peerkey->addr, key, ver,
00879                                        WPA_GET_BE16(key->key_info),
00880                                        NULL, 0, &peerkey->stk))
00881                 return;
00882 
00883         _key = (u8 *) peerkey->stk.tk1;
00884         if (peerkey->cipher == WPA_CIPHER_TKIP) {
00885                 /* Swap Tx/Rx keys for Michael MIC */
00886                 os_memcpy(key_buf, _key, 16);
00887                 os_memcpy(key_buf + 16, peerkey->stk.u.auth.rx_mic_key, 8);
00888                 os_memcpy(key_buf + 24, peerkey->stk.u.auth.tx_mic_key, 8);
00889                 _key = key_buf;
00890                 key_len = 32;
00891         } else
00892                 key_len = 16;
00893 
00894         os_memset(rsc, 0, 6);
00895         if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1,
00896                            rsc, sizeof(rsc), _key, key_len) < 0) {
00897                 wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the "
00898                            "driver.");
00899                 return;
00900         }
00901 }
00902 
00903 
00904 static void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm,
00905                                               struct wpa_peerkey *peerkey,
00906                                               const struct wpa_eapol_key *key,
00907                                               u16 ver)
00908 {
00909         u8 rsc[6];
00910 
00911         wpa_printf(MSG_DEBUG, "RSN: RX message 4 of STK 4-Way Handshake from "
00912                    MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
00913 
00914         os_memset(rsc, 0, 6);
00915         if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1,
00916                            rsc, sizeof(rsc), (u8 *) peerkey->stk.tk1,
00917                            peerkey->cipher == WPA_CIPHER_TKIP ? 32 : 16) < 0) {
00918                 wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the "
00919                            "driver.");
00920                 return;
00921         }
00922 }
00923 
00924 
00935 int peerkey_verify_eapol_key_mic(struct wpa_sm *sm,
00936                                  struct wpa_peerkey *peerkey,
00937                                  struct wpa_eapol_key *key, u16 ver,
00938                                  const u8 *buf, size_t len)
00939 {
00940         u8 mic[16];
00941         int ok = 0;
00942 
00943         if (peerkey->initiator && !peerkey->stk_set) {
00944                 wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion",
00945                                sm->own_addr, peerkey->addr,
00946                                peerkey->inonce, key->key_nonce,
00947                                (u8 *) &peerkey->stk, sizeof(peerkey->stk),
00948                                peerkey->use_sha256);
00949                 peerkey->stk_set = 1;
00950         }
00951 
00952         os_memcpy(mic, key->key_mic, 16);
00953         if (peerkey->tstk_set) {
00954                 os_memset(key->key_mic, 0, 16);
00955                 wpa_eapol_key_mic(peerkey->tstk.kck, ver, buf, len,
00956                                   key->key_mic);
00957                 if (os_memcmp(mic, key->key_mic, 16) != 0) {
00958                         wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
00959                                    "when using TSTK - ignoring TSTK");
00960                 } else {
00961                         ok = 1;
00962                         peerkey->tstk_set = 0;
00963                         peerkey->stk_set = 1;
00964                         os_memcpy(&peerkey->stk, &peerkey->tstk,
00965                                   sizeof(peerkey->stk));
00966                 }
00967         }
00968 
00969         if (!ok && peerkey->stk_set) {
00970                 os_memset(key->key_mic, 0, 16);
00971                 wpa_eapol_key_mic(peerkey->stk.kck, ver, buf, len,
00972                                   key->key_mic);
00973                 if (os_memcmp(mic, key->key_mic, 16) != 0) {
00974                         wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
00975                                    "- dropping packet");
00976                         return -1;
00977                 }
00978                 ok = 1;
00979         }
00980 
00981         if (!ok) {
00982                 wpa_printf(MSG_WARNING, "RSN: Could not verify EAPOL-Key MIC "
00983                            "- dropping packet");
00984                 return -1;
00985         }
00986 
00987         os_memcpy(peerkey->replay_counter, key->replay_counter,
00988                   WPA_REPLAY_COUNTER_LEN);
00989         peerkey->replay_counter_set = 1;
00990         return 0;
00991 }
00992 
00993 
01003 int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer)
01004 {
01005         size_t rlen, kde_len;
01006         struct wpa_eapol_key *req;
01007         int key_info, ver;
01008         u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos;
01009         u16 count;
01010         struct rsn_ie_hdr *hdr;
01011         struct wpa_peerkey *peerkey;
01012         struct wpa_ie_data ie;
01013 
01014         if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set || !sm->peerkey_enabled)
01015                 return -1;
01016 
01017         if (sm->ap_rsn_ie &&
01018             wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 &&
01019             !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) {
01020                 wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK");
01021                 return -1;
01022         }
01023 
01024         if (sm->pairwise_cipher == WPA_CIPHER_CCMP)
01025                 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
01026         else
01027                 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
01028 
01029         if (wpa_sm_get_bssid(sm, bssid) < 0) {
01030                 wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key "
01031                            "SMK M1");
01032                 return -1;
01033         }
01034 
01035         /* TODO: find existing entry and if found, use that instead of adding
01036          * a new one */
01037         peerkey = os_zalloc(sizeof(*peerkey));
01038         if (peerkey == NULL)
01039                 return -1;
01040         peerkey->initiator = 1;
01041         os_memcpy(peerkey->addr, peer, ETH_ALEN);
01042 #ifdef CONFIG_IEEE80211W
01043         if (wpa_key_mgmt_sha256(sm->key_mgmt))
01044                 peerkey->use_sha256 = 1;
01045 #endif /* CONFIG_IEEE80211W */
01046 
01047         /* SMK M1:
01048          * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
01049          *           MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE))
01050          */
01051 
01052         hdr = (struct rsn_ie_hdr *) peerkey->rsnie_i;
01053         hdr->elem_id = WLAN_EID_RSN;
01054         WPA_PUT_LE16(hdr->version, RSN_VERSION);
01055         pos = (u8 *) (hdr + 1);
01056         /* Group Suite can be anything for SMK RSN IE; receiver will just
01057          * ignore it. */
01058         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
01059         pos += RSN_SELECTOR_LEN;
01060         count_pos = pos;
01061         pos += 2;
01062 
01063         count = 0;
01064         if (sm->allowed_pairwise_cipher & WPA_CIPHER_CCMP) {
01065                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
01066                 pos += RSN_SELECTOR_LEN;
01067                 count++;
01068         }
01069         if (sm->allowed_pairwise_cipher & WPA_CIPHER_TKIP) {
01070                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
01071                 pos += RSN_SELECTOR_LEN;
01072                 count++;
01073         }
01074         WPA_PUT_LE16(count_pos, count);
01075 
01076         hdr->len = (pos - peerkey->rsnie_i) - 2;
01077         peerkey->rsnie_i_len = pos - peerkey->rsnie_i;
01078         wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",
01079                     peerkey->rsnie_i, peerkey->rsnie_i_len);
01080 
01081         kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
01082 
01083         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
01084                                   sizeof(*req) + kde_len, &rlen,
01085                                   (void *) &req);
01086         if (rbuf == NULL) {
01087                 wpa_supplicant_peerkey_free(sm, peerkey);
01088                 return -1;
01089         }
01090 
01091         req->type = EAPOL_KEY_TYPE_RSN;
01092         key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
01093                 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver;
01094         WPA_PUT_BE16(req->key_info, key_info);
01095         WPA_PUT_BE16(req->key_length, 0);
01096         os_memcpy(req->replay_counter, sm->request_counter,
01097                   WPA_REPLAY_COUNTER_LEN);
01098         inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
01099 
01100         if (os_get_random(peerkey->inonce, WPA_NONCE_LEN)) {
01101                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
01102                         "WPA: Failed to get random data for INonce");
01103                 os_free(rbuf);
01104                 wpa_supplicant_peerkey_free(sm, peerkey);
01105                 return -1;
01106         }
01107         os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
01108         wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake",
01109                     req->key_nonce, WPA_NONCE_LEN);
01110 
01111         WPA_PUT_BE16(req->key_data_length, (u16) kde_len);
01112         pos = (u8 *) (req + 1);
01113 
01114         /* Initiator RSN IE */
01115         pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);
01116         /* Peer MAC address KDE */
01117         wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);
01118 
01119         wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer "
01120                    MACSTR ")", MAC2STR(peer));
01121         wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL,
01122                            rbuf, rlen, req->key_mic);
01123 
01124         peerkey->next = sm->peerkey;
01125         sm->peerkey = peerkey;
01126 
01127         return 0;
01128 }
01129 
01130 
01135 void peerkey_deinit(struct wpa_sm *sm)
01136 {
01137         struct wpa_peerkey *prev, *peerkey = sm->peerkey;
01138         while (peerkey) {
01139                 prev = peerkey;
01140                 peerkey = peerkey->next;
01141                 os_free(prev);
01142         }
01143 }
01144 
01145 
01146 void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey,
01147                            struct wpa_eapol_key *key, u16 key_info, u16 ver)
01148 {
01149         if ((key_info & (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) ==
01150             (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) {
01151                 /* 3/4 STK 4-Way Handshake */
01152                 wpa_supplicant_process_stk_3_of_4(sm, peerkey, key, ver);
01153         } else if (key_info & WPA_KEY_INFO_ACK) {
01154                 /* 1/4 STK 4-Way Handshake */
01155                 wpa_supplicant_process_stk_1_of_4(sm, peerkey, key, ver);
01156         } else if (key_info & WPA_KEY_INFO_SECURE) {
01157                 /* 4/4 STK 4-Way Handshake */
01158                 wpa_supplicant_process_stk_4_of_4(sm, peerkey, key, ver);
01159         } else {
01160                 /* 2/4 STK 4-Way Handshake */
01161                 wpa_supplicant_process_stk_2_of_4(sm, peerkey, key, ver);
01162         }
01163 }
01164 
01165 
01166 void peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr,
01167                           struct wpa_eapol_key *key, size_t extra_len,
01168                           u16 key_info, u16 ver)
01169 {
01170         if (key_info & WPA_KEY_INFO_ERROR) {
01171                 /* SMK Error */
01172                 wpa_supplicant_process_smk_error(sm, src_addr, key, extra_len);
01173         } else if (key_info & WPA_KEY_INFO_ACK) {
01174                 /* SMK M2 */
01175                 wpa_supplicant_process_smk_m2(sm, src_addr, key, extra_len,
01176                                               ver);
01177         } else {
01178                 /* SMK M4 or M5 */
01179                 wpa_supplicant_process_smk_m45(sm, src_addr, key, extra_len,
01180                                                ver);
01181         }
01182 }
01183 
01184 #endif /* CONFIG_PEERKEY */


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:35