diff mbox series

[v9,12/16] tests: Extended Key ID tests

Message ID 20200104221015.90469-13-alexander@wetzel-home.de
State Changes Requested
Headers show
Series Seamless PTK rekeys | expand

Commit Message

Alexander Wetzel Jan. 4, 2020, 10:10 p.m. UTC
Add the needed infrastructure for the Extended Key ID tests, update
tests overriding RSN Capabilities to work with and without Extended Key
ID support and add additional interoperability tests for Extended Key
ID.

When supported by the platform (hwsim) all tests will use Extended Key
ID by default while still being able to run all tests not directly linked
to Extended Key ID.

Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
 tests/hwsim/hostapd.py       |  14 +++-
 tests/hwsim/test_ap_eap.py   |  24 ++++++-
 tests/hwsim/test_ap_psk.py   | 132 ++++++++++++++++++++++++++++++++---
 tests/hwsim/test_ocv.py      |  13 +++-
 tests/hwsim/test_rrm.py      |   7 +-
 tests/hwsim/wpasupplicant.py |   2 +-
 wlantest/bss.c               |   4 +-
 wlantest/rx_data.c           |   6 +-
 wlantest/rx_eapol.c          |   4 ++
 9 files changed, 183 insertions(+), 23 deletions(-)
diff mbox series

Patch

diff --git a/tests/hwsim/hostapd.py b/tests/hwsim/hostapd.py
index c618a28e0..0823ea56c 100644
--- a/tests/hwsim/hostapd.py
+++ b/tests/hwsim/hostapd.py
@@ -151,6 +151,7 @@  class Hostapd:
         self.mon.attach()
         self.bssid = None
         self.bssidx = bssidx
+        self.extKeyID = False
 
     def cmd_execute(self, cmd_array, shell=False):
         if self.hostname is None:
@@ -548,7 +549,7 @@  def add_ap(apdev, params, wait_enabled=True, no_enable=False, timeout=30,
             raise Exception("Could not ping hostapd")
         hapd.set_defaults()
         fields = ["ssid", "wpa_passphrase", "nas_identifier", "wpa_key_mgmt",
-                  "wpa", "wpa_deny_ptk0_rekey",
+                  "wpa", "wpa_deny_ptk0_rekey", "wpa_extended_key_id",
                   "wpa_pairwise", "rsn_pairwise", "auth_server_addr",
                   "acct_server_addr", "osu_server_uri"]
         for field in fields:
@@ -566,7 +567,12 @@  def add_ap(apdev, params, wait_enabled=True, no_enable=False, timeout=30,
             return hapd
         hapd.enable()
         if wait_enabled:
-            ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=timeout)
+            ev = hapd.wait_event(["Extended Key ID",
+                                  "AP-ENABLED", "AP-DISABLED"], timeout=timeout)
+            if "Extended Key ID" in ev:
+                if "Enable" in ev:
+                    hapd.extKeyID = True
+                ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=timeout)
             if ev is None:
                 raise Exception("AP startup timed out")
             if "AP-ENABLED" not in ev:
@@ -631,7 +637,7 @@  def terminate(apdev):
     hapd_global = HostapdGlobal(apdev)
     hapd_global.terminate()
 
-def wpa2_params(ssid=None, passphrase=None):
+def wpa2_params(ssid=None, passphrase=None, wpa_extended_key_id=None):
     params = {"wpa": "2",
               "wpa_deny_ptk0_rekey": "0",
               "wpa_key_mgmt": "WPA-PSK",
@@ -640,6 +646,8 @@  def wpa2_params(ssid=None, passphrase=None):
         params["ssid"] = ssid
     if passphrase:
         params["wpa_passphrase"] = passphrase
+    if wpa_extended_key_id:
+        params["wpa_extended_key_id"] = wpa_extended_key_id
     return params
 
 def wpa_params(ssid=None, passphrase=None):
diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py
index 28a1b11e4..13be61b7f 100644
--- a/tests/hwsim/test_ap_eap.py
+++ b/tests/hwsim/test_ap_eap.py
@@ -5131,6 +5131,7 @@  def test_ap_wpa2_eap_reauth_ptk_rekey_blocked_ap(dev, apdev):
     params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
     params['eap_reauth_period'] = '2'
     params['wpa_deny_ptk0_rekey'] = '2'
+    params['wpa_extended_key_id'] = '0'
     hapd = hostapd.add_ap(apdev[0], params)
     eap_connect(dev[0], hapd, "PAX", "pax.user@example.com",
                 password_hex="0123456789abcdef0123456789abcdef")
@@ -5153,7 +5154,8 @@  def test_ap_wpa2_eap_reauth_ptk_rekey_blocked_sta(dev, apdev):
     hapd = hostapd.add_ap(apdev[0], params)
     eap_connect(dev[0], hapd, "PAX", "pax.user@example.com",
                 password_hex="0123456789abcdef0123456789abcdef",
-                wpa_deny_ptk0_rekey="2")
+                wpa_deny_ptk0_rekey="2", wpa_extended_key_id="0")
+
     logger.info("Wait for disconnect due to reauth")
     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
                             "CTRL-EVENT-DISCONNECTED"], timeout=10)
