Remove src/crypto from default include path
[libeap.git] / hostapd / wpa.c
index e995562..73425e6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * hostapd - IEEE 802.11i-2004 / WPA Authenticator
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #ifndef CONFIG_NATIVE_WINDOWS
 
 #include "common.h"
+#include "eloop.h"
+#include "crypto/aes_wrap.h"
+#include "crypto/crypto.h"
+#include "crypto/sha1.h"
+#include "crypto/sha256.h"
+#include "eapol_auth/eapol_auth_sm.h"
 #include "config.h"
-#include "eapol_sm.h"
 #include "wpa.h"
-#include "sha1.h"
-#include "sha256.h"
-#include "rc4.h"
-#include "aes_wrap.h"
-#include "crypto.h"
-#include "eloop.h"
 #include "ieee802_11.h"
 #include "pmksa_cache.h"
 #include "state_machine.h"
@@ -44,6 +43,8 @@ static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx);
 static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
                              struct wpa_group *group);
 static void wpa_request_new_ptk(struct wpa_state_machine *sm);
+static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
+                         struct wpa_group *group);
 
 static const u32 dot11RSNAConfigGroupUpdateCount = 4;
 static const u32 dot11RSNAConfigPairwiseUpdateCount = 4;
@@ -102,7 +103,7 @@ static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth,
 
 static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
                                   int vlan_id,
-                                  const char *alg, const u8 *addr, int idx,
+                                  wpa_alg alg, const u8 *addr, int idx,
                                   u8 *key, size_t key_len)
 {
        if (wpa_auth->cb.set_key == NULL)
@@ -286,21 +287,9 @@ static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
 }
 
 
-static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
-                                        int vlan_id)
+static void wpa_group_set_key_len(struct wpa_group *group, int cipher)
 {
-       struct wpa_group *group;
-       u8 buf[ETH_ALEN + 8 + sizeof(group)];
-       u8 rkey[32];
-
-       group = os_zalloc(sizeof(struct wpa_group));
-       if (group == NULL)
-               return NULL;
-
-       group->GTKAuthenticator = TRUE;
-       group->vlan_id = vlan_id;
-
-       switch (wpa_auth->conf.wpa_group) {
+       switch (cipher) {
        case WPA_CIPHER_CCMP:
                group->GTK_len = 16;
                break;
@@ -314,6 +303,24 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
                group->GTK_len = 5;
                break;
        }
+}
+
+
+static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
+                                        int vlan_id)
+{
+       struct wpa_group *group;
+       u8 buf[ETH_ALEN + 8 + sizeof(group)];
+       u8 rkey[32];
+
+       group = os_zalloc(sizeof(struct wpa_group));
+       if (group == NULL)
+               return NULL;
+
+       group->GTKAuthenticator = TRUE;
+       group->vlan_id = vlan_id;
+
+       wpa_group_set_key_len(group, wpa_auth->conf.wpa_group);
 
        /* Counter = PRF-256(Random number, "Init Counter",
         *                   Local MAC Address || Time)
@@ -345,6 +352,7 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
  * wpa_init - Initialize WPA authenticator
  * @addr: Authenticator address
  * @conf: Configuration for WPA authenticator
+ * @cb: Callback functions for WPA authenticator
  * Returns: Pointer to WPA authenticator data or %NULL on failure
  */
 struct wpa_authenticator * wpa_init(const u8 *addr,
@@ -373,7 +381,8 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
                return NULL;
        }
 
-       wpa_auth->pmksa = pmksa_cache_init(wpa_auth_pmksa_free_cb, wpa_auth);
+       wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb,
+                                               wpa_auth);
        if (wpa_auth->pmksa == NULL) {
                wpa_printf(MSG_ERROR, "PMKSA cache initialization failed.");
                os_free(wpa_auth->wpa_ie);
@@ -386,7 +395,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
        if (wpa_auth->ft_pmk_cache == NULL) {
                wpa_printf(MSG_ERROR, "FT PMK cache initialization failed.");
                os_free(wpa_auth->wpa_ie);
-               pmksa_cache_deinit(wpa_auth->pmksa);
+               pmksa_cache_auth_deinit(wpa_auth->pmksa);
                os_free(wpa_auth);
                return NULL;
        }
@@ -422,7 +431,7 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth)
                wpa_stsl_remove(wpa_auth, wpa_auth->stsl_negotiations);
 #endif /* CONFIG_PEERKEY */
 
-       pmksa_cache_deinit(wpa_auth->pmksa);
+       pmksa_cache_auth_deinit(wpa_auth->pmksa);
 
 #ifdef CONFIG_IEEE80211R
        wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache);
@@ -450,6 +459,7 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth)
 int wpa_reconfig(struct wpa_authenticator *wpa_auth,
                 struct wpa_auth_config *conf)
 {
+       struct wpa_group *group;
        if (wpa_auth == NULL)
                return 0;
 
@@ -459,6 +469,17 @@ int wpa_reconfig(struct wpa_authenticator *wpa_auth,
                return -1;
        }
 
+       /*
+        * Reinitialize GTK to make sure it is suitable for the new
+        * configuration.
+        */
+       group = wpa_auth->group;
+       wpa_group_set_key_len(group, wpa_auth->conf.wpa_group);
+       group->GInit = TRUE;
+       wpa_group_sm_step(wpa_auth, group);
+       group->GInit = FALSE;
+       wpa_group_sm_step(wpa_auth, group);
+
        return 0;
 }
 
