peerkey.c

Go to the documentation of this file.
00001 
00016 #include "includes.h"
00017 
00018 #include "common.h"
00019 #include "eloop.h"
00020 #include "sha1.h"
00021 #include "sha256.h"
00022 #include "wpa.h"
00023 #include "defs.h"
00024 #include "wpa_auth_i.h"
00025 #include "wpa_auth_ie.h"
00026 
00027 #ifdef CONFIG_PEERKEY
00028 
00029 static void wpa_stsl_step(void *eloop_ctx, void *timeout_ctx)
00030 {
00031 #if 0
00032         struct wpa_authenticator *wpa_auth = eloop_ctx;
00033         struct wpa_stsl_negotiation *neg = timeout_ctx;
00034 #endif
00035 
00036         /* TODO: ? */
00037 }
00038 
00039 
00040 struct wpa_stsl_search {
00041         const u8 *addr;
00042         struct wpa_state_machine *sm;
00043 };
00044 
00045 
00046 static int wpa_stsl_select_sta(struct wpa_state_machine *sm, void *ctx)
00047 {
00048         struct wpa_stsl_search *search = ctx;
00049         if (os_memcmp(search->addr, sm->addr, ETH_ALEN) == 0) {
00050                 search->sm = sm;
00051                 return 1;
00052         }
00053         return 0;
00054 }
00055 
00056 
00057 static void wpa_smk_send_error(struct wpa_authenticator *wpa_auth,
00058                                struct wpa_state_machine *sm, const u8 *peer,
00059                                u16 mui, u16 error_type)
00060 {
00061         u8 kde[2 + RSN_SELECTOR_LEN + ETH_ALEN +
00062                2 + RSN_SELECTOR_LEN + sizeof(struct rsn_error_kde)];
00063         u8 *pos;
00064         struct rsn_error_kde error;
00065 
00066         wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
00067                         "Sending SMK Error");
00068 
00069         pos = kde;
00070 
00071         if (peer) {
00072                 pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN,
00073                                   NULL, 0);
00074         }
00075 
00076         error.mui = host_to_be16(mui);
00077         error.error_type = host_to_be16(error_type);
00078         pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR,
00079                           (u8 *) &error, sizeof(error), NULL, 0);
00080 
00081         __wpa_send_eapol(wpa_auth, sm,
00082                          WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
00083                          WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_ERROR,
00084                          NULL, NULL, kde, pos - kde, 0, 0, 0);
00085 }
00086 
00087 
00088 void wpa_smk_m1(struct wpa_authenticator *wpa_auth,
00089                 struct wpa_state_machine *sm, struct wpa_eapol_key *key)
00090 {
00091         struct wpa_eapol_ie_parse kde;
00092         struct wpa_stsl_search search;
00093         u8 *buf, *pos;
00094         size_t buf_len;
00095 
00096         if (wpa_parse_kde_ies((const u8 *) (key + 1),
00097                               WPA_GET_BE16(key->key_data_length), &kde) < 0) {
00098                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M1");
00099                 return;
00100         }
00101 
00102         if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
00103             kde.mac_addr_len < ETH_ALEN) {
00104                 wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
00105                            "SMK M1");
00106                 return;
00107         }
00108 
00109         /* Initiator = sm->addr; Peer = kde.mac_addr */
00110 
00111         search.addr = kde.mac_addr;
00112         search.sm = NULL;
00113         if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
00114             0 || search.sm == NULL) {
00115                 wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
00116                            " aborted - STA not associated anymore",
00117                            MAC2STR(kde.mac_addr));
00118                 wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
00119                                    STK_ERR_STA_NR);
00120                 /* FIX: wpa_stsl_remove(wpa_auth, neg); */
00121                 return;
00122         }
00123 
00124         buf_len = kde.rsn_ie_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
00125         buf = os_malloc(buf_len);
00126         if (buf == NULL)
00127                 return;
00128         /* Initiator RSN IE */
00129         os_memcpy(buf, kde.rsn_ie, kde.rsn_ie_len);
00130         pos = buf + kde.rsn_ie_len;
00131         /* Initiator MAC Address */
00132         pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->addr, ETH_ALEN,
00133                           NULL, 0);
00134 
00135         /* SMK M2:
00136          * EAPOL-Key(S=1, M=1, A=1, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
00137          *           MIC=MIC, DataKDs=(RSNIE_I, MAC_I KDE)
00138          */
00139 
00140         wpa_auth_logger(wpa_auth, search.sm->addr, LOGGER_DEBUG,
00141                         "Sending SMK M2");
00142 
00143         __wpa_send_eapol(wpa_auth, search.sm,
00144                          WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
00145                          WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE,
00146                          NULL, key->key_nonce, buf, pos - buf, 0, 0, 0);
00147 
00148         os_free(buf);
00149 }
00150 
00151 
00152 static void wpa_send_smk_m4(struct wpa_authenticator *wpa_auth,
00153                             struct wpa_state_machine *sm,
00154                             struct wpa_eapol_key *key,
00155                             struct wpa_eapol_ie_parse *kde,
00156                             const u8 *smk)
00157 {
00158         u8 *buf, *pos;
00159         size_t buf_len;
00160         u32 lifetime;
00161 
00162         /* SMK M4:
00163          * EAPOL-Key(S=1, M=1, A=0, I=1, K=0, SM=1, KeyRSC=0, Nonce=PNonce,
00164          *           MIC=MIC, DataKDs=(MAC_I KDE, INonce KDE, SMK KDE,
00165          *           Lifetime KDE)
00166          */
00167 
00168         buf_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN +
00169                 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
00170                 2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
00171                 2 + RSN_SELECTOR_LEN + sizeof(lifetime);
00172         pos = buf = os_malloc(buf_len);
00173         if (buf == NULL)
00174                 return;
00175 
00176         /* Initiator MAC Address */
00177         pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, kde->mac_addr, ETH_ALEN,
00178                           NULL, 0);
00179 
00180         /* Initiator Nonce */
00181         pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, kde->nonce, WPA_NONCE_LEN,
00182                           NULL, 0);
00183 
00184         /* SMK with PNonce */
00185         pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
00186                           key->key_nonce, WPA_NONCE_LEN);
00187 
00188         /* Lifetime */
00189         lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
00190         pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
00191                           (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
00192 
00193         wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
00194                         "Sending SMK M4");
00195 
00196         __wpa_send_eapol(wpa_auth, sm,
00197                          WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
00198                          WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_SMK_MESSAGE,
00199                          NULL, key->key_nonce, buf, pos - buf, 0, 1, 0);
00200 
00201         os_free(buf);
00202 }
00203 
00204 
00205 static void wpa_send_smk_m5(struct wpa_authenticator *wpa_auth,
00206                             struct wpa_state_machine *sm,
00207                             struct wpa_eapol_key *key,
00208                             struct wpa_eapol_ie_parse *kde,
00209                             const u8 *smk, const u8 *peer)
00210 {
00211         u8 *buf, *pos;
00212         size_t buf_len;
00213         u32 lifetime;
00214 
00215         /* SMK M5:
00216          * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
00217          *           MIC=MIC, DataKDs=(RSNIE_P, MAC_P KDE, PNonce, SMK KDE,
00218          *                             Lifetime KDE))
00219          */
00220 
00221         buf_len = kde->rsn_ie_len +
00222                 2 + RSN_SELECTOR_LEN + ETH_ALEN +
00223                 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
00224                 2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
00225                 2 + RSN_SELECTOR_LEN + sizeof(lifetime);
00226         pos = buf = os_malloc(buf_len);
00227         if (buf == NULL)
00228                 return;
00229 
00230         /* Peer RSN IE */
00231         os_memcpy(buf, kde->rsn_ie, kde->rsn_ie_len);
00232         pos = buf + kde->rsn_ie_len;
00233 
00234         /* Peer MAC Address */
00235         pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, NULL, 0);
00236 
00237         /* PNonce */
00238         pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, key->key_nonce,
00239                           WPA_NONCE_LEN, NULL, 0);
00240 
00241         /* SMK and INonce */
00242         pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
00243                           kde->nonce, WPA_NONCE_LEN);
00244 
00245         /* Lifetime */
00246         lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
00247         pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
00248                           (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
00249 
00250         wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
00251                         "Sending SMK M5");
00252 
00253         __wpa_send_eapol(wpa_auth, sm,
00254                          WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
00255                          WPA_KEY_INFO_SMK_MESSAGE,
00256                          NULL, kde->nonce, buf, pos - buf, 0, 1, 0);
00257 
00258         os_free(buf);
00259 }
00260 
00261 
00262 void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
00263                 struct wpa_state_machine *sm, struct wpa_eapol_key *key)
00264 {
00265         struct wpa_eapol_ie_parse kde;
00266         struct wpa_stsl_search search;
00267         u8 smk[32], buf[ETH_ALEN + 8 + 2 * WPA_NONCE_LEN], *pos;
00268 
00269         if (wpa_parse_kde_ies((const u8 *) (key + 1),
00270                               WPA_GET_BE16(key->key_data_length), &kde) < 0) {
00271                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M3");
00272                 return;
00273         }
00274 
00275         if (kde.rsn_ie == NULL ||
00276             kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
00277             kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN) {
00278                 wpa_printf(MSG_INFO, "RSN: No RSN IE, MAC address KDE, or "
00279                            "Nonce KDE in SMK M3");
00280                 return;
00281         }
00282 
00283         /* Peer = sm->addr; Initiator = kde.mac_addr;
00284          * Peer Nonce = key->key_nonce; Initiator Nonce = kde.nonce */
00285 
00286         search.addr = kde.mac_addr;
00287         search.sm = NULL;
00288         if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
00289             0 || search.sm == NULL) {
00290                 wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
00291                            " aborted - STA not associated anymore",
00292                            MAC2STR(kde.mac_addr));
00293                 wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
00294                                    STK_ERR_STA_NR);
00295                 /* FIX: wpa_stsl_remove(wpa_auth, neg); */
00296                 return;
00297         }
00298 
00299         if (os_get_random(smk, PMK_LEN)) {
00300                 wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK");
00301                 return;
00302         }
00303 
00304         /* SMK = PRF-256(Random number, "SMK Derivation",
00305          *               AA || Time || INonce || PNonce)
00306          */
00307         os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
00308         pos = buf + ETH_ALEN;
00309         wpa_get_ntp_timestamp(pos);
00310         pos += 8;
00311         os_memcpy(pos, kde.nonce, WPA_NONCE_LEN);
00312         pos += WPA_NONCE_LEN;
00313         os_memcpy(pos, key->key_nonce, WPA_NONCE_LEN);
00314 #ifdef CONFIG_IEEE80211W
00315         sha256_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
00316                    smk, PMK_LEN);
00317 #else /* CONFIG_IEEE80211W */
00318         sha1_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
00319                  smk, PMK_LEN);
00320 #endif /* CONFIG_IEEE80211W */
00321 
00322         wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", smk, PMK_LEN);
00323 
00324         wpa_send_smk_m4(wpa_auth, sm, key, &kde, smk);
00325         wpa_send_smk_m5(wpa_auth, search.sm, key, &kde, smk, sm->addr);
00326 
00327         /* Authenticator does not need SMK anymore and it is required to forget
00328          * it. */
00329         os_memset(smk, 0, sizeof(*smk));
00330 }
00331 
00332 
00333 void wpa_smk_error(struct wpa_authenticator *wpa_auth,
00334                    struct wpa_state_machine *sm, struct wpa_eapol_key *key)
00335 {
00336         struct wpa_eapol_ie_parse kde;
00337         struct wpa_stsl_search search;
00338         struct rsn_error_kde error;
00339         u16 mui, error_type;
00340 
00341         if (wpa_parse_kde_ies((const u8 *) (key + 1),
00342                               WPA_GET_BE16(key->key_data_length), &kde) < 0) {
00343                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
00344                 return;
00345         }
00346 
00347         if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
00348             kde.error == NULL || kde.error_len < sizeof(error)) {
00349                 wpa_printf(MSG_INFO, "RSN: No MAC address or Error KDE in "
00350                            "SMK Error");
00351                 return;
00352         }
00353 
00354         search.addr = kde.mac_addr;
00355         search.sm = NULL;
00356         if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
00357             0 || search.sm == NULL) {
00358                 wpa_printf(MSG_DEBUG, "RSN: Peer STA " MACSTR " not "
00359                            "associated for SMK Error message from " MACSTR,
00360                            MAC2STR(kde.mac_addr), MAC2STR(sm->addr));
00361                 return;
00362         }
00363 
00364         os_memcpy(&error, kde.error, sizeof(error));
00365         mui = be_to_host16(error.mui);
00366         error_type = be_to_host16(error.error_type);
00367         wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
00368                          "STA reported SMK Error: Peer " MACSTR
00369                          " MUI %d Error Type %d",
00370                          MAC2STR(kde.mac_addr), mui, error_type);
00371 
00372         wpa_smk_send_error(wpa_auth, search.sm, sm->addr, mui, error_type);
00373 }
00374 
00375 
00376 int wpa_stsl_remove(struct wpa_authenticator *wpa_auth,
00377                     struct wpa_stsl_negotiation *neg)
00378 {
00379         struct wpa_stsl_negotiation *pos, *prev;
00380 
00381         if (wpa_auth == NULL)
00382                 return -1;
00383         pos = wpa_auth->stsl_negotiations;
00384         prev = NULL;
00385         while (pos) {
00386                 if (pos == neg) {
00387                         if (prev)
00388                                 prev->next = pos->next;
00389                         else
00390                                 wpa_auth->stsl_negotiations = pos->next;
00391 
00392                         eloop_cancel_timeout(wpa_stsl_step, wpa_auth, pos);
00393                         os_free(pos);
00394                         return 0;
00395                 }
00396                 prev = pos;
00397                 pos = pos->next;
00398         }
00399 
00400         return -1;
00401 }
00402 
00403 #endif /* CONFIG_PEERKEY */
00404 
 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