@@ -6685,7 +6687,7 @@  def test_eap_tls_sha384(dev, apdev, params):
 def test_ap_wpa2_eap_assoc_rsn(dev, apdev):
     """WPA2-Enterprise AP and association request RSN IE differences"""
     params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
-    hostapd.add_ap(apdev[0], params)
+    hapd = hostapd.add_ap(apdev[0], params)
 
     params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap-11w")
     params["ieee80211w"] = "2"
@@ -6705,6 +6707,17 @@  def test_ap_wpa2_eap_assoc_rsn(dev, apdev):
              ("RSN IE without AKM", "300c0100000fac040100000fac04"),
              ("RSN IE without pairwise", "30060100000fac04"),
              ("RSN IE without group", "30020100")]
+
+    if hapd.extKeyID:
+        tests += [("Normal wpa_supplicant assoc req RSN IE with Extended Key ID",
+                   "30140100000fac040100000fac040100000fac010020"),
+                  ("Extra PMKIDCount field in RSN IE with Extended Key ID",
+                   "30160100000fac040100000fac040100000fac0100200000"),
+                  ("Extra Group Management Cipher Suite in RSN IE with Extended Key ID",
+                   "301a0100000fac040100000fac040100000fac0100200000000fac06"),
+                  ("Extra undefined extension field in RSN IE with Extended Key ID",
+                   "301c0100000fac040100000fac040100000fac0100200000000fac061122")]
+
     for title, ie in tests:
         logger.info(title)
         set_test_assoc_ie(dev[0], ie)
@@ -6719,6 +6732,13 @@  def test_ap_wpa2_eap_assoc_rsn(dev, apdev):
               "30140100000fac040100000fac040100000fac01cc00"),
              ("Group management cipher included in assoc req RSN IE",
               "301a0100000fac040100000fac040100000fac01cc000000000fac06")]
+
+    if hapd.extKeyID:
+        tests += [("Normal wpa_supplicant assoc req RSN IE with Extended Key ID",
+                   "30140100000fac040100000fac040100000fac01cc20"),
+                  ("Group management cipher included in assoc req RSN IE with Extended Key ID",
+                   "301a0100000fac040100000fac040100000fac01cc200000000fac06")]
+
     for title, ie in tests:
         logger.info(title)
         set_test_assoc_ie(dev[0], ie)
diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py
index 9511cbbfa..482c95afd 100644
--- a/tests/hwsim/test_ap_psk.py
+++ b/tests/hwsim/test_ap_psk.py
@@ -205,12 +205,14 @@  def _test_ap_wpa2_psk_mem(dev, apdev):
 
 @remote_compatible
 def test_ap_wpa2_ptk_rekey(dev, apdev):
-    """WPA2-PSK AP and PTK rekey enforced by station"""
+    """WPA2-PSK AP and PTK rekey enforced by station without Extended Key ID"""
     ssid = "test-wpa2-psk"
     passphrase = 'qwertyuiop'
-    params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
+    params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase,
+                                 wpa_extended_key_id="0")
     hapd = hostapd.add_ap(apdev[0], params)
-    dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412")
+    dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412",
+                   wpa_extended_key_id="0")
     ev = dev[0].wait_event(["WPA: Key negotiation completed",
                             "CTRL-EVENT-DISCONNECTED"])
     if ev is None:
@@ -225,6 +227,7 @@  def test_ap_wpa2_ptk_rekey_blocked_ap(dev, apdev):
     passphrase = 'qwertyuiop'
     params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
     params['wpa_deny_ptk0_rekey'] = "2"
+    params['wpa_extended_key_id'] = "0"
     hapd = hostapd.add_ap(apdev[0], params)
     dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412")
     ev = dev[0].wait_event(["WPA: Key negotiation completed",
@@ -244,7 +247,7 @@  def test_ap_wpa2_ptk_rekey_blocked_sta(dev, apdev):
     params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
     hapd = hostapd.add_ap(apdev[0], params)
     dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412",
-                   wpa_deny_ptk0_rekey="2")
+                   wpa_deny_ptk0_rekey="2", wpa_extended_key_id="0")
     ev = dev[0].wait_event(["WPA: Key negotiation completed",
                             "CTRL-EVENT-DISCONNECTED"])
     if ev is None:
