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


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