wpa_ie.c

Go to the documentation of this file.
00001 
00016 #include "includes.h"
00017 
00018 #include "common.h"
00019 #include "wpa.h"
00020 #include "pmksa_cache.h"
00021 #include "ieee802_11_defs.h"
00022 #include "wpa_i.h"
00023 #include "wpa_ie.h"
00024 
00025 
00026 static int wpa_selector_to_bitfield(const u8 *s)
00027 {
00028         if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
00029                 return WPA_CIPHER_NONE;
00030         if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40)
00031                 return WPA_CIPHER_WEP40;
00032         if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
00033                 return WPA_CIPHER_TKIP;
00034         if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
00035                 return WPA_CIPHER_CCMP;
00036         if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104)
00037                 return WPA_CIPHER_WEP104;
00038         return 0;
00039 }
00040 
00041 
00042 static int wpa_key_mgmt_to_bitfield(const u8 *s)
00043 {
00044         if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
00045                 return WPA_KEY_MGMT_IEEE8021X;
00046         if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
00047                 return WPA_KEY_MGMT_PSK;
00048         if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE)
00049                 return WPA_KEY_MGMT_WPA_NONE;
00050         return 0;
00051 }
00052 
00053 
00054 static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
00055                                 struct wpa_ie_data *data)
00056 {
00057         const struct wpa_ie_hdr *hdr;
00058         const u8 *pos;
00059         int left;
00060         int i, count;
00061 
00062         os_memset(data, 0, sizeof(*data));
00063         data->proto = WPA_PROTO_WPA;
00064         data->pairwise_cipher = WPA_CIPHER_TKIP;
00065         data->group_cipher = WPA_CIPHER_TKIP;
00066         data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
00067         data->capabilities = 0;
00068         data->pmkid = NULL;
00069         data->num_pmkid = 0;
00070         data->mgmt_group_cipher = 0;
00071 
00072         if (wpa_ie_len == 0) {
00073                 /* No WPA IE - fail silently */
00074                 return -1;
00075         }
00076 
00077         if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) {
00078                 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
00079                            __func__, (unsigned long) wpa_ie_len);
00080                 return -1;
00081         }
00082 
00083         hdr = (const struct wpa_ie_hdr *) wpa_ie;
00084 
00085         if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
00086             hdr->len != wpa_ie_len - 2 ||
00087             RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
00088             WPA_GET_LE16(hdr->version) != WPA_VERSION) {
00089                 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
00090                            __func__);
00091                 return -1;
00092         }
00093 
00094         pos = (const u8 *) (hdr + 1);
00095         left = wpa_ie_len - sizeof(*hdr);
00096 
00097         if (left >= WPA_SELECTOR_LEN) {
00098                 data->group_cipher = wpa_selector_to_bitfield(pos);
00099                 pos += WPA_SELECTOR_LEN;
00100                 left -= WPA_SELECTOR_LEN;
00101         } else if (left > 0) {
00102                 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
00103                            __func__, left);
00104                 return -1;
00105         }
00106 
00107         if (left >= 2) {
00108                 data->pairwise_cipher = 0;
00109                 count = WPA_GET_LE16(pos);
00110                 pos += 2;
00111                 left -= 2;
00112                 if (count == 0 || left < count * WPA_SELECTOR_LEN) {
00113                         wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
00114                                    "count %u left %u", __func__, count, left);
00115                         return -1;
00116                 }
00117                 for (i = 0; i < count; i++) {
00118                         data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
00119                         pos += WPA_SELECTOR_LEN;
00120                         left -= WPA_SELECTOR_LEN;
00121                 }
00122         } else if (left == 1) {
00123                 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
00124                            __func__);
00125                 return -1;
00126         }
00127 
00128         if (left >= 2) {
00129                 data->key_mgmt = 0;
00130                 count = WPA_GET_LE16(pos);
00131                 pos += 2;
00132                 left -= 2;
00133                 if (count == 0 || left < count * WPA_SELECTOR_LEN) {
00134                         wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
00135                                    "count %u left %u", __func__, count, left);
00136                         return -1;
00137                 }
00138                 for (i = 0; i < count; i++) {
00139                         data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
00140                         pos += WPA_SELECTOR_LEN;
00141                         left -= WPA_SELECTOR_LEN;
00142                 }
00143         } else if (left == 1) {
00144                 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
00145                            __func__);
00146                 return -1;
00147         }
00148 
00149         if (left >= 2) {
00150                 data->capabilities = WPA_GET_LE16(pos);
00151                 pos += 2;
00152                 left -= 2;
00153         }
00154 
00155         if (left > 0) {
00156                 wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",
00157                            __func__, left);
00158         }
00159 
00160         return 0;
00161 }
00162 
00163 
00174 int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
00175                      struct wpa_ie_data *data)
00176 {
00177         if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN)
00178                 return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
00179         else
00180                 return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
00181 }
00182 
00183 
00184 static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len,
00185                               int pairwise_cipher, int group_cipher,
00186                               int key_mgmt)
00187 {
00188         u8 *pos;
00189         struct wpa_ie_hdr *hdr;
00190 
00191         if (wpa_ie_len < sizeof(*hdr) + WPA_SELECTOR_LEN +
00192             2 + WPA_SELECTOR_LEN + 2 + WPA_SELECTOR_LEN)
00193                 return -1;
00194 
00195         hdr = (struct wpa_ie_hdr *) wpa_ie;
00196         hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC;
00197         RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE);
00198         WPA_PUT_LE16(hdr->version, WPA_VERSION);
00199         pos = (u8 *) (hdr + 1);
00200 
00201         if (group_cipher == WPA_CIPHER_CCMP) {
00202                 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
00203         } else if (group_cipher == WPA_CIPHER_TKIP) {
00204                 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
00205         } else if (group_cipher == WPA_CIPHER_WEP104) {
00206                 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP104);
00207         } else if (group_cipher == WPA_CIPHER_WEP40) {
00208                 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP40);
00209         } else {
00210                 wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
00211                            group_cipher);
00212                 return -1;
00213         }
00214         pos += WPA_SELECTOR_LEN;
00215 
00216         *pos++ = 1;
00217         *pos++ = 0;
00218         if (pairwise_cipher == WPA_CIPHER_CCMP) {
00219                 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
00220         } else if (pairwise_cipher == WPA_CIPHER_TKIP) {
00221                 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
00222         } else if (pairwise_cipher == WPA_CIPHER_NONE) {
00223                 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
00224         } else {
00225                 wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
00226                            pairwise_cipher);
00227                 return -1;
00228         }
00229         pos += WPA_SELECTOR_LEN;
00230 
00231         *pos++ = 1;
00232         *pos++ = 0;
00233         if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
00234                 RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
00235         } else if (key_mgmt == WPA_KEY_MGMT_PSK) {
00236                 RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
00237         } else if (key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
00238                 RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_NONE);
00239         } else {
00240                 wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
00241                            key_mgmt);
00242                 return -1;
00243         }
00244         pos += WPA_SELECTOR_LEN;
00245 
00246         /* WPA Capabilities; use defaults, so no need to include it */
00247 
00248         hdr->len = (pos - wpa_ie) - 2;
00249 
00250         WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len);
00251 
00252         return pos - wpa_ie;
00253 }
00254 
00255 
00256 static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
00257                               int pairwise_cipher, int group_cipher,
00258                               int key_mgmt, int mgmt_group_cipher,
00259                               struct wpa_sm *sm)
00260 {
00261 #ifndef CONFIG_NO_WPA2
00262         u8 *pos;
00263         struct rsn_ie_hdr *hdr;
00264         u16 capab;
00265 
00266         if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN +
00267             2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 +
00268             (sm->cur_pmksa ? 2 + PMKID_LEN : 0)) {
00269                 wpa_printf(MSG_DEBUG, "RSN: Too short IE buffer (%lu bytes)",
00270                            (unsigned long) rsn_ie_len);
00271                 return -1;
00272         }
00273 
00274         hdr = (struct rsn_ie_hdr *) rsn_ie;
00275         hdr->elem_id = WLAN_EID_RSN;
00276         WPA_PUT_LE16(hdr->version, RSN_VERSION);
00277         pos = (u8 *) (hdr + 1);
00278 
00279         if (group_cipher == WPA_CIPHER_CCMP) {
00280                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
00281         } else if (group_cipher == WPA_CIPHER_TKIP) {
00282                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
00283         } else if (group_cipher == WPA_CIPHER_WEP104) {
00284                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP104);
00285         } else if (group_cipher == WPA_CIPHER_WEP40) {
00286                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP40);
00287         } else {
00288                 wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
00289                            group_cipher);
00290                 return -1;
00291         }
00292         pos += RSN_SELECTOR_LEN;
00293 
00294         *pos++ = 1;
00295         *pos++ = 0;
00296         if (pairwise_cipher == WPA_CIPHER_CCMP) {
00297                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
00298         } else if (pairwise_cipher == WPA_CIPHER_TKIP) {
00299                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
00300         } else if (pairwise_cipher == WPA_CIPHER_NONE) {
00301                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
00302         } else {
00303                 wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
00304                            pairwise_cipher);
00305                 return -1;
00306         }
00307         pos += RSN_SELECTOR_LEN;
00308 
00309         *pos++ = 1;
00310         *pos++ = 0;
00311         if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
00312                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
00313         } else if (key_mgmt == WPA_KEY_MGMT_PSK) {
00314                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
00315 #ifdef CONFIG_IEEE80211R
00316         } else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) {
00317                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
00318         } else if (key_mgmt == WPA_KEY_MGMT_FT_PSK) {
00319                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
00320 #endif /* CONFIG_IEEE80211R */
00321 #ifdef CONFIG_IEEE80211W
00322         } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA256) {
00323                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
00324         } else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) {
00325                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
00326 #endif /* CONFIG_IEEE80211W */
00327         } else {
00328                 wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
00329                            key_mgmt);
00330                 return -1;
00331         }
00332         pos += RSN_SELECTOR_LEN;
00333 
00334         /* RSN Capabilities */
00335         capab = 0;
00336 #ifdef CONFIG_IEEE80211W
00337         if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC)
00338                 capab |= WPA_CAPABILITY_MFPC;
00339 #endif /* CONFIG_IEEE80211W */
00340         WPA_PUT_LE16(pos, capab);
00341         pos += 2;
00342 
00343         if (sm->cur_pmksa) {
00344                 /* PMKID Count (2 octets, little endian) */
00345                 *pos++ = 1;
00346                 *pos++ = 0;
00347                 /* PMKID */
00348                 os_memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN);
00349                 pos += PMKID_LEN;
00350         }
00351 
00352 #ifdef CONFIG_IEEE80211W
00353         if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
00354                 if (!sm->cur_pmksa) {
00355                         /* PMKID Count */
00356                         WPA_PUT_LE16(pos, 0);
00357                         pos += 2;
00358                 }
00359 
00360                 /* Management Group Cipher Suite */
00361                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
00362                 pos += RSN_SELECTOR_LEN;
00363         }
00364 #endif /* CONFIG_IEEE80211W */
00365 
00366         hdr->len = (pos - rsn_ie) - 2;
00367 
00368         WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len);
00369 
00370         return pos - rsn_ie;
00371 #else /* CONFIG_NO_WPA2 */
00372         return -1;
00373 #endif /* CONFIG_NO_WPA2 */
00374 }
00375 
00376 
00385 int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len)
00386 {
00387         if (sm->proto == WPA_PROTO_RSN)
00388                 return wpa_gen_wpa_ie_rsn(wpa_ie, wpa_ie_len,
00389                                           sm->pairwise_cipher,
00390                                           sm->group_cipher,
00391                                           sm->key_mgmt, sm->mgmt_group_cipher,
00392                                           sm);
00393         else
00394                 return wpa_gen_wpa_ie_wpa(wpa_ie, wpa_ie_len,
00395                                           sm->pairwise_cipher,
00396                                           sm->group_cipher,
00397                                           sm->key_mgmt);
00398 }
00399 
00400 
00409 static int wpa_parse_generic(const u8 *pos, const u8 *end,
00410                              struct wpa_eapol_ie_parse *ie)
00411 {
00412         if (pos[1] == 0)
00413                 return 1;
00414 
00415         if (pos[1] >= 6 &&
00416             RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE &&
00417             pos[2 + WPA_SELECTOR_LEN] == 1 &&
00418             pos[2 + WPA_SELECTOR_LEN + 1] == 0) {
00419                 ie->wpa_ie = pos;
00420                 ie->wpa_ie_len = pos[1] + 2;
00421                 return 0;
00422         }
00423 
00424         if (pos + 1 + RSN_SELECTOR_LEN < end &&
00425             pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
00426             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
00427                 ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
00428                 return 0;
00429         }
00430 
00431         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
00432             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) {
00433                 ie->gtk = pos + 2 + RSN_SELECTOR_LEN;
00434                 ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;
00435                 return 0;
00436         }
00437 
00438         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
00439             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) {
00440                 ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;
00441                 ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;
00442                 return 0;
00443         }
00444 
00445 #ifdef CONFIG_PEERKEY
00446         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
00447             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) {
00448                 ie->smk = pos + 2 + RSN_SELECTOR_LEN;
00449                 ie->smk_len = pos[1] - RSN_SELECTOR_LEN;
00450                 return 0;
00451         }
00452 
00453         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
00454             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) {
00455                 ie->nonce = pos + 2 + RSN_SELECTOR_LEN;
00456                 ie->nonce_len = pos[1] - RSN_SELECTOR_LEN;
00457                 return 0;
00458         }
00459 
00460         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
00461             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) {
00462                 ie->lifetime = pos + 2 + RSN_SELECTOR_LEN;
00463                 ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN;
00464                 return 0;
00465         }
00466 
00467         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
00468             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) {
00469                 ie->error = pos + 2 + RSN_SELECTOR_LEN;
00470                 ie->error_len = pos[1] - RSN_SELECTOR_LEN;
00471                 return 0;
00472         }
00473 #endif /* CONFIG_PEERKEY */
00474 
00475 #ifdef CONFIG_IEEE80211W
00476         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
00477             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
00478                 ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
00479                 ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
00480                 return 0;
00481         }
00482 #endif /* CONFIG_IEEE80211W */
00483 
00484         return 0;
00485 }
00486 
00487 
00496 int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
00497                              struct wpa_eapol_ie_parse *ie)
00498 {
00499         const u8 *pos, *end;
00500         int ret = 0;
00501 
00502         os_memset(ie, 0, sizeof(*ie));
00503         for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
00504                 if (pos[0] == 0xdd &&
00505                     ((pos == buf + len - 1) || pos[1] == 0)) {
00506                         /* Ignore padding */
00507                         break;
00508                 }
00509                 if (pos + 2 + pos[1] > end) {
00510                         wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "
00511                                    "underflow (ie=%d len=%d pos=%d)",
00512                                    pos[0], pos[1], (int) (pos - buf));
00513                         wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data",
00514                                         buf, len);
00515                         ret = -1;
00516                         break;
00517                 }
00518                 if (*pos == WLAN_EID_RSN) {
00519                         ie->rsn_ie = pos;
00520                         ie->rsn_ie_len = pos[1] + 2;
00521 #ifdef CONFIG_IEEE80211R
00522                 } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
00523                         ie->mdie = pos;
00524                         ie->mdie_len = pos[1] + 2;
00525 #endif /* CONFIG_IEEE80211R */
00526                 } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
00527                         ret = wpa_parse_generic(pos, end, ie);
00528                         if (ret < 0)
00529                                 break;
00530                         if (ret > 0) {
00531                                 ret = 0;
00532                                 break;
00533                         }
00534                 } else {
00535                         wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "
00536                                     "Key Data IE", pos, 2 + pos[1]);
00537                 }
00538         }
00539 
00540         return ret;
00541 }
00542 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

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