]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Added support for enforcing frequent PTK rekeying
authorJouni Malinen <jouni.malinen@atheros.com>
Thu, 6 Nov 2008 17:57:21 +0000 (19:57 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 6 Nov 2008 17:57:21 +0000 (19:57 +0200)
Added a new configuration option, wpa_ptk_rekey, that can be used to
enforce frequent PTK rekeying, e.g., to mitigate some attacks against TKIP
deficiencies. This can be set either by the Authenticator (to initiate
periodic 4-way handshake to rekey PTK) or by the Supplicant (to request
Authenticator to rekey PTK).

With both wpa_ptk_rekey and wpa_group_rekey (in hostapd) set to 600, TKIP
keys will not be used for more than 10 minutes which may make some attacks
against TKIP more difficult to implement.

15 files changed:
hostapd/ChangeLog
hostapd/config.c
hostapd/config.h
hostapd/hostapd.c
hostapd/hostapd.conf
hostapd/wpa.c
hostapd/wpa.h
src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_i.h
wpa_supplicant/ChangeLog
wpa_supplicant/config.c
wpa_supplicant/config_ssid.h
wpa_supplicant/wpa_supplicant.conf
wpa_supplicant/wpas_glue.c

index a8e7f4eb41687997deb34e79e5840ff40a309d8c..b2cfb5bfe91e65ba38f0774e2e798171d8e8999b 100644 (file)
@@ -1,5 +1,10 @@
 ChangeLog for hostapd
 
+????-??-?? - v0.6.6
+       * added a new configuration option, wpa_ptk_rekey, that can be used to
+         enforce frequent PTK rekeying, e.g., to mitigate some attacks against
+         TKIP deficiencies
+
 2008-11-01 - v0.6.5
        * added support for SHA-256 as X.509 certificate digest when using the
          internal X.509/TLSv1 implementation
index 7fceacbb8238c681b1330587d7ab2b0883f79824..d10d64f280dfe9e88d4a7b64220bd3948a833e86 100644 (file)
@@ -1697,6 +1697,8 @@ struct hostapd_config * hostapd_config_read(const char *fname)
                        bss->wpa_strict_rekey = atoi(pos);
                } else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) {
                        bss->wpa_gmk_rekey = atoi(pos);
+               } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
+                       bss->wpa_ptk_rekey = atoi(pos);
                } else if (os_strcmp(buf, "wpa_passphrase") == 0) {
                        int len = os_strlen(pos);
                        if (len < 8 || len > 63) {
index 5c7d04068c42aa7d8fd1ea694f34783036d43dca..212e09967ddf0b4f49a2aeba3454b99f129fa177 100644 (file)
@@ -223,6 +223,7 @@ struct hostapd_bss_config {
        int wpa_group_rekey;
        int wpa_strict_rekey;
        int wpa_gmk_rekey;
+       int wpa_ptk_rekey;
        int rsn_pairwise;
        int rsn_preauth;
        char *rsn_preauth_interfaces;
index e80446a7be0fdb2fb8634cb8db2484932fc2a0a2..889f81e12fb47a1175ba8bd38fb7c9de8ea00658 100644 (file)
@@ -293,6 +293,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
        wconf->wpa_group_rekey = conf->wpa_group_rekey;
        wconf->wpa_strict_rekey = conf->wpa_strict_rekey;
        wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey;
+       wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey;
        wconf->rsn_pairwise = conf->rsn_pairwise;
        wconf->rsn_preauth = conf->rsn_preauth;
        wconf->eapol_version = conf->eapol_version;
index 898a3a3bc2ccc8836d98718c6b091cf9891281df..599d7f1a26ea87244f8389ea274efe0b17c75302 100644 (file)
@@ -710,6 +710,10 @@ own_ip_addr=127.0.0.1
 # (in seconds).
 #wpa_gmk_rekey=86400
 
+# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of
+# PTK to mitigate some attacks against TKIP deficiencies.
+#wpa_ptk_rekey=600
+
 # Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up
 # roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN
 # authentication and key handshake before actually associating with a new AP.
index c7bcac82a40a1930f67a7a9e108b9eb3bbee3b51..cc01f0282956f77f37c9acaeddea6026c94c356c 100644 (file)
@@ -43,6 +43,7 @@ static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len);
 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);
 
 /* Default timeouts are 100 ms, but this seems to be a bit too fast for most
  * WPA Supplicants, so use a bit longer timeout. */
@@ -260,6 +261,17 @@ static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
 }
 
 