@@ -1391,10 +1394,15 @@  def eapol_test(apdev, dev, wpa2=True, ieee80211w=0):
                 ieee80211w=str(ieee80211w))
     addr = dev.p2p_interface_addr()
     if wpa2:
-        if ieee80211w == 2:
-            rsne = binascii.unhexlify('30140100000fac040100000fac040100000fac02cc00')
+        if hapd.extKeyID and ieee80211w == 2:
+            cap = "cc20"
+        elif hapd.extKeyID:
+            cap = "0020"
+        elif ieee80211w == 2:
+            cap = "cc00"
         else:
-            rsne = binascii.unhexlify('30140100000fac040100000fac040100000fac020000')
+            cap = "0000"
+        rsne = binascii.unhexlify('30140100000fac040100000fac040100000fac02'+cap)
     else:
         rsne = binascii.unhexlify('dd160050f20101000050f20201000050f20201000050f202')
     snonce = binascii.unhexlify('1111111111111111111111111111111111111111111111111111111111111111')
@@ -2964,6 +2972,11 @@  def test_ap_wpa2_psk_assoc_rsn(dev, apdev):
               "30140100000fac040100000fac040100000fac020000"),
              ("RSN IE without RSN Capabilities",
               "30120100000fac040100000fac040100000fac02")]
+
+    if hapd.extKeyID:
+        tests += [("Normal wpa_supplicant assoc req RSN IE with Extended Key ID",
+                   "30140100000fac040100000fac040100000fac020020")]
+
     for title, ie in tests:
         logger.info(title)
         set_test_assoc_ie(dev[0], ie)
@@ -3007,9 +3020,13 @@  def test_ap_wpa2_psk_ft_workaround(dev, apdev):
     params['r1_key_holder'] = "000102030405"
     hapd = hostapd.add_ap(apdev[0], params)
 
+    if hapd.extKeyID:
+        ie = "30180100000fac040100000fac040200000fac02000fac040020"
+    else:
+        ie = "30180100000fac040100000fac040200000fac02000fac040000"
+
     # Include both WPA-PSK and FT-PSK AKMs in Association Request frame
-    set_test_assoc_ie(dev[0],
-                      "30180100000fac040100000fac040200000fac02000fac040000")
+    set_test_assoc_ie(dev[0], ie)
     dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
     dev[0].request("REMOVE_NETWORK all")
     dev[0].wait_disconnected()
@@ -3026,6 +3043,14 @@  def test_ap_wpa2_psk_assoc_rsn_pmkid(dev, apdev):
     dev[0].request("REMOVE_NETWORK all")
     dev[0].wait_disconnected()
 
+    if not hapd.extKeyID:
+        return
+
+    set_test_assoc_ie(dev[0], "30260100000fac040100000fac040100000fac0200200100" + 16*'00')
+    dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
+    dev[0].request("REMOVE_NETWORK all")
+    dev[0].wait_disconnected()
+
 def test_ap_wpa_psk_rsn_pairwise(dev, apdev):
     """WPA-PSK AP and only rsn_pairwise set"""
     params = {"ssid": "wpapsk", "wpa": "1", "wpa_key_mgmt": "WPA-PSK",
@@ -3321,3 +3346,92 @@  def test_ap_wpa2_psk_inject_assoc(dev, apdev, params):
                      wait=False)
     if len(res) > 0:
         raise Exception("Unexpected frame from unauthorized STA seen")
+
+def test_ap_wpa2_ptk_extended_key_id(dev, apdev):
+    """Extended Key ID WPA2-PSK AP and PTK rekey enforced by station"""
+    ssid = "test-wpa2-psk"
+    passphrase = 'qwertyuiop'
+    params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
+    hapd = hostapd.add_ap(apdev[0], params)
+    if not hapd.extKeyID:
+        raise Exception("Extended Key ID support missing in hwsim")
+
+    dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412")
+    ev = dev[0].wait_event(["WPA: Key negotiation completed"])
+    if ev is None:
+        raise Exception("PTK rekey timed out (STA with Extended Key ID)")
+    elif "Extended_Key_ID" not in ev:
+        raise Exception("Extended Key ID not used")
+    hwsim_utils.test_connectivity(dev[0], hapd)
+    ev = dev[0].wait_event(["WPA: Key negotiation completed"])
+    if ev is None:
+        raise Exception("PTK rekey timed out 2 (STA with Extended Key ID)")
+    elif "Extended_Key_ID" not in ev:
+        raise Exception("Extended Key ID not used")
+    hwsim_utils.test_connectivity(dev[0], hapd)
+    dev[0].reset()
+
+def test_ap_wpa2_ptk_extended_key_id_compat_ap(dev, apdev):
+    """Extended Key ID WPA2-PSK AP and station not supporting Extended Key ID"""
+    ssid = "test-wpa2-psk"
+    passphrase = 'qwertyuiop'
+    params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
+    hapd = hostapd.add_ap(apdev[0], params)
+    if not hapd.extKeyID:
+        raise HwsimSkip("Extended Key ID support missing in hwsim")
+
+    dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412",
+                   wpa_extended_key_id="0")
+    ev = dev[0].wait_event(["WPA: Key negotiation completed"])
+    if ev is None:
+        raise Exception("PTK rekey timed out (STA without Extended Key ID)")
+    elif "Extended_Key_ID" in ev:
+        raise Exception("Invalid Extended Key ID usage")
+    hwsim_utils.test_connectivity(dev[0], hapd)
+    dev[0].reset()
+
+def test_ap_wpa2_ptk_extended_key_id_compat_sta(dev, apdev):
+    """WPA2-PSK AP not supporting Extended Key ID and station supporting it"""
+    ssid = "test-wpa2-psk"
+    passphrase = 'qwertyuiop'
+    params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase,
+                                 wpa_extended_key_id="0")
+    hapd = hostapd.add_ap(apdev[0], params)
+    dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412")
+    ev = dev[0].wait_event(["WPA: Key negotiation completed"])
+    if ev is None:
+        raise Exception("PTK rekey timed out (AP without Extended Key ID")
+    elif "Extended_Key_ID" in ev:
+        raise Exception("Extended Key ID used when AP not supporting it")
+    hwsim_utils.test_connectivity(dev[0], hapd)
+    dev[0].reset()
+
+def test_ap_wpa2_ptk_extended_key_id_tkip(dev, apdev):
+    """Extended Key ID with TKIP only AP"""
+    ssid = "test-wpa2-psk"
+    passphrase = 'qwertyuiop'
+    params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
+    params["rsn_pairwise"] = "TKIP"
+    hapd = hostapd.add_ap(apdev[0], params)
+    if hapd.extKeyID:
+        raise Exception("Extended Key ID support not disabled for TKIP only AP")
+
+def test_ap_wpa2_ptk_extended_key_id_tkip_sta(dev, apdev):
+    """Extended Key ID WPA2-PSK AP and station using WPA2 with TKIP only"""
+    ssid = "test-wpa2-psk"
+    passphrase = 'qwertyuiop'
+    params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
+    params["rsn_pairwise"] = "TKIP CCMP"
+    hapd = hostapd.add_ap(apdev[0], params)
+    if not hapd.extKeyID:
+        raise HwsimSkip("Extended Key ID support missing in hwsim")
+
+    dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", pairwise="TKIP",
+                   scan_freq="2412")
+    ev = dev[0].wait_event(["WPA: Key negotiation completed"])
+    if ev is None:
+        raise Exception("PTK rekey timed out (STA with Extended Key ID using TKIP)")
+    elif "Extended_Key_ID" in ev:
+        raise Exception("Invalid Extended Key ID usage with TKIP")
+    hwsim_utils.test_connectivity(dev[0], hapd)
+    dev[0].reset()
diff --git a/tests/hwsim/test_ocv.py b/tests/hwsim/test_ocv.py
index df84e7124..0b90cadf5 100644
--- a/tests/hwsim/test_ocv.py
+++ b/tests/hwsim/test_ocv.py
@@ -380,10 +380,17 @@  class APConnection:
         self.bssid = apdev['bssid']
         pmk = binascii.unhexlify("c2c6c255af836bed1b3f2f1ded98e052f5ad618bb554e2836757b55854a0eab7")
 
-        if sta_ocv != "0":
-            self.rsne = binascii.unhexlify("301a0100000fac040100000fac040100000fac0280400000000fac06")
+        if self.hapd.extKeyID:
+            if sta_ocv != "0":
+                cap = "8060"
+            else:
+                cap = "8020"
         else:
-            self.rsne = binascii.unhexlify("301a0100000fac040100000fac040100000fac0280000000000fac06")
+            if sta_ocv != "0":
+                cap = "8040"
+            else:
+                cap = "8000"
+        self.rsne = binascii.unhexlify("301a0100000fac040100000fac040100000fac02"+cap+"0000000fac06")
         self.snonce = binascii.unhexlify('1111111111111111111111111111111111111111111111111111111111111111')
 
         dev.connect(self.ssid, raw_psk=self.psk, scan_freq=freq, ocv=sta_ocv,
diff --git a/tests/hwsim/test_rrm.py b/tests/hwsim/test_rrm.py
index dde98932b..7336f82a1 100644
--- a/tests/hwsim/test_rrm.py
+++ b/tests/hwsim/test_rrm.py
@@ -1233,6 +1233,11 @@  def test_rrm_beacon_req_table_rsne(dev, apdev):
     params["rrm_beacon_report"] = "1"
     hapd = hostapd.add_ap(apdev[0], params)
 
+    if hapd.extKeyID:
+        cap = "0c20"
+    else:
+        cap = "0c00"
+
     dev[0].connect("rrm-rsn", psk="12345678", scan_freq="2412")
     addr = dev[0].own_addr()
 
@@ -1247,7 +1252,7 @@  def test_rrm_beacon_req_table_rsne(dev, apdev):
         raise Exception("Reported Frame Body subelement missing")
     if len(report.frame_body) != 12 + 22:
         raise Exception("Unexpected Reported Frame Body subelement length with Reporting Detail 1 and requested element RSNE")
-    if binascii.unhexlify("30140100000fac040100000fac040100000fac020c00") not in report.frame_body:
+    if binascii.unhexlify("30140100000fac040100000fac040100000fac02"+cap) not in report.frame_body:
         raise Exception("Full RSNE not found")
 
 def test_rrm_beacon_req_table_vht(dev, apdev):
diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py
index 08fa55cd1..530c9d660 100644
--- a/tests/hwsim/wpasupplicant.py
+++ b/tests/hwsim/wpasupplicant.py
@@ -1094,7 +1094,7 @@  class WpaSupplicant:
                       "group_mgmt", "owe_group",
                       "roaming_consortium_selection", "ocv",
                       "multi_ap_backhaul_sta", "rx_stbc", "tx_stbc",
-                      "ft_eap_pmksa_caching"]
+                      "ft_eap_pmksa_caching", "wpa_extended_key_id"]
         for field in not_quoted:
             if field in kwargs and kwargs[field]:
                 self.set_network(id, field, kwargs[field])
diff --git a/wlantest/bss.c b/wlantest/bss.c
index 298a902c7..08181dc8c 100644
--- a/wlantest/bss.c
+++ b/wlantest/bss.c
@@ -334,7 +334,9 @@  void bss_update(struct wlantest *wt, struct wlantest_bss *bss,
 		   bss->rsn_capab & WPA_CAPABILITY_MFPC ? "MFPC " : "",
 		   bss->rsn_capab & WPA_CAPABILITY_PEERKEY_ENABLED ?
 		   "PEERKEY " : "",
-		   bss->rsn_capab & WPA_CAPABILITY_OCVC ? "OCVC " : "");
+		   bss->rsn_capab & WPA_CAPABILITY_OCVC ? "OCVC " : "",
+		   bss->rsn_capab & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST ?
+		   "Extended Key ID" : "");
 }
 
 
diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c
index d6c7a54c7..17ff79aa5 100644
--- a/wlantest/rx_data.c
+++ b/wlantest/rx_data.c
@@ -407,9 +407,9 @@  static void rx_data_bss_prot(struct wlantest *wt,
 	}
 
 	keyid = data[3] >> 6;
-	if (keyid != 0) {
-		add_note(wt, MSG_INFO, "Unexpected non-zero KeyID %d in "
-			 "individually addressed Data frame from " MACSTR,
+	if (keyid != 0 && keyid != 1) {
+		add_note(wt, MSG_INFO, "Unexpected KeyID %d in individually "
+			 "addressed Data frame from " MACSTR,
 			 keyid, MAC2STR(hdr->addr2));
 	}
 
diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c
index e18449542..de1770b71 100644
--- a/wlantest/rx_eapol.c
+++ b/wlantest/rx_eapol.c
@@ -460,6 +460,10 @@  static void learn_kde_keys(struct wlantest *wt, struct wlantest_bss *bss,
 			    ie.rsn_ie, ie.rsn_ie_len);
 	}
 
+	if (ie.key_id) {
+		add_note(wt, MSG_DEBUG, "KeyID %u", ie.key_id[0]);
+	}
+
 	if (ie.gtk) {
 		wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - GTK KDE",
 			    ie.gtk, ie.gtk_len);