@@ -618,6 +639,22 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
                return;
        }
 
+       if (sm->wpa == WPA_VERSION_WPA2) {
+               if (key->type != EAPOL_KEY_TYPE_RSN) {
+                       wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with "
+                                  "unexpected type %d in RSN mode",
+                                  key->type);
+                       return;
+               }
+       } else {
+               if (key->type != EAPOL_KEY_TYPE_WPA) {
+                       wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with "
+                                  "unexpected type %d in WPA mode",
+                                  key->type);
+                       return;
+               }
+       }
+
        /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys
         * are set */
 
@@ -1141,7 +1178,8 @@ void wpa_remove_ptk(struct wpa_state_machine *sm)
 {
        sm->PTK_valid = FALSE;
        os_memset(&sm->PTK, 0, sizeof(sm->PTK));
-       wpa_auth_set_key(sm->wpa_auth, 0, "none", sm->addr, 0, (u8 *) "", 0);
+       wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, (u8 *) "",
+                        0);
        sm->pairwise_set = FALSE;
        eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
 }
@@ -1209,18 +1247,18 @@ void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event)
 }
 
 
-static const char * wpa_alg_txt(int alg)
+static wpa_alg wpa_alg_enum(int alg)
 {
        switch (alg) {
        case WPA_CIPHER_CCMP:
-               return "CCMP";
+               return WPA_ALG_CCMP;
        case WPA_CIPHER_TKIP:
-               return "TKIP";
+               return WPA_ALG_TKIP;
        case WPA_CIPHER_WEP104:
        case WPA_CIPHER_WEP40:
-               return "WEP";
+               return WPA_ALG_WEP;
        default:
-               return "";
+               return WPA_ALG_NONE;
        }
 }
 
@@ -1402,14 +1440,15 @@ SM_STATE(WPA_PTK, PTKSTART)
 static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *pmk,
                          struct wpa_ptk *ptk)
 {
+       size_t ptk_len = sm->pairwise == WPA_CIPHER_CCMP ? 48 : 64;
 #ifdef CONFIG_IEEE80211R
        if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
-               return wpa_auth_derive_ptk_ft(sm, pmk, ptk);
+               return wpa_auth_derive_ptk_ft(sm, pmk, ptk, ptk_len);
 #endif /* CONFIG_IEEE80211R */
 
        wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion",
                       sm->wpa_auth->addr, sm->addr, sm->ANonce, sm->SNonce,
-                      (u8 *) ptk, sizeof(*ptk),
+                      (u8 *) ptk, ptk_len,
                       wpa_key_mgmt_sha256(sm->wpa_key_mgmt));
 
        return 0;
@@ -1608,13 +1647,13 @@ SM_STATE(WPA_PTK, PTKINITDONE)
        SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
        sm->EAPOLKeyReceived = FALSE;
        if (sm->Pair) {
-               char *alg;
+               wpa_alg alg;
                int klen;
                if (sm->pairwise == WPA_CIPHER_TKIP) {
-                       alg = "TKIP";
+                       alg = WPA_ALG_TKIP;
                        klen = 32;
                } else {
-                       alg = "CCMP";
+                       alg = WPA_ALG_CCMP;
                        klen = 16;
                }
                if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
@@ -1994,13 +2033,13 @@ static void wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
        group->changed = TRUE;
        group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
        wpa_auth_set_key(wpa_auth, group->vlan_id,
-                        wpa_alg_txt(wpa_auth->conf.wpa_group),
+                        wpa_alg_enum(wpa_auth->conf.wpa_group),
                         NULL, group->GN, group->GTK[group->GN - 1],
                         group->GTK_len);
 
 #ifdef CONFIG_IEEE80211W
        if (wpa_auth->conf.ieee80211w != WPA_NO_IEEE80211W) {
-               wpa_auth_set_key(wpa_auth, group->vlan_id, "IGTK",
+               wpa_auth_set_key(wpa_auth, group->vlan_id, WPA_ALG_IGTK,
                                 NULL, group->GN_igtk,
                                 group->IGTK[group->GN_igtk - 4],
                                 WPA_IGTK_LEN);
@@ -2366,9 +2405,9 @@ int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
        if (sm == NULL || sm->wpa != WPA_VERSION_WPA2)
                return -1;
 
-       if (pmksa_cache_add(sm->wpa_auth->pmksa, pmk, PMK_LEN,
-                           sm->wpa_auth->addr, sm->addr, session_timeout,
-                           eapol, sm->wpa_key_mgmt))
+       if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, PMK_LEN,
+                                sm->wpa_auth->addr, sm->addr, session_timeout,
+                                eapol, sm->wpa_key_mgmt))
                return 0;
 
        return -1;
@@ -2383,9 +2422,9 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
        if (wpa_auth == NULL)
                return -1;
 
-       if (pmksa_cache_add(wpa_auth->pmksa, pmk, len, wpa_auth->addr,
-                           sta_addr, session_timeout, eapol,
-                           WPA_KEY_MGMT_IEEE8021X))
+       if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, wpa_auth->addr,
+                                sta_addr, session_timeout, eapol,
+                                WPA_KEY_MGMT_IEEE8021X))
                return 0;
 
        return -1;