+static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
+{
+       struct wpa_authenticator *wpa_auth = eloop_ctx;
+       struct wpa_state_machine *sm = timeout_ctx;
+
+       wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
+       wpa_request_new_ptk(sm);
+       wpa_sm_step(sm);
+}
+
+
 static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx)
 {
        if (sm->pmksa == ctx)
@@ -528,6 +540,7 @@ void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
 
        eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
        eloop_cancel_timeout(wpa_sm_call_step, sm, NULL);
+       eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
        if (sm->in_step_loop) {
                /* Must not free state machine while wpa_sm_step() is running.
                 * Freeing will be completed in the end of wpa_sm_step(). */
@@ -1086,6 +1099,7 @@ void wpa_remove_ptk(struct wpa_state_machine *sm)
        os_memset(&sm->PTK, 0, sizeof(sm->PTK));
        wpa_auth_set_key(sm->wpa_auth, 0, "none", sm->addr, 0, (u8 *) "", 0);
        sm->pairwise_set = FALSE;
+       eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
 }
 
 
@@ -1553,6 +1567,13 @@ SM_STATE(WPA_PTK, PTKINITDONE)
                /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
                sm->pairwise_set = TRUE;
 
+               if (sm->wpa_auth->conf.wpa_ptk_rekey) {
+                       eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
+                       eloop_register_timeout(sm->wpa_auth->conf.
+                                              wpa_ptk_rekey, 0, wpa_rekey_ptk,
+                                              sm->wpa_auth, sm);
+               }
+
                if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
                        wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
                                           WPA_EAPOL_authorized, 1);
index 567a8bfed93616be6007afa83c0a15845f5bbcc6..153106e1fc85ab29f9ce7105bac669cbc435d449 100644 (file)
@@ -136,6 +136,7 @@ struct wpa_auth_config {
        int wpa_group_rekey;
        int wpa_strict_rekey;
        int wpa_gmk_rekey;
+       int wpa_ptk_rekey;
        int rsn_pairwise;
        int rsn_preauth;
        int eapol_version;
index 5ec1dabdc3a2b93fde2661778d0a30f96a47c8ee..1da54f296ec0c7e90341049c8ef98e0a1752c19d 100644 (file)
@@ -133,7 +133,6 @@ void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck,
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
  * @error: Indicate whether this is an Michael MIC error report
  * @pairwise: 1 = error report for pairwise packet, 0 = for group packet
- * Returns: Pointer to the current network structure or %NULL on failure
  *
  * Send an EAPOL-Key Request to the current authenticator. This function is
  * used to request rekeying and it is usually called when a local Michael MIC
@@ -489,6 +488,14 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
 }
 
 
+static void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
+{
+       struct wpa_sm *sm = eloop_ctx;
+       wpa_printf(MSG_DEBUG, "WPA: Request PTK rekeying");
+       wpa_sm_key_request(sm, 0, 1);
+}
+
+
 static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
                                      const struct wpa_eapol_key *key)
 {
@@ -533,6 +540,13 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
                           "driver.");
                return -1;
        }
+
+       if (sm->wpa_ptk_rekey) {
+               eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
+               eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk,
+                                      sm, NULL);
+       }
+
        return 0;
 }
 
@@ -1849,6 +1863,7 @@ void wpa_sm_deinit(struct wpa_sm *sm)
                return;
        pmksa_cache_deinit(sm->pmksa);
        eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL);
+       eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
        os_free(sm->assoc_wpa_ie);
        os_free(sm->ap_wpa_ie);
        os_free(sm->ap_rsn_ie);
@@ -2018,6 +2033,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
                        sm->ssid_len = config->ssid_len;
                } else
                        sm->ssid_len = 0;
+               sm->wpa_ptk_rekey = config->wpa_ptk_rekey;
        } else {
                sm->network_ctx = NULL;
                sm->peerkey_enabled = 0;
@@ -2026,6 +2042,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
                sm->eap_workaround = 0;
                sm->eap_conf_ctx = NULL;
                sm->ssid_len = 0;
+               sm->wpa_ptk_rekey = 0;
        }
        if (config == NULL || config->network_ctx != sm->network_ctx)
                pmksa_cache_notify_reconfig(sm->pmksa);
index 650e75f2c68bf0f1d3be496454be318fc677c585..bdf778544f416daf1f2d70630b56637b5d5a13c1 100644 (file)
@@ -85,6 +85,7 @@ struct rsn_supp_config {
        void *eap_conf_ctx;
        const u8 *ssid;
        size_t ssid_len;
+       int wpa_ptk_rekey;
 };
 
 #ifndef CONFIG_NO_WPA
index 150515541a8188a05f722a0a30ee5fc80c830000..95348da8a996053d5692901f155c83e15f1acb37 100644 (file)
@@ -60,6 +60,7 @@ struct wpa_sm {
        void *eap_conf_ctx;
        u8 ssid[32];
        size_t ssid_len;
+       int wpa_ptk_rekey;
 
        u8 own_addr[ETH_ALEN];
        const char *ifname;
index 251e95a0638d246a8d07a9a59ad25956fba77562..4f213fa236e6d586ab4bb380056b9bb34f52518d 100644 (file)
@@ -5,6 +5,9 @@ ChangeLog for wpa_supplicant
          (can be used to simulate test SIM/USIM card with a known private key;
          enable with CONFIG_SIM_SIMULATOR=y/CONFIG_USIM_SIMULATOR=y in .config
          and password="Ki:OPc"/password="Ki:OPc:SQN" in network configuration)
+       * added a new network configuration option, wpa_ptk_rekey, that can be
+         used to enforce frequent PTK rekeying, e.g., to mitigate some attacks
+         against TKIP deficiencies
 
 2008-11-01 - v0.6.5
        * added support for SHA-256 as X.509 certificate digest when using the
index fc64be1f2eb6ca54dd722e984737c66db83fa4cf..70b02c4ef37c62243b631905b83c943185f645fe 100644 (file)
@@ -1357,7 +1357,8 @@ static const struct parse_data ssid_fields[] = {
 #endif /* CONFIG_IEEE80211W */
        { INT_RANGE(peerkey, 0, 1) },
        { INT_RANGE(mixed_cell, 0, 1) },
-       { INT_RANGE(frequency, 0, 10000) }
+       { INT_RANGE(frequency, 0, 10000) },
+       { INT(wpa_ptk_rekey) }
 };
 
 #undef OFFSET
index 5e57bc162b02df789a03da57a01466788263d475..5510639c147cd7552073806538fe35ea25ede7e7 100644 (file)
@@ -334,6 +334,14 @@ struct wpa_ssid {
         * will be used instead of this configured value.
         */
        int frequency;
+
+       /**
+        * wpa_ptk_rekey - Maximum lifetime for PTK in seconds
+        *
+        * This value can be used to enforce rekeying of PTK to mitigate some
+        * attacks against TKIP deficiencies.
+        */
+       int wpa_ptk_rekey;
 };
 
 #endif /* CONFIG_SSID_H */
index b639d39f44b22318b09bcc7e12212d53bb40834e..44dc3a17a143176d821a4ee9cc6fd33aa6b9645a 100644 (file)
@@ -276,6 +276,9 @@ fast_reauth=1
 # 1 = enabled
 #peerkey=1
 #
+# wpa_ptk_rekey: Maximum lifetime for PTK in seconds. This can be used to
+# enforce rekeying of PTK to mitigate some attacks against TKIP deficiencies.
+#
 # Following fields are only used with internal EAP implementation.
 # eap: space-separated list of accepted EAP methods
 #      MD5 = EAP-MD5 (unsecure and does not generate keying material ->
@@ -475,6 +478,17 @@ network={
        priority=2
 }
 
+# WPA-Personal(PSK) with TKIP and enforcement for frequent PTK rekeying
+network={
+       ssid="example"
+       proto=WPA
+       key_mgmt=WPA-PSK
+       pairwise=TKIP
+       group=TKIP
+       psk="not so secure passphrase"
+       wpa_ptk_rekey=600
+}
+
 # Only WPA-EAP is used. Both CCMP and TKIP is accepted. An AP that used WEP104
 # or WEP40 as the group cipher will not be accepted.
 network={
index f0c1cdabc4d8865cad5c0542d62de41e22d39c89..d5e31ebb0d3d77ad53dc9ba1735afeeeb07e4800 100644 (file)
@@ -626,6 +626,7 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
 #endif /* IEEE8021X_EAPOL */
                conf.ssid = ssid->ssid;
                conf.ssid_len = ssid->ssid_len;
+               conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey;
        }
        wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
 }