From ca27ee099818643b3e88864d5c46b4b035328df1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 12 Dec 2015 18:16:19 +0200 Subject: [PATCH] tests: External server certificate chain validation This tests tls_ext_cert_check=1 behavior with EAP-TLS, EAP-TTLS, EAP-PEAP, and EAP-FAST. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_eap.py | 136 +++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py index 89a704bb9..54054c7d8 100644 --- a/tests/hwsim/test_ap_eap.py +++ b/tests/hwsim/test_ap_eap.py @@ -21,6 +21,12 @@ from utils import HwsimSkip, alloc_fail, fail_test, skip_with_fips, wait_fail_tr from wpasupplicant import WpaSupplicant from test_ap_psk import check_mib, find_wpas_process, read_process_memory, verify_not_present, get_key_locations, set_test_assoc_ie +try: + import OpenSSL + openssl_imported = True +except ImportError: + openssl_imported = False + def check_hlr_auc_gw_support(): if not os.path.exists("/tmp/hlr_auc_gw.sock"): raise HwsimSkip("No hlr_auc_gw available") @@ -60,6 +66,11 @@ def check_cert_probe_support(dev): if not tls.startswith("OpenSSL") and not tls.startswith("internal"): raise HwsimSkip("Certificate probing not supported with this TLS library: " + tls) +def check_ext_cert_check_support(dev): + tls = dev.request("GET tls_library") + if not tls.startswith("OpenSSL"): + raise HwsimSkip("ext_cert_check not supported with this TLS library: " + tls) + def check_ocsp_support(dev): tls = dev.request("GET tls_library") if tls.startswith("internal"): @@ -4374,3 +4385,128 @@ def test_ap_wpa2_eap_assoc_rsn(dev, apdev): raise Exception("Unexpected status code: " + ev) dev[0].request("REMOVE_NETWORK all") dev[0].dump_monitor() + +def test_eap_tls_ext_cert_check(dev, apdev): + """EAP-TLS and external server certification validation""" + # With internal server certificate chain validation + id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS", + identity="tls user", + ca_cert="auth_serv/ca.pem", + client_cert="auth_serv/user.pem", + private_key="auth_serv/user.key", + phase1="tls_ext_cert_check=1", scan_freq="2412", + only_add_network=True) + run_ext_cert_check(dev, apdev, id) + +def test_eap_ttls_ext_cert_check(dev, apdev): + """EAP-TTLS and external server certification validation""" + # Without internal server certificate chain validation + id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS", + identity="pap user", anonymous_identity="ttls", + password="password", phase2="auth=PAP", + phase1="tls_ext_cert_check=1", scan_freq="2412", + only_add_network=True) + run_ext_cert_check(dev, apdev, id) + +def test_eap_peap_ext_cert_check(dev, apdev): + """EAP-PEAP and external server certification validation""" + # With internal server certificate chain validation + id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="PEAP", + identity="user", anonymous_identity="peap", + ca_cert="auth_serv/ca.pem", + password="password", phase2="auth=MSCHAPV2", + phase1="tls_ext_cert_check=1", scan_freq="2412", + only_add_network=True) + run_ext_cert_check(dev, apdev, id) + +def test_eap_fast_ext_cert_check(dev, apdev): + """EAP-FAST and external server certification validation""" + check_eap_capa(dev[0], "FAST") + # With internal server certificate chain validation + dev[0].request("SET blob fast_pac_auth_ext ") + id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="FAST", + identity="user", anonymous_identity="FAST", + ca_cert="auth_serv/ca.pem", + password="password", phase2="auth=GTC", + phase1="tls_ext_cert_check=1 fast_provisioning=2", + pac_file="blob://fast_pac_auth_ext", + scan_freq="2412", + only_add_network=True) + run_ext_cert_check(dev, apdev, id) + +def run_ext_cert_check(dev, apdev, net_id): + check_ext_cert_check_support(dev[0]) + if not openssl_imported: + raise HwsimSkip("OpenSSL python method not available") + + params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") + hapd = hostapd.add_ap(apdev[0]['ifname'], params) + + dev[0].select_network(net_id) + certs = {} + while True: + ev = dev[0].wait_event(["CTRL-EVENT-EAP-PEER-CERT", + "CTRL-REQ-EXT_CERT_CHECK", + "CTRL-EVENT-EAP-SUCCESS"], timeout=10) + if ev is None: + raise Exception("No peer server certificate event seen") + if "CTRL-EVENT-EAP-PEER-CERT" in ev: + depth = None + cert = None + vals = ev.split(' ') + for v in vals: + if v.startswith("depth="): + depth = int(v.split('=')[1]) + elif v.startswith("cert="): + cert = v.split('=')[1] + if depth is not None and cert: + certs[depth] = binascii.unhexlify(cert) + elif "CTRL-EVENT-EAP-SUCCESS" in ev: + raise Exception("Unexpected EAP-Success") + elif "CTRL-REQ-EXT_CERT_CHECK" in ev: + id = ev.split(':')[0].split('-')[-1] + break + if 0 not in certs: + raise Exception("Server certificate not received") + if 1 not in certs: + raise Exception("Server certificate issuer not received") + + cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1, + certs[0]) + cn = cert.get_subject().commonName + logger.info("Server certificate CN=" + cn) + + issuer = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1, + certs[1]) + icn = issuer.get_subject().commonName + logger.info("Issuer certificate CN=" + icn) + + if cn != "server.w1.fi": + raise Exception("Unexpected server certificate CN: " + cn) + if icn != "Root CA": + raise Exception("Unexpected server certificate issuer CN: " + icn) + + ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=0.1) + if ev: + raise Exception("Unexpected EAP-Success before external check result indication") + + dev[0].request("CTRL-RSP-EXT_CERT_CHECK-" + id + ":good") + dev[0].wait_connected() + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + if "FAIL" in dev[0].request("PMKSA_FLUSH"): + raise Exception("PMKSA_FLUSH failed") + dev[0].request("SET blob fast_pac_auth_ext ") + dev[0].request("RECONNECT") + + ev = dev[0].wait_event(["CTRL-REQ-EXT_CERT_CHECK"], timeout=10) + if ev is None: + raise Exception("No peer server certificate event seen (2)") + id = ev.split(':')[0].split('-')[-1] + dev[0].request("CTRL-RSP-EXT_CERT_CHECK-" + id + ":bad") + ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5) + if ev is None: + raise Exception("EAP-Failure not reported") + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected()