peerkey.c

Go to the documentation of this file.
00001 
00016 #include "includes.h"
00017 
00018 #ifdef CONFIG_PEERKEY
00019 
00020 #include "common.h"
00021 #include "sha1.h"
00022 #include "sha256.h"
00023 #include "eloop.h"
00024 #include "wpa.h"
00025 #include "wpa_i.h"
00026 #include "wpa_ie.h"
00027 #include "ieee802_11_defs.h"
00028 #include "peerkey.h"
00029 
00030 
00031 static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len)
00032 {
00033         os_memcpy(pos, ie, ie_len);
00034         return pos + ie_len;
00035 }
00036 
00037 
00038 static u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len)
00039 {
00040         *pos++ = WLAN_EID_VENDOR_SPECIFIC;
00041         *pos++ = RSN_SELECTOR_LEN + data_len;
00042         RSN_SELECTOR_PUT(pos, kde);
00043         pos += RSN_SELECTOR_LEN;
00044         os_memcpy(pos, data, data_len);
00045         pos += data_len;
00046         return pos;
00047 }
00048 
00049 
00050 static void wpa_supplicant_smk_timeout(void *eloop_ctx, void *timeout_ctx)
00051 {
00052 #if 0
00053         struct wpa_sm *sm = eloop_ctx;
00054         struct wpa_peerkey *peerkey = timeout_ctx;
00055 #endif
00056         /* TODO: time out SMK and any STK that was generated using this SMK */
00057 }
00058 
00059 
00060 static void wpa_supplicant_peerkey_free(struct wpa_sm *sm,
00061                                         struct wpa_peerkey *peerkey)
00062 {
00063         eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey);
00064         os_free(peerkey);
00065 }
00066 
00067 
00068 static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst,
00069                                          const u8 *peer,
00070                                          u16 mui, u16 error_type, int ver)
00071 {
00072         size_t rlen;
00073         struct wpa_eapol_key *err;
00074         struct rsn_error_kde error;
00075         u8 *rbuf, *pos;
00076         size_t kde_len;
00077         u16 key_info;
00078 
00079         kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error);
00080         if (peer)
00081                 kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN;
00082 
00083         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
00084                                   NULL, sizeof(*err) + kde_len, &rlen,
00085                                   (void *) &err);
00086         if (rbuf == NULL)
00087                 return -1;
00088 
00089         err->type = EAPOL_KEY_TYPE_RSN;
00090         key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
00091                 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR |
00092                 WPA_KEY_INFO_REQUEST;
00093         WPA_PUT_BE16(err->key_info, key_info);
00094         WPA_PUT_BE16(err->key_length, 0);
00095         os_memcpy(err->replay_counter, sm->request_counter,
00096                   WPA_REPLAY_COUNTER_LEN);
00097         inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
00098 
00099         WPA_PUT_BE16(err->key_data_length, (u16) kde_len);
00100         pos = (u8 *) (err + 1);
00101 
00102         if (peer) {
00103                 /* Peer MAC Address KDE */
00104                 pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);
00105         }
00106 
00107         /* Error KDE */
00108         error.mui = host_to_be16(mui);
00109         error.error_type = host_to_be16(error_type);
00110         wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error));
00111 
00112         if (peer) {
00113                 wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer "
00114                            MACSTR " mui %d error_type %d)",
00115                            MAC2STR(peer), mui, error_type);
00116         } else {
00117                 wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error "
00118                            "(mui %d error_type %d)", mui, error_type);
00119         }
00120 
00121         wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL,
00122                            rbuf, rlen, err->key_mic);
00123 
00124         return 0;
00125 }
00126 
00127 
00128 static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm,
00129                                       const unsigned char *src_addr,
00130                                       const struct wpa_eapol_key *key,
00131                                       int ver, struct wpa_peerkey *peerkey)
00132 {
00133         size_t rlen;
00134         struct wpa_eapol_key *reply;
00135         u8 *rbuf, *pos;
00136         size_t kde_len;
00137         u16 key_info;
00138 
00139         /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */
00140         kde_len = peerkey->rsnie_p_len +
00141                 2 + RSN_SELECTOR_LEN + ETH_ALEN +
00142                 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN;
00143 
00144         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
00145                                   NULL, sizeof(*reply) + kde_len, &rlen,
00146                                   (void *) &reply);
00147         if (rbuf == NULL)
00148                 return -1;
00149 
00150         reply->type = EAPOL_KEY_TYPE_RSN;
00151         key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
00152                 WPA_KEY_INFO_SECURE;
00153         WPA_PUT_BE16(reply->key_info, key_info);
00154         WPA_PUT_BE16(reply->key_length, 0);
00155         os_memcpy(reply->replay_counter, key->replay_counter,
00156                   WPA_REPLAY_COUNTER_LEN);
00157 
00158         os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN);
00159 
00160         WPA_PUT_BE16(reply->key_data_length, (u16) kde_len);
00161         pos = (u8 *) (reply + 1);
00162 
00163         /* Peer RSN IE */
00164         pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len);
00165 
00166         /* Initiator MAC Address KDE */
00167         pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN);
00168 
00169         /* Initiator Nonce */
00170         wpa_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN);
00171 
00172         wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3");
00173         wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL,
00174                            rbuf, rlen, reply->key_mic);
00175 
00176         return 0;
00177 }
00178 
00179 
00180 static int wpa_supplicant_process_smk_m2(
00181         struct wpa_sm *sm, const unsigned char *src_addr,
00182         const struct wpa_eapol_key *key, size_t extra_len, int ver)
00183 {
00184         struct wpa_peerkey *peerkey;
00185         struct wpa_eapol_ie_parse kde;
00186         struct wpa_ie_data ie;
00187         int cipher;
00188         struct rsn_ie_hdr *hdr;
00189         u8 *pos;
00190 
00191         wpa_printf(MSG_DEBUG, "RSN: Received SMK M2");
00192 
00193         if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
00194                 wpa_printf(MSG_INFO, "RSN: SMK handshake not allowed for "
00195                            "the current network");
00196                 return -1;
00197         }
00198 
00199         if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
00200             0) {
00201                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M2");
00202                 return -1;
00203         }
00204 
00205         if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
00206             kde.mac_addr_len < ETH_ALEN) {
00207                 wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
00208                            "SMK M2");
00209                 return -1;
00210         }
00211 
00212         wpa_printf(MSG_DEBUG, "RSN: SMK M2 - SMK initiator " MACSTR,
00213                    MAC2STR(kde.mac_addr));
00214 
00215         if (kde.rsn_ie_len > PEERKEY_MAX_IE_LEN) {
00216                 wpa_printf(MSG_INFO, "RSN: Too long Initiator RSN IE in SMK "
00217                            "M2");
00218                 return -1;
00219         }
00220 
00221         if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
00222                 wpa_printf(MSG_INFO, "RSN: Failed to parse RSN IE in SMK M2");
00223                 return -1;
00224         }
00225 
00226         cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher;
00227         if (cipher & WPA_CIPHER_CCMP) {
00228                 wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey");
00229                 cipher = WPA_CIPHER_CCMP;
00230         } else if (cipher & WPA_CIPHER_TKIP) {
00231                 wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey");
00232                 cipher = WPA_CIPHER_TKIP;
00233         } else {
00234                 wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2");
00235                 wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr,
00236                                               STK_MUI_SMK, STK_ERR_CPHR_NS,
00237                                               ver);
00238                 return -1;
00239         }
00240 
00241         /* TODO: find existing entry and if found, use that instead of adding
00242          * a new one; how to handle the case where both ends initiate at the
00243          * same time? */
00244         peerkey = os_zalloc(sizeof(*peerkey));
00245         if (peerkey == NULL)
00246                 return -1;
00247         os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN);
00248         os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN);
00249         os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);
00250         peerkey->rsnie_i_len = kde.rsn_ie_len;
00251         peerkey->cipher = cipher;
00252 #ifdef CONFIG_IEEE80211W
00253         if (ie.key_mgmt & (WPA_KEY_MGMT_IEEE8021X_SHA256 |
00254                            WPA_KEY_MGMT_PSK_SHA256))
00255                 peerkey->use_sha256 = 1;
00256 #endif /* CONFIG_IEEE80211W */
00257 
00258         if (os_get_random(peerkey->pnonce, WPA_NONCE_LEN)) {
00259                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
00260                         "WPA: Failed to get random data for PNonce");
00261                 wpa_supplicant_peerkey_free(sm, peerkey);
00262                 return -1;
00263         }
00264 
00265         hdr = (struct rsn_ie_hdr *) peerkey->rsnie_p;
00266         hdr->elem_id = WLAN_EID_RSN;
00267         WPA_PUT_LE16(hdr->version, RSN_VERSION);
00268         pos = (u8 *) (hdr + 1);
00269         /* Group Suite can be anything for SMK RSN IE; receiver will just
00270          * ignore it. */
00271         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
00272         pos += RSN_SELECTOR_LEN;
00273         /* Include only the selected cipher in pairwise cipher suite */
00274         WPA_PUT_LE16(pos, 1);
00275         pos += 2;
00276         if (cipher == WPA_CIPHER_CCMP)
00277                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
00278         else if (cipher == WPA_CIPHER_TKIP)
00279                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
00280         pos += RSN_SELECTOR_LEN;
00281 
00282         hdr->len = (pos - peerkey->rsnie_p) - 2;
00283         peerkey->rsnie_p_len = pos - peerkey->rsnie_p;
00284         wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",
00285                     peerkey->rsnie_p, peerkey->rsnie_p_len);
00286 
00287         wpa_supplicant_send_smk_m3(sm, src_addr, key, ver, peerkey);
00288 
00289         peerkey->next = sm->peerkey;
00290         sm->peerkey = peerkey;
00291 
00292         return 0;
00293 }
00294 
00295 
00309 static void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p,
00310                       const u8 *inonce, const u8 *mac_i, u8 *smkid,
00311                       int use_sha256)
00312 {
00313         char *title = "SMK Name";
00314         const u8 *addr[5];
00315         const size_t len[5] = { 8, WPA_NONCE_LEN, ETH_ALEN, WPA_NONCE_LEN,
00316                                 ETH_ALEN };
00317         unsigned char hash[SHA256_MAC_LEN];
00318 
00319         addr[0] = (u8 *) title;
00320         addr[1] = pnonce;
00321         addr[2] = mac_p;
00322         addr[3] = inonce;
00323         addr[4] = mac_i;
00324 
00325 #ifdef CONFIG_IEEE80211W
00326         if (use_sha256)
00327                 hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash);
00328         else
00329 #endif /* CONFIG_IEEE80211W */
00330                 hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash);
00331         os_memcpy(smkid, hash, PMKID_LEN);
00332 }
00333 
00334 
00335 static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm,
00336                                            struct wpa_peerkey *peerkey)
00337 {
00338         size_t mlen;
00339         struct wpa_eapol_key *msg;
00340         u8 *mbuf;
00341         size_t kde_len;
00342         u16 key_info, ver;
00343 
00344         kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
00345 
00346         mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
00347                                   sizeof(*msg) + kde_len, &mlen,
00348                                   (void *) &msg);
00349         if (mbuf == NULL)
00350                 return;
00351 
00352         msg->type = EAPOL_KEY_TYPE_RSN;
00353 
00354         if (peerkey->cipher == WPA_CIPHER_CCMP)
00355                 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
00356         else
00357                 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
00358 
00359         key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK;
00360         WPA_PUT_BE16(msg->key_info, key_info);
00361 
00362         if (peerkey->cipher == WPA_CIPHER_CCMP)
00363                 WPA_PUT_BE16(msg->key_length, 16);
00364         else
00365                 WPA_PUT_BE16(msg->key_length, 32);
00366 
00367         os_memcpy(msg->replay_counter, peerkey->replay_counter,
00368                   WPA_REPLAY_COUNTER_LEN);
00369         inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN);
00370 
00371         WPA_PUT_BE16(msg->key_data_length, kde_len);
00372         wpa_add_kde((u8 *) (msg + 1), RSN_KEY_DATA_PMKID,
00373                     peerkey->smkid, PMKID_LEN);
00374 
00375         if (os_get_random(peerkey->inonce, WPA_NONCE_LEN)) {
00376                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
00377                         "RSN: Failed to get random data for INonce (STK)");
00378                 os_free(mbuf);
00379                 return;
00380         }
00381         wpa_hexdump(MSG_DEBUG, "RSN: INonce for STK 4-Way Handshake",
00382                     peerkey->inonce, WPA_NONCE_LEN);
00383         os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
00384 
00385         wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR,
00386                    MAC2STR(peerkey->addr));
00387         wpa_eapol_key_send(sm, NULL, ver, peerkey->addr, ETH_P_EAPOL,
00388                            mbuf, mlen, NULL);
00389 }
00390 
00391 
00392 static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm,
00393                                            struct wpa_peerkey *peerkey)
00394 {
00395         size_t mlen;
00396         struct wpa_eapol_key *msg;
00397         u8 *mbuf, *pos;
00398         size_t kde_len;
00399         u16 key_info, ver;
00400         be32 lifetime;
00401 
00402         kde_len = peerkey->rsnie_i_len +
00403                 2 + RSN_SELECTOR_LEN + sizeof(lifetime);
00404 
00405         mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
00406                                   sizeof(*msg) + kde_len, &mlen,
00407                                   (void *) &msg);
00408         if (mbuf == NULL)
00409                 return;
00410 
00411         msg->type = EAPOL_KEY_TYPE_RSN;
00412 
00413         if (peerkey->cipher == WPA_CIPHER_CCMP)
00414                 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
00415         else
00416                 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
00417 
00418         key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK |
00419                 WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
00420         WPA_PUT_BE16(msg->key_info, key_info);
00421 
00422         if (peerkey->cipher == WPA_CIPHER_CCMP)
00423                 WPA_PUT_BE16(msg->key_length, 16);
00424         else
00425                 WPA_PUT_BE16(msg->key_length, 32);
00426 
00427         os_memcpy(msg->replay_counter, peerkey->replay_counter,
00428                   WPA_REPLAY_COUNTER_LEN);
00429         inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN);
00430 
00431         WPA_PUT_BE16(msg->key_data_length, kde_len);
00432         pos = (u8 *) (msg + 1);
00433         pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);
00434         lifetime = host_to_be32(peerkey->lifetime);
00435         wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
00436                     (u8 *) &lifetime, sizeof(lifetime));
00437 
00438         os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
00439 
00440         wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR,
00441                    MAC2STR(peerkey->addr));
00442         wpa_eapol_key_send(sm, peerkey->stk.kck, ver, peerkey->addr,
00443                            ETH_P_EAPOL, mbuf, mlen, msg->key_mic);
00444 }
00445 
00446 
00447 static int wpa_supplicant_process_smk_m4(struct wpa_peerkey *peerkey,
00448                                          struct wpa_eapol_ie_parse *kde)
00449 {
00450         wpa_printf(MSG_DEBUG, "RSN: Received SMK M4 (Initiator " MACSTR ")",
00451                    MAC2STR(kde->mac_addr));
00452 
00453         if (os_memcmp(kde->smk + PMK_LEN, peerkey->pnonce, WPA_NONCE_LEN) != 0)
00454         {
00455                 wpa_printf(MSG_INFO, "RSN: PNonce in SMK KDE does not "
00456                            "match with the one used in SMK M3");
00457                 return -1;
00458         }
00459 
00460         if (os_memcmp(kde->nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) {
00461                 wpa_printf(MSG_INFO, "RSN: INonce in SMK M4 did not "
00462                            "match with the one received in SMK M2");
00463                 return -1;
00464         }
00465 
00466         return 0;
00467 }
00468 
00469 
00470 static int wpa_supplicant_process_smk_m5(struct wpa_sm *sm,
00471                                          const unsigned char *src_addr,
00472                                          const struct wpa_eapol_key *key,
00473                                          int ver,
00474                                          struct wpa_peerkey *peerkey,
00475                                          struct wpa_eapol_ie_parse *kde)
00476 {
00477         int cipher;
00478         struct wpa_ie_data ie;
00479 
00480         wpa_printf(MSG_DEBUG, "RSN: Received SMK M5 (Peer " MACSTR ")",
00481                    MAC2STR(kde->mac_addr));
00482         if (kde->rsn_ie == NULL || kde->rsn_ie_len > PEERKEY_MAX_IE_LEN ||
00483             wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0) {
00484                 wpa_printf(MSG_INFO, "RSN: No RSN IE in SMK M5");
00485                 /* TODO: abort negotiation */
00486                 return -1;
00487         }
00488 
00489         if (os_memcmp(key->key_nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) {
00490                 wpa_printf(MSG_INFO, "RSN: Key Nonce in SMK M5 does "
00491                            "not match with INonce used in SMK M1");
00492                 return -1;
00493         }
00494 
00495         if (os_memcmp(kde->smk + PMK_LEN, peerkey->inonce, WPA_NONCE_LEN) != 0)
00496         {
00497                 wpa_printf(MSG_INFO, "RSN: INonce in SMK KDE does not "
00498                            "match with the one used in SMK M1");
00499                 return -1;
00500         }
00501 
00502         os_memcpy(peerkey->rsnie_p, kde->rsn_ie, kde->rsn_ie_len);
00503         peerkey->rsnie_p_len = kde->rsn_ie_len;
00504         os_memcpy(peerkey->pnonce, kde->nonce, WPA_NONCE_LEN);
00505 
00506         cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher;
00507         if (cipher & WPA_CIPHER_CCMP) {
00508                 wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey");
00509                 peerkey->cipher = WPA_CIPHER_CCMP;
00510         } else if (cipher & WPA_CIPHER_TKIP) {
00511                 wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey");
00512                 peerkey->cipher = WPA_CIPHER_TKIP;
00513         } else {
00514                 wpa_printf(MSG_INFO, "RSN: SMK Peer STA " MACSTR " selected "
00515                            "unacceptable cipher", MAC2STR(kde->mac_addr));
00516                 wpa_supplicant_send_smk_error(sm, src_addr, kde->mac_addr,
00517                                               STK_MUI_SMK, STK_ERR_CPHR_NS,
00518                                               ver);
00519                 /* TODO: abort negotiation */
00520                 return -1;
00521         }
00522 
00523         return 0;
00524 }
00525 
00526 
00527 static int wpa_supplicant_process_smk_m45(
00528         struct wpa_sm *sm, const unsigned char *src_addr,
00529         const struct wpa_eapol_key *key, size_t extra_len, int ver)
00530 {
00531         struct wpa_peerkey *peerkey;
00532         struct wpa_eapol_ie_parse kde;
00533         u32 lifetime;
00534         struct os_time now;
00535 
00536         if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
00537                 wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
00538                            "the current network");
00539                 return -1;
00540         }
00541 
00542         if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
00543             0) {
00544                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5");
00545                 return -1;
00546         }
00547 
00548         if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
00549             kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN ||
00550             kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN ||
00551             kde.lifetime == NULL || kde.lifetime_len < 4) {
00552                 wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or "
00553                            "Lifetime KDE in SMK M4/M5");
00554                 return -1;
00555         }
00556 
00557         for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
00558                 if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 &&
00559                     os_memcmp(peerkey->initiator ? peerkey->inonce :
00560                            peerkey->pnonce,
00561                            key->key_nonce, WPA_NONCE_LEN) == 0)
00562                         break;
00563         }
00564         if (peerkey == NULL) {
00565                 wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found "
00566                            "for SMK M4/M5: peer " MACSTR,
00567                            MAC2STR(kde.mac_addr));
00568                 return -1;
00569         }
00570 
00571         if (peerkey->initiator) {
00572                 if (wpa_supplicant_process_smk_m5(sm, src_addr, key, ver,
00573                                                   peerkey, &kde) < 0)
00574                         return -1;
00575         } else {
00576                 if (wpa_supplicant_process_smk_m4(peerkey, &kde) < 0)
00577                         return -1;
00578         }
00579 
00580         os_memcpy(peerkey->smk, kde.smk, PMK_LEN);
00581         peerkey->smk_complete = 1;
00582         wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN);
00583         lifetime = WPA_GET_BE32(kde.lifetime);
00584         wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime);
00585         if (lifetime > 1000000000)
00586                 lifetime = 1000000000; /* avoid overflowing expiration time */
00587         peerkey->lifetime = lifetime;
00588         os_get_time(&now);
00589         peerkey->expiration = now.sec + lifetime;
00590         eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout,
00591                                sm, peerkey);
00592 
00593         if (peerkey->initiator) {
00594                 rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr,
00595                           peerkey->inonce, sm->own_addr, peerkey->smkid,
00596                           peerkey->use_sha256);
00597                 wpa_supplicant_send_stk_1_of_4(sm, peerkey);
00598         } else {
00599                 rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr,
00600                           peerkey->inonce, peerkey->addr, peerkey->smkid,
00601                           peerkey->use_sha256);
00602         }
00603         wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN);
00604 
00605         return 0;
00606 }
00607 
00608 
00609 static int wpa_supplicant_process_smk_error(
00610         struct wpa_sm *sm, const unsigned char *src_addr,
00611         const struct wpa_eapol_key *key, size_t extra_len)
00612 {
00613         struct wpa_eapol_ie_parse kde;
00614         struct rsn_error_kde error;
00615         u8 peer[ETH_ALEN];
00616         u16 error_type;
00617 
00618         wpa_printf(MSG_DEBUG, "RSN: Received SMK Error");
00619 
00620         if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
00621                 wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
00622                            "the current network");
00623                 return -1;
00624         }
00625 
00626         if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
00627             0) {
00628                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
00629                 return -1;
00630         }
00631 
00632         if (kde.error == NULL || kde.error_len < sizeof(error)) {
00633                 wpa_printf(MSG_INFO, "RSN: No Error KDE in SMK Error");
00634                 return -1;
00635         }
00636 
00637         if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN)
00638                 os_memcpy(peer, kde.mac_addr, 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 
00936 int peerkey_verify_eapol_key_mic(struct wpa_sm *sm,
00937                                  struct wpa_peerkey *peerkey,
00938                                  struct wpa_eapol_key *key, u16 ver,
00939                                  const u8 *buf, size_t len)
00940 {
00941         u8 mic[16];
00942         int ok = 0;
00943 
00944         if (peerkey->initiator && !peerkey->stk_set) {
00945                 wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion",
00946                                sm->own_addr, peerkey->addr,
00947                                peerkey->inonce, key->key_nonce,
00948                                (u8 *) &peerkey->stk, sizeof(peerkey->stk),
00949                                peerkey->use_sha256);
00950                 peerkey->stk_set = 1;
00951         }
00952 
00953         os_memcpy(mic, key->key_mic, 16);
00954         if (peerkey->tstk_set) {
00955                 os_memset(key->key_mic, 0, 16);
00956                 wpa_eapol_key_mic(peerkey->tstk.kck, ver, buf, len,
00957                                   key->key_mic);
00958                 if (os_memcmp(mic, key->key_mic, 16) != 0) {
00959                         wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
00960                                    "when using TSTK - ignoring TSTK");
00961                 } else {
00962                         ok = 1;
00963                         peerkey->tstk_set = 0;
00964                         peerkey->stk_set = 1;
00965                         os_memcpy(&peerkey->stk, &peerkey->tstk,
00966                                   sizeof(peerkey->stk));
00967                 }
00968         }
00969 
00970         if (!ok && peerkey->stk_set) {
00971                 os_memset(key->key_mic, 0, 16);
00972                 wpa_eapol_key_mic(peerkey->stk.kck, ver, buf, len,
00973                                   key->key_mic);
00974                 if (os_memcmp(mic, key->key_mic, 16) != 0) {
00975                         wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
00976                                    "- dropping packet");
00977                         return -1;
00978                 }
00979                 ok = 1;
00980         }
00981 
00982         if (!ok) {
00983                 wpa_printf(MSG_WARNING, "RSN: Could not verify EAPOL-Key MIC "
00984                            "- dropping packet");
00985                 return -1;
00986         }
00987 
00988         os_memcpy(peerkey->replay_counter, key->replay_counter,
00989                   WPA_REPLAY_COUNTER_LEN);
00990         peerkey->replay_counter_set = 1;
00991         return 0;
00992 }
00993 
00994 
01005 int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer)
01006 {
01007         size_t rlen, kde_len;
01008         struct wpa_eapol_key *req;
01009         int key_info, ver;
01010         u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos;
01011         u16 count;
01012         struct rsn_ie_hdr *hdr;
01013         struct wpa_peerkey *peerkey;
01014         struct wpa_ie_data ie;
01015 
01016         if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set || !sm->peerkey_enabled)
01017                 return -1;
01018 
01019         if (sm->ap_rsn_ie &&
01020             wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 &&
01021             !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) {
01022                 wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK");
01023                 return -1;
01024         }
01025 
01026         if (sm->pairwise_cipher == WPA_CIPHER_CCMP)
01027                 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
01028         else
01029                 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
01030 
01031         if (wpa_sm_get_bssid(sm, bssid) < 0) {
01032                 wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key "
01033                            "SMK M1");
01034                 return -1;
01035         }
01036 
01037         /* TODO: find existing entry and if found, use that instead of adding
01038          * a new one */
01039         peerkey = os_zalloc(sizeof(*peerkey));
01040         if (peerkey == NULL)
01041                 return -1;
01042         peerkey->initiator = 1;
01043         os_memcpy(peerkey->addr, peer, ETH_ALEN);
01044 #ifdef CONFIG_IEEE80211W
01045         if (wpa_key_mgmt_sha256(sm->key_mgmt))
01046                 peerkey->use_sha256 = 1;
01047 #endif /* CONFIG_IEEE80211W */
01048 
01049         /* SMK M1:
01050          * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
01051          *           MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE))
01052          */
01053 
01054         hdr = (struct rsn_ie_hdr *) peerkey->rsnie_i;
01055         hdr->elem_id = WLAN_EID_RSN;
01056         WPA_PUT_LE16(hdr->version, RSN_VERSION);
01057         pos = (u8 *) (hdr + 1);
01058         /* Group Suite can be anything for SMK RSN IE; receiver will just
01059          * ignore it. */
01060         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
01061         pos += RSN_SELECTOR_LEN;
01062         count_pos = pos;
01063         pos += 2;
01064 
01065         count = 0;
01066         if (sm->allowed_pairwise_cipher & WPA_CIPHER_CCMP) {
01067                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
01068                 pos += RSN_SELECTOR_LEN;
01069                 count++;
01070         }
01071         if (sm->allowed_pairwise_cipher & WPA_CIPHER_TKIP) {
01072                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
01073                 pos += RSN_SELECTOR_LEN;
01074                 count++;
01075         }
01076         WPA_PUT_LE16(count_pos, count);
01077 
01078         hdr->len = (pos - peerkey->rsnie_i) - 2;
01079         peerkey->rsnie_i_len = pos - peerkey->rsnie_i;
01080         wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",
01081                     peerkey->rsnie_i, peerkey->rsnie_i_len);
01082 
01083         kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
01084 
01085         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
01086                                   sizeof(*req) + kde_len, &rlen,
01087                                   (void *) &req);
01088         if (rbuf == NULL) {
01089                 wpa_supplicant_peerkey_free(sm, peerkey);
01090                 return -1;
01091         }
01092 
01093         req->type = EAPOL_KEY_TYPE_RSN;
01094         key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
01095                 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver;
01096         WPA_PUT_BE16(req->key_info, key_info);
01097         WPA_PUT_BE16(req->key_length, 0);
01098         os_memcpy(req->replay_counter, sm->request_counter,
01099                   WPA_REPLAY_COUNTER_LEN);
01100         inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
01101 
01102         if (os_get_random(peerkey->inonce, WPA_NONCE_LEN)) {
01103                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
01104                         "WPA: Failed to get random data for INonce");
01105                 os_free(rbuf);
01106                 wpa_supplicant_peerkey_free(sm, peerkey);
01107                 return -1;
01108         }
01109         os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
01110         wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake",
01111                     req->key_nonce, WPA_NONCE_LEN);
01112 
01113         WPA_PUT_BE16(req->key_data_length, (u16) kde_len);
01114         pos = (u8 *) (req + 1);
01115 
01116         /* Initiator RSN IE */
01117         pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);
01118         /* Peer MAC address KDE */
01119         wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);
01120 
01121         wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer "
01122                    MACSTR ")", MAC2STR(peer));
01123         wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL,
01124                            rbuf, rlen, req->key_mic);
01125 
01126         peerkey->next = sm->peerkey;
01127         sm->peerkey = peerkey;
01128 
01129         return 0;
01130 }
01131 
01132 
01138 void peerkey_deinit(struct wpa_sm *sm)
01139 {
01140         struct wpa_peerkey *prev, *peerkey = sm->peerkey;
01141         while (peerkey) {
01142                 prev = peerkey;
01143                 peerkey = peerkey->next;
01144                 os_free(prev);
01145         }
01146 }
01147 
01148 
01149 void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey,
01150                            struct wpa_eapol_key *key, u16 key_info, u16 ver)
01151 {
01152         if ((key_info & (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) ==
01153             (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) {
01154                 /* 3/4 STK 4-Way Handshake */
01155                 wpa_supplicant_process_stk_3_of_4(sm, peerkey, key, ver);
01156         } else if (key_info & WPA_KEY_INFO_ACK) {
01157                 /* 1/4 STK 4-Way Handshake */
01158                 wpa_supplicant_process_stk_1_of_4(sm, peerkey, key, ver);
01159         } else if (key_info & WPA_KEY_INFO_SECURE) {
01160                 /* 4/4 STK 4-Way Handshake */
01161                 wpa_supplicant_process_stk_4_of_4(sm, peerkey, key, ver);
01162         } else {
01163                 /* 2/4 STK 4-Way Handshake */
01164                 wpa_supplicant_process_stk_2_of_4(sm, peerkey, key, ver);
01165         }
01166 }
01167 
01168 
01169 void peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr,
01170                           struct wpa_eapol_key *key, size_t extra_len,
01171                           u16 key_info, u16 ver)
01172 {
01173         if (key_info & WPA_KEY_INFO_ERROR) {
01174                 /* SMK Error */
01175                 wpa_supplicant_process_smk_error(sm, src_addr, key, extra_len);
01176         } else if (key_info & WPA_KEY_INFO_ACK) {
01177                 /* SMK M2 */
01178                 wpa_supplicant_process_smk_m2(sm, src_addr, key, extra_len,
01179                                               ver);
01180         } else {
01181                 /* SMK M4 or M5 */
01182                 wpa_supplicant_process_smk_m45(sm, src_addr, key, extra_len,
01183                                                ver);
01184         }
01185 }
01186 
01187 #endif /* CONFIG_PEERKEY */
01188 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:48 2009 for hostapd by  doxygen 1.6.1