Replace None SecurityMode with SecurityMode.OPEN

Replace all use of None SecurityMode with SecurityMode.OPEN, which
better describes its functionality and decreases the risk of
accidentally making an open network.

Bug: b/285950835
Change-Id: I38d64e1cd36ec5060f25182b7afb21c10d1090e9
Reviewed-on: https://fuchsia-review.googlesource.com/c/antlion/+/885953
Fuchsia-Auto-Submit: Sam Balana <sbalana@google.com>
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
Reviewed-by: Karl Ward <karlward@google.com>
diff --git a/packages/antlion/controllers/ap_lib/hostapd_ap_preset.py b/packages/antlion/controllers/ap_lib/hostapd_ap_preset.py
index cf3aab6..3d40c14 100644
--- a/packages/antlion/controllers/ap_lib/hostapd_ap_preset.py
+++ b/packages/antlion/controllers/ap_lib/hostapd_ap_preset.py
@@ -44,9 +44,9 @@
 
 
 def create_ap_preset(
+    iface_wlan_2g: str,
+    iface_wlan_5g: str,
     profile_name: str = "whirlwind",
-    iface_wlan_2g: Optional[str] = None,
-    iface_wlan_5g: Optional[str] = None,
     channel: Optional[int] = None,
     mode: Optional[str] = None,
     frequency: Optional[int] = None,
@@ -99,6 +99,8 @@
 
     Returns: A hostapd_config object that can be used by the hostapd object.
     """
+    if security is None:
+        security = Security()
 
     # Verify interfaces
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
diff --git a/packages/antlion/controllers/ap_lib/hostapd_bss_settings.py b/packages/antlion/controllers/ap_lib/hostapd_bss_settings.py
index 24bb3fb..77260aa 100644
--- a/packages/antlion/controllers/ap_lib/hostapd_bss_settings.py
+++ b/packages/antlion/controllers/ap_lib/hostapd_bss_settings.py
@@ -35,14 +35,14 @@
         self,
         name: str,
         ssid: str,
+        security: Security,
         hidden: bool = False,
-        security: Optional[Security] = None,
         bssid: Optional[str] = None,
     ):
         self.name = name
         self.ssid = ssid
-        self.hidden = hidden
         self.security = security
+        self.hidden = hidden
         self.bssid = bssid
 
     def generate_dict(self) -> Dict[str, Union[str, int]]:
@@ -55,9 +55,8 @@
             settings["ssid"] = self.ssid
             settings["ignore_broadcast_ssid"] = 1 if self.hidden else 0
 
-        if self.security is not None:
-            security_settings = self.security.generate_dict()
-            for k, v in security_settings.items():
-                settings[k] = v
+        security_settings = self.security.generate_dict()
+        for k, v in security_settings.items():
+            settings[k] = v
 
         return settings
diff --git a/packages/antlion/controllers/ap_lib/hostapd_config.py b/packages/antlion/controllers/ap_lib/hostapd_config.py
index 817634b..2effe88 100644
--- a/packages/antlion/controllers/ap_lib/hostapd_config.py
+++ b/packages/antlion/controllers/ap_lib/hostapd_config.py
@@ -18,7 +18,7 @@
 
 from antlion.controllers.ap_lib import hostapd_constants
 from antlion.controllers.ap_lib.hostapd_bss_settings import BssSettings
-from antlion.controllers.ap_lib.hostapd_security import Security
+from antlion.controllers.ap_lib.hostapd_security import Security, SecurityMode
 
 
 def ht40_plus_allowed(channel: int):
@@ -164,6 +164,8 @@
             bss_settings = []
         if additional_parameters is None:
             additional_parameters = {}
+        if security is None:
+            security = Security()
 
         self.set_ap_defaults_profile = set_ap_defaults_profile
         self._interface = interface
@@ -211,17 +213,10 @@
         self._bssid = bssid
         # Default PMF Values
         if pmf_support is None:
-            if (
-                self.security
-                and self.security.security_mode_string == hostapd_constants.WPA3_STRING
-            ):
+            if self.security and self.security.security_mode is SecurityMode.WPA3:
                 # Set PMF required for WP3
                 self._pmf_support = hostapd_constants.PMF_SUPPORT_REQUIRED
-            elif (
-                self.security
-                and self.security.security_mode_string
-                in hostapd_constants.WPA3_MODE_STRINGS
-            ):
+            elif self.security and self.security.security_mode.is_wpa3():
                 # Default PMF to enabled for WPA3 mixed modes (can be
                 # overwritten by explicitly provided value)
                 self._pmf_support = hostapd_constants.PMF_SUPPORT_ENABLED
@@ -234,7 +229,7 @@
         elif (
             pmf_support != hostapd_constants.PMF_SUPPORT_REQUIRED
             and self.security
-            and self.security.security_mode_string == hostapd_constants.WPA3_STRING
+            and self.security.security_mode is SecurityMode.WPA3
         ):
             raise ValueError("PMF support must be required with wpa3.")
         else:
@@ -458,7 +453,7 @@
         self.hidden = value
 
     @property
-    def security(self) -> Optional[Security]:
+    def security(self) -> Security:
         """Returns: The security type being used."""
         return self._security
 
@@ -681,9 +676,8 @@
             conf["local_pwr_constraint"] = 0  # No local constraint
             conf["spectrum_mgmt_required"] = 1  # Requires local_pwr_constraint
 
-        if self._security:
-            for k, v in self._security.generate_dict().items():
-                conf[k] = v
+        for k, v in self._security.generate_dict().items():
+            conf[k] = v
 
         all_conf = [conf]
 
diff --git a/packages/antlion/controllers/ap_lib/hostapd_constants.py b/packages/antlion/controllers/ap_lib/hostapd_constants.py
index 437af28..de3836f 100755
--- a/packages/antlion/controllers/ap_lib/hostapd_constants.py
+++ b/packages/antlion/controllers/ap_lib/hostapd_constants.py
@@ -80,10 +80,7 @@
     WPA_WPA2_WPA3_MIXED_STRING: DUAL_WPA_PSK_SAE_KEY_MGMT,
 }
 
-# TODO(http://b/286584981): Replace with SecurityMode.is_wpa3()
-WPA3_MODE_STRINGS = {WPA3_STRING, WPA2_WPA3_MIXED_STRING, WPA_WPA2_WPA3_MIXED_STRING}
-
-# TODO(http://b/286584981): Replace with SecurityMode.default_target_security
+# TODO(http://b/286584981): Replace with SecurityMode.fuchsia_security_type
 SECURITY_STRING_TO_DEFAULT_TARGET_SECURITY = {
     WEP_STRING: WEP_STRING,
     WPA_STRING: WPA_STRING,
diff --git a/packages/antlion/controllers/ap_lib/hostapd_security.py b/packages/antlion/controllers/ap_lib/hostapd_security.py
index 6365376..af6999e 100644
--- a/packages/antlion/controllers/ap_lib/hostapd_security.py
+++ b/packages/antlion/controllers/ap_lib/hostapd_security.py
@@ -22,27 +22,34 @@
 
 
 class SecurityModeInt(int, Enum):
+    """Possible values for hostapd's "wpa" config option.
+
+    The int value is a bit field that can enable WPA and/or WPA2.
+
+    bit0 = enable WPA defined by IEEE 802.11i/D3.0
+    bit1 = enable RNA (WPA2) defined by IEEE 802.11i/RSN
+    bit2 = enable WAPI (rejected/withdrawn)
+    bit3 = enable OSEN (ENT)
+    """
+
     WEP = 0
     WPA1 = 1
     WPA2 = 2
     WPA3 = 2  # same as wpa2 and wpa2/wpa3; distinguished by wpa_key_mgmt
     MIXED = 3  # applies to wpa/wpa2 and wpa/wpa2/wpa3; distinguished by wpa_key_mgmt
-    ENT = 4  # get the correct constant
+    ENT = 8
 
     def __str__(self):
         return str(self.value)
 
 
 @unique
-class KeyManagement(str, Enum):
+class KeyManagement(StrEnum):
     SAE = "SAE"
     WPA_PSK = "WPA-PSK"
     WPA_PSK_SAE = "WPA-PSK SAE"
     ENT = "WPA-EAP"
 
-    def __str__(self):
-        return self.value
-
 
 # TODO(http://b/286584981): This is currently only being used for OpenWRT.
 # Investigate whether we can replace KeyManagement with OpenWRTEncryptionMode.
@@ -150,12 +157,26 @@
     OWE = "owe"
     """Opportunistic Wireless Encryption (OWE) using CCMP cipher"""
 
-    def __str__(self):
-        return self.value
+
+@unique
+class FuchsiaSecurityType(StrEnum):
+    """Fuchsia supported security types.
+
+    Defined by the fuchsia.wlan.policy.SecurityType FIDL.
+
+    https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/fidl/fuchsia.wlan.policy/types.fidl
+    """
+
+    NONE = "none"
+    WEP = "wep"
+    WPA = "wpa"
+    WPA2 = "wpa2"
+    WPA3 = "wpa3"
 
 
 @unique
-class SecurityMode(str, Enum):
+class SecurityMode(StrEnum):
+    OPEN = "open"
     WEP = "wep"
     WPA = "wpa"
     WPA2 = "wpa2"
@@ -165,10 +186,10 @@
     WPA_WPA2_WPA3 = "wpa/wpa2/wpa3"
     ENT = "ent"
 
-    def __str__(self):
-        return self.value
-
+    # TODO(http://b/261746355): Use a PEP 636 `match` statement.
     def security_mode_int(self) -> SecurityModeInt:
+        if self == SecurityMode.OPEN:
+            raise TypeError("Open security doesn't have a SecurityModeInt")
         if self == SecurityMode.WEP:
             return SecurityModeInt.WEP
         if self == SecurityMode.WPA:
@@ -187,7 +208,10 @@
             return SecurityModeInt.ENT
         raise TypeError("Unknown security mode")
 
+    # TODO(http://b/261746355): Use a PEP 636 `match` statement.
     def key_management(self) -> Optional[KeyManagement]:
+        if self == SecurityMode.OPEN:
+            return None
         if self == SecurityMode.WEP:
             return None
         if self == SecurityMode.WPA:
@@ -206,27 +230,52 @@
             return KeyManagement.ENT
         raise TypeError("Unknown security mode")
 
-    def default_target_security(self) -> "SecurityMode":
+    # TODO(http://b/261746355): Use a PEP 636 `match` statement.
+    def fuchsia_security_type(self) -> FuchsiaSecurityType:
+        if self == SecurityMode.OPEN:
+            return FuchsiaSecurityType.NONE
         if self == SecurityMode.WEP:
-            return SecurityMode.WEP
+            return FuchsiaSecurityType.WEP
         if self == SecurityMode.WPA:
-            return SecurityMode.WPA
+            return FuchsiaSecurityType.WPA
         if self == SecurityMode.WPA2:
-            return SecurityMode.WPA2
+            return FuchsiaSecurityType.WPA2
         if self == SecurityMode.WPA_WPA2:
-            return SecurityMode.WPA2
+            return FuchsiaSecurityType.WPA2
         if self == SecurityMode.WPA3:
-            return SecurityMode.WPA3
+            return FuchsiaSecurityType.WPA3
         if self == SecurityMode.WPA2_WPA3:
-            return SecurityMode.WPA3
+            return FuchsiaSecurityType.WPA3
         if self == SecurityMode.WPA_WPA2_WPA3:
-            return SecurityMode.WPA3
+            return FuchsiaSecurityType.WPA3
         if self == SecurityMode.ENT:
             raise NotImplementedError(
-                f'Security mode "{self}" does not have a default target security'
+                f'Fuchsia has not implemented support for security mode "{self}"'
             )
         raise TypeError("Unknown security mode")
 
+    # TODO(http://b/261746355): Use a PEP 636 `match` statement.
+    def is_wpa3(self) -> bool:
+        if self == SecurityMode.OPEN:
+            return False
+        if self == SecurityMode.WEP:
+            return False
+        if self == SecurityMode.WPA:
+            return False
+        if self == SecurityMode.WPA2:
+            return False
+        if self == SecurityMode.WPA_WPA2:
+            return False
+        if self == SecurityMode.WPA3:
+            return True
+        if self == SecurityMode.WPA2_WPA3:
+            return True
+        if self == SecurityMode.WPA_WPA2_WPA3:
+            return True
+        if self == SecurityMode.ENT:
+            return False
+        raise TypeError("Unknown security mode")
+
 
 class Security(object):
     """The Security class for hostapd representing some of the security
@@ -235,7 +284,7 @@
 
     def __init__(
         self,
-        security_mode: Optional[SecurityMode] = None,
+        security_mode: SecurityMode = SecurityMode.OPEN,
         password: Optional[str] = None,
         wpa_cipher: Optional[str] = hostapd_constants.WPA_DEFAULT_CIPHER,
         wpa2_cipher: Optional[str] = hostapd_constants.WPA2_DEFAULT_CIPER,
@@ -250,9 +299,7 @@
            expanded later.
 
         Args:
-            security_mode: Type of security modes.
-                        Options: wep, wpa, wpa2, wpa/wpa2, wpa3, wpa2/wpa3,
-                        wpa/wpa2/wpa3
+            security_mode: Type of security mode.
             password: The PSK or passphrase for the security mode.
             wpa_cipher: The cipher to be used for wpa.
                         Options: TKIP, CCMP, TKIP CCMP
@@ -262,7 +309,7 @@
                          Default: CCMP
             wpa_group_rekey: How often to refresh the GTK regardless of network
                              changes.
-                             Options: An integrer in seconds, None
+                             Options: An integer in seconds, None
                              Default: 600 seconds
             wpa_strict_rekey: Whether to do a group key update when client
                               leaves the network or not.
@@ -273,7 +320,7 @@
             radius_server_port: Radius server port for Enterprise auth.
             radius_server_secret: Radius server secret for Enterprise auth.
         """
-        self.security_mode_string = security_mode
+        self.security_mode = security_mode
         self.wpa_cipher = wpa_cipher
         self.wpa2_cipher = wpa2_cipher
         self.wpa_group_rekey = wpa_group_rekey
@@ -282,13 +329,8 @@
         self.radius_server_ip = radius_server_ip
         self.radius_server_port = radius_server_port
         self.radius_server_secret = radius_server_secret
-        self.security_mode = (
-            hostapd_constants.SECURITY_STRING_TO_SECURITY_MODE_INT[security_mode]
-            if security_mode is not None
-            else None
-        )
         if password:
-            if self.security_mode == hostapd_constants.WEP:
+            if self.security_mode is SecurityMode.WEP:
                 if len(password) in hostapd_constants.WEP_STR_LENGTH:
                     self.password = f'"{password}"'
                 elif len(password) in hostapd_constants.WEP_HEX_LENGTH and all(
@@ -317,51 +359,52 @@
 
     def generate_dict(self) -> Dict[str, Union[str, int]]:
         """Returns: an ordered dictionary of settings"""
+        if self.security_mode is SecurityMode.OPEN:
+            return {}
+
         settings: Dict[str, Union[str, int]] = collections.OrderedDict()
-        if self.security_mode is not None:
-            if self.security_mode == hostapd_constants.WEP:
-                settings["wep_default_key"] = self.wep_default_key
-                settings[f"wep_key{self.wep_default_key}"] = self.password
-            elif self.security_mode == hostapd_constants.ENT:
-                if self.radius_server_ip is not None:
-                    settings["auth_server_addr"] = self.radius_server_ip
-                if self.radius_server_port is not None:
-                    settings["auth_server_port"] = self.radius_server_port
-                if self.radius_server_secret is not None:
-                    settings["auth_server_shared_secret"] = self.radius_server_secret
-                settings["wpa_key_mgmt"] = hostapd_constants.ENT_KEY_MGMT
-                settings["ieee8021x"] = hostapd_constants.IEEE8021X
-                settings["wpa"] = hostapd_constants.WPA2
+
+        if self.security_mode is SecurityMode.WEP:
+            settings["wep_default_key"] = self.wep_default_key
+            settings[f"wep_key{self.wep_default_key}"] = self.password
+        elif self.security_mode == SecurityMode.ENT:
+            if self.radius_server_ip is not None:
+                settings["auth_server_addr"] = self.radius_server_ip
+            if self.radius_server_port is not None:
+                settings["auth_server_port"] = self.radius_server_port
+            if self.radius_server_secret is not None:
+                settings["auth_server_shared_secret"] = self.radius_server_secret
+            settings["wpa_key_mgmt"] = hostapd_constants.ENT_KEY_MGMT
+            settings["ieee8021x"] = hostapd_constants.IEEE8021X
+            settings["wpa"] = hostapd_constants.WPA2
+        else:
+            settings["wpa"] = self.security_mode.security_mode_int().value
+            if len(self.password) == hostapd_constants.MAX_WPA_PSK_LENGTH:
+                settings["wpa_psk"] = self.password
             else:
-                settings["wpa"] = self.security_mode
-                if len(self.password) == hostapd_constants.MAX_WPA_PSK_LENGTH:
-                    settings["wpa_psk"] = self.password
-                else:
-                    settings["wpa_passphrase"] = self.password
-                # For wpa, wpa/wpa2, and wpa/wpa2/wpa3, add wpa_pairwise
-                if self.wpa_cipher and (
-                    self.security_mode == hostapd_constants.WPA1
-                    or self.security_mode == hostapd_constants.MIXED
-                ):
-                    settings["wpa_pairwise"] = self.wpa_cipher
-                # For wpa/wpa2, wpa2, wpa3, and wpa2/wpa3, and wpa/wpa2, wpa3, add rsn_pairwise
-                if self.wpa2_cipher and (
-                    self.security_mode == hostapd_constants.WPA2
-                    or self.security_mode == hostapd_constants.MIXED
-                ):
-                    settings["rsn_pairwise"] = self.wpa2_cipher
-                # Add wpa_key_mgmt based on security mode string
-                if (
-                    self.security_mode_string
-                    in hostapd_constants.SECURITY_STRING_TO_WPA_KEY_MGMT
-                ):
-                    settings[
-                        "wpa_key_mgmt"
-                    ] = hostapd_constants.SECURITY_STRING_TO_WPA_KEY_MGMT[
-                        self.security_mode_string
-                    ]
-                if self.wpa_group_rekey:
-                    settings["wpa_group_rekey"] = self.wpa_group_rekey
-                if self.wpa_strict_rekey:
-                    settings["wpa_strict_rekey"] = hostapd_constants.WPA_STRICT_REKEY
+                settings["wpa_passphrase"] = self.password
+            # For wpa, wpa/wpa2, and wpa/wpa2/wpa3, add wpa_pairwise
+            if self.wpa_cipher and (
+                self.security_mode is SecurityMode.WPA
+                or self.security_mode is SecurityMode.WPA_WPA2
+                or self.security_mode is SecurityMode.WPA_WPA2_WPA3
+            ):
+                settings["wpa_pairwise"] = self.wpa_cipher
+            # For wpa/wpa2, wpa2, wpa3, and wpa2/wpa3, and wpa/wpa2, wpa3, add rsn_pairwise
+            if self.wpa2_cipher and (
+                self.security_mode is SecurityMode.WPA_WPA2
+                or self.security_mode is SecurityMode.WPA2
+                or self.security_mode is SecurityMode.WPA2_WPA3
+                or self.security_mode is SecurityMode.WPA3
+            ):
+                settings["rsn_pairwise"] = self.wpa2_cipher
+            # Add wpa_key_mgmt based on security mode string
+            wpa_key_mgmt = self.security_mode.key_management()
+            if wpa_key_mgmt is not None:
+                settings["wpa_key_mgmt"] = str(wpa_key_mgmt)
+            if self.wpa_group_rekey:
+                settings["wpa_group_rekey"] = self.wpa_group_rekey
+            if self.wpa_strict_rekey:
+                settings["wpa_strict_rekey"] = hostapd_constants.WPA_STRICT_REKEY
+
         return settings
diff --git a/packages/antlion/controllers/ap_lib/hostapd_utils.py b/packages/antlion/controllers/ap_lib/hostapd_utils.py
index face504..8eefe8b 100644
--- a/packages/antlion/controllers/ap_lib/hostapd_utils.py
+++ b/packages/antlion/controllers/ap_lib/hostapd_utils.py
@@ -12,15 +12,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from typing import List, Optional, Union
+from typing import List, Optional
 
 from antlion import utils
 from antlion.controllers.ap_lib import hostapd_constants
-from antlion.controllers.ap_lib.hostapd_security import Security
+from antlion.controllers.ap_lib.hostapd_security import Security, SecurityMode
 
 
 def generate_random_password(
-    security_mode: Optional[str] = None,
+    security_mode: SecurityMode = SecurityMode.OPEN,
     length: Optional[int] = None,
     hex: Optional[int] = None,
 ) -> str:
@@ -40,70 +40,59 @@
 
     if length:
         return generator_func(length)
-    if security_mode and security_mode.lower() == hostapd_constants.WEP_STRING:
+    if security_mode is SecurityMode.WEP:
         return generator_func(hostapd_constants.WEP_DEFAULT_STR_LENGTH)
     else:
         return generator_func(hostapd_constants.MIN_WPA_PSK_LENGTH)
 
 
-def verify_interface(interface: Optional[str], valid_interfaces: List[str]) -> None:
+def verify_interface(interface: str, valid_interfaces: List[str]) -> None:
     """Raises error if interface is missing or invalid
 
     Args:
         interface: interface name
         valid_interfaces: valid interface names
     """
-    if not interface:
-        raise ValueError("Required wlan interface is missing.")
     if interface not in valid_interfaces:
         raise ValueError(f"Invalid interface name was passed: {interface}")
 
 
 def verify_security_mode(
-    security_profile: Optional[Security], valid_security_modes: List[Union[int, None]]
+    security_profile: Security, valid_security_modes: List[SecurityMode]
 ) -> None:
     """Raises error if security mode is not in list of valid security modes.
 
     Args:
-        security_profile: a hostapd_security.Security object.
-        valid_security_modes: a list of valid security modes for a profile. Must
-            include None if open security is valid.
+        security_profile: Security to verify
+        valid_security_modes: Valid security modes for a profile.
     """
-    if security_profile is None:
-        if None not in valid_security_modes:
-            raise ValueError("Open security is not allowed for this profile.")
-    elif security_profile.security_mode not in valid_security_modes:
+    if security_profile.security_mode not in valid_security_modes:
         raise ValueError(
-            "Invalid Security Mode: %s. "
-            "Valid Security Modes for this profile: %s."
-            % (security_profile.security_mode, valid_security_modes)
+            f"Invalid Security Mode: {security_profile.security_mode}; "
+            f"Valid Security Modes for this profile: {valid_security_modes}"
         )
 
 
-def verify_cipher(
-    security_profile: Optional[Security], valid_ciphers: List[str]
-) -> None:
+def verify_cipher(security_profile: Security, valid_ciphers: List[str]) -> None:
     """Raise error if cipher is not in list of valid ciphers.
 
     Args:
-        security_profile: a hostapd_security.Security object.
-        valid_ciphers: a list of valid ciphers for a profile.
+        security_profile: Security profile to verify
+        valid_ciphers: A list of valid ciphers for security_profile.
     """
-    if security_profile is None:
+    if security_profile.security_mode is SecurityMode.OPEN:
         raise ValueError("Security mode is open.")
-    elif security_profile.security_mode == hostapd_constants.WPA1:
+    elif security_profile.security_mode is SecurityMode.WPA:
         if security_profile.wpa_cipher not in valid_ciphers:
             raise ValueError(
-                "Invalid WPA Cipher: %s. "
-                "Valid WPA Ciphers for this profile: %s"
-                % (security_profile.wpa_cipher, valid_ciphers)
+                f"Invalid WPA Cipher: {security_profile.wpa_cipher}. "
+                f"Valid WPA Ciphers for this profile: {valid_ciphers}"
             )
-    elif security_profile.security_mode == hostapd_constants.WPA2:
+    elif security_profile.security_mode is SecurityMode.WPA2:
         if security_profile.wpa2_cipher not in valid_ciphers:
             raise ValueError(
-                "Invalid WPA2 Cipher: %s. "
-                "Valid WPA2 Ciphers for this profile: %s"
-                % (security_profile.wpa2_cipher, valid_ciphers)
+                f"Invalid WPA2 Cipher: {security_profile.wpa2_cipher}. "
+                f"Valid WPA2 Ciphers for this profile: {valid_ciphers}"
             )
     else:
         raise ValueError(f"Invalid Security Mode: {security_profile.security_mode}")
diff --git a/packages/antlion/controllers/ap_lib/third_party_ap_profiles/actiontec.py b/packages/antlion/controllers/ap_lib/third_party_ap_profiles/actiontec.py
index 54a6188..73bbf72 100644
--- a/packages/antlion/controllers/ap_lib/third_party_ap_profiles/actiontec.py
+++ b/packages/antlion/controllers/ap_lib/third_party_ap_profiles/actiontec.py
@@ -12,16 +12,21 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from typing import Optional
+
 from antlion import utils
 from antlion.controllers.ap_lib import hostapd_config, hostapd_constants, hostapd_utils
+from antlion.controllers.ap_lib.hostapd_security import Security, SecurityMode
 
 
-def actiontec_pk5000(iface_wlan_2g=None, channel=None, security=None, ssid=None):
+def actiontec_pk5000(
+    iface_wlan_2g: str, channel: int, security: Security, ssid: Optional[str] = None
+):
     """A simulated implementation of what a Actiontec PK5000 AP
     Args:
         iface_wlan_2g: The 2.4 interface of the test AP.
         channel: What channel to use.  Only 2.4Ghz is supported for this profile
-        security: A security profile.  Must be none or WPA2 as this is what is
+        security: A security profile.  Must be open or WPA2 as this is what is
             supported by the PK5000.
         ssid: Network name
     Returns:
@@ -42,7 +47,7 @@
         )
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
@@ -74,7 +79,9 @@
     return config
 
 
-def actiontec_mi424wr(iface_wlan_2g=None, channel=None, security=None, ssid=None):
+def actiontec_mi424wr(
+    iface_wlan_2g: str, channel: int, security: Security, ssid: Optional[str] = None
+):
     # TODO(b/143104825): Permit RIFS once it is supported
     """A simulated implementation of an Actiontec MI424WR AP.
     Args:
@@ -103,7 +110,7 @@
         )
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
diff --git a/packages/antlion/controllers/ap_lib/third_party_ap_profiles/asus.py b/packages/antlion/controllers/ap_lib/third_party_ap_profiles/asus.py
index 980de0f..c01e175 100644
--- a/packages/antlion/controllers/ap_lib/third_party_ap_profiles/asus.py
+++ b/packages/antlion/controllers/ap_lib/third_party_ap_profiles/asus.py
@@ -12,12 +12,19 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from typing import Optional
+
 from antlion import utils
 from antlion.controllers.ap_lib import hostapd_config, hostapd_constants, hostapd_utils
+from antlion.controllers.ap_lib.hostapd_security import Security, SecurityMode
 
 
 def asus_rtac66u(
-    iface_wlan_2g=None, iface_wlan_5g=None, channel=None, security=None, ssid=None
+    iface_wlan_2g: str,
+    iface_wlan_5g: str,
+    channel: int,
+    security: Security,
+    ssid: Optional[str] = None,
 ):
     # TODO(b/143104825): Permit RIFS once it is supported
     # TODO(b/144446076): Address non-whirlwind hardware capabilities.
@@ -26,7 +33,7 @@
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         iface_wlan_5g: The 5Ghz interface of the test AP.
         channel: What channel to use.
-        security: A security profile.  Must be none or WPA2 as this is what is
+        security: A security profile.  Must be open or WPA2 as this is what is
             supported by the RTAC66U.
         ssid: Network name
     Returns:
@@ -72,7 +79,7 @@
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
     hostapd_utils.verify_interface(iface_wlan_5g, hostapd_constants.INTERFACE_5G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
@@ -141,14 +148,18 @@
 
 
 def asus_rtac86u(
-    iface_wlan_2g=None, iface_wlan_5g=None, channel=None, security=None, ssid=None
+    iface_wlan_2g: str,
+    iface_wlan_5g: str,
+    channel: int,
+    security: Security,
+    ssid: Optional[str] = None,
 ):
     """A simulated implementation of an Asus RTAC86U AP.
     Args:
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         iface_wlan_5g: The 5Ghz interface of the test AP.
         channel: What channel to use.
-        security: A security profile.  Must be none or WPA2 as this is what is
+        security: A security profile.  Must be open or WPA2 as this is what is
             supported by the RTAC86U.
         ssid: Network name
     Returns:
@@ -177,7 +188,7 @@
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
     hostapd_utils.verify_interface(iface_wlan_5g, hostapd_constants.INTERFACE_5G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
@@ -231,7 +242,11 @@
 
 
 def asus_rtac5300(
-    iface_wlan_2g=None, iface_wlan_5g=None, channel=None, security=None, ssid=None
+    iface_wlan_2g: str,
+    iface_wlan_5g: str,
+    channel: int,
+    security: Security,
+    ssid: Optional[str] = None,
 ):
     # TODO(b/143104825): Permit RIFS once it is supported
     # TODO(b/144446076): Address non-whirlwind hardware capabilities.
@@ -240,7 +255,7 @@
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         iface_wlan_5g: The 5Ghz interface of the test AP.
         channel: What channel to use.
-        security: A security profile.  Must be none or WPA2 as this is what is
+        security: A security profile.  Must be open or WPA2 as this is what is
             supported by the RTAC5300.
         ssid: Network name
     Returns:
@@ -283,7 +298,7 @@
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
     hostapd_utils.verify_interface(iface_wlan_5g, hostapd_constants.INTERFACE_5G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
@@ -355,14 +370,18 @@
 
 
 def asus_rtn56u(
-    iface_wlan_2g=None, iface_wlan_5g=None, channel=None, security=None, ssid=None
+    iface_wlan_2g: str,
+    iface_wlan_5g: str,
+    channel: int,
+    security: Security,
+    ssid: Optional[str] = None,
 ):
     """A simulated implementation of an Asus RTN56U AP.
     Args:
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         iface_wlan_5g: The 5Ghz interface of the test AP.
         channel: What channel to use.
-        security: A security profile.  Must be none or WPA2 as this is what is
+        security: A security profile.  Must be open or WPA2 as this is what is
             supported by the RTN56U.
         ssid: Network name
     Returns:
@@ -393,7 +412,7 @@
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
     hostapd_utils.verify_interface(iface_wlan_5g, hostapd_constants.INTERFACE_5G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
@@ -455,7 +474,11 @@
 
 
 def asus_rtn66u(
-    iface_wlan_2g=None, iface_wlan_5g=None, channel=None, security=None, ssid=None
+    iface_wlan_2g: str,
+    iface_wlan_5g: str,
+    channel: int,
+    security: Security,
+    ssid: Optional[str] = None,
 ):
     # TODO(b/143104825): Permit RIFS once it is supported
     """A simulated implementation of an Asus RTN66U AP.
@@ -463,7 +486,7 @@
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         iface_wlan_5g: The 5Ghz interface of the test AP.
         channel: What channel to use.
-        security: A security profile.  Must be none or WPA2 as this is what is
+        security: A security profile.  Must be open or WPA2 as this is what is
             supported by the RTN66U.
         ssid: Network name
     Returns:
@@ -492,7 +515,7 @@
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
     hostapd_utils.verify_interface(iface_wlan_5g, hostapd_constants.INTERFACE_5G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
diff --git a/packages/antlion/controllers/ap_lib/third_party_ap_profiles/belkin.py b/packages/antlion/controllers/ap_lib/third_party_ap_profiles/belkin.py
index f48a66a..58e303f 100644
--- a/packages/antlion/controllers/ap_lib/third_party_ap_profiles/belkin.py
+++ b/packages/antlion/controllers/ap_lib/third_party_ap_profiles/belkin.py
@@ -12,17 +12,22 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from typing import Optional
+
 from antlion import utils
 from antlion.controllers.ap_lib import hostapd_config, hostapd_constants, hostapd_utils
+from antlion.controllers.ap_lib.hostapd_security import Security, SecurityMode
 
 
-def belkin_f9k1001v5(iface_wlan_2g=None, channel=None, security=None, ssid=None):
+def belkin_f9k1001v5(
+    iface_wlan_2g: str, channel: int, security: Security, ssid: Optional[str] = None
+):
     # TODO(b/143104825): Permit RIFS once it is supported
     """A simulated implementation of what a Belkin F9K1001v5 AP
     Args:
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         channel: What channel to use.
-        security: A security profile (None or WPA2).
+        security: A security profile (open or WPA2).
         ssid: The network name.
     Returns:
         A hostapd config.
@@ -51,7 +56,7 @@
         )
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
diff --git a/packages/antlion/controllers/ap_lib/third_party_ap_profiles/linksys.py b/packages/antlion/controllers/ap_lib/third_party_ap_profiles/linksys.py
index fb065d2..fdc8a5a 100644
--- a/packages/antlion/controllers/ap_lib/third_party_ap_profiles/linksys.py
+++ b/packages/antlion/controllers/ap_lib/third_party_ap_profiles/linksys.py
@@ -12,12 +12,19 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from typing import Optional
+
 from antlion import utils
 from antlion.controllers.ap_lib import hostapd_config, hostapd_constants, hostapd_utils
+from antlion.controllers.ap_lib.hostapd_security import Security, SecurityMode
 
 
 def linksys_ea4500(
-    iface_wlan_2g=None, iface_wlan_5g=None, channel=None, security=None, ssid=None
+    iface_wlan_2g: str,
+    iface_wlan_5g,
+    channel: int,
+    security: Security,
+    ssid: Optional[str] = None,
 ):
     # TODO(b/143104825): Permit RIFS once it is supported
     # TODO(b/144446076): Address non-whirlwind hardware capabilities.
@@ -26,7 +33,7 @@
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         iface_wlan_5g: The 5GHz interface of the test AP.
         channel: What channel to use.
-        security: A security profile (None or WPA2).
+        security: A security profile (open or WPA2).
         ssid: The network name.
     Returns:
         A hostapd config.
@@ -50,7 +57,7 @@
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
     hostapd_utils.verify_interface(iface_wlan_5g, hostapd_constants.INTERFACE_5G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
@@ -111,14 +118,18 @@
 
 
 def linksys_ea9500(
-    iface_wlan_2g=None, iface_wlan_5g=None, channel=None, security=None, ssid=None
+    iface_wlan_2g: str,
+    iface_wlan_5g: str,
+    channel: int,
+    security: Security,
+    ssid: Optional[str] = None,
 ):
     """A simulated implementation of what a Linksys EA9500 AP
     Args:
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         iface_wlan_5g: The 5GHz interface of the test AP.
         channel: What channel to use.
-        security: A security profile (None or WPA2).
+        security: A security profile (open or WPA2).
         ssid: The network name.
     Returns:
         A hostapd config.
@@ -140,7 +151,7 @@
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
     hostapd_utils.verify_interface(iface_wlan_5g, hostapd_constants.INTERFACE_5G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
@@ -181,7 +192,11 @@
 
 
 def linksys_wrt1900acv2(
-    iface_wlan_2g=None, iface_wlan_5g=None, channel=None, security=None, ssid=None
+    iface_wlan_2g: str,
+    iface_wlan_5g: str,
+    channel: int,
+    security: Security,
+    ssid: Optional[str] = None,
 ):
     # TODO(b/144446076): Address non-whirlwind hardware capabilities.
     """A simulated implementation of what a Linksys WRT1900ACV2 AP
@@ -189,7 +204,7 @@
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         iface_wlan_5g: The 5GHz interface of the test AP.
         channel: What channel to use.
-        security: A security profile (None or WPA2).
+        security: A security profile (open or WPA2).
         ssid: The network name.
     Returns:
         A hostapd config.
@@ -220,7 +235,7 @@
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
     hostapd_utils.verify_interface(iface_wlan_5g, hostapd_constants.INTERFACE_5G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
diff --git a/packages/antlion/controllers/ap_lib/third_party_ap_profiles/netgear.py b/packages/antlion/controllers/ap_lib/third_party_ap_profiles/netgear.py
index c4b57d3..da1f568 100644
--- a/packages/antlion/controllers/ap_lib/third_party_ap_profiles/netgear.py
+++ b/packages/antlion/controllers/ap_lib/third_party_ap_profiles/netgear.py
@@ -12,12 +12,19 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from typing import Optional
+
 from antlion import utils
 from antlion.controllers.ap_lib import hostapd_config, hostapd_constants, hostapd_utils
+from antlion.controllers.ap_lib.hostapd_security import Security, SecurityMode
 
 
 def netgear_r7000(
-    iface_wlan_2g=None, iface_wlan_5g=None, channel=None, security=None, ssid=None
+    iface_wlan_2g: str,
+    iface_wlan_5g: str,
+    channel: int,
+    security: Security,
+    ssid: Optional[str] = None,
 ):
     # TODO(b/143104825): Permit RIFS once it is supported
     # TODO(b/144446076): Address non-whirlwind hardware capabilities.
@@ -26,7 +33,7 @@
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         iface_wlan_5g: The 5GHz interface of the test AP.
         channel: What channel to use.
-        security: A security profile (None or WPA2).
+        security: A security profile (open or WPA2).
         ssid: The network name.
     Returns:
         A hostapd config.
@@ -76,7 +83,7 @@
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
     hostapd_utils.verify_interface(iface_wlan_5g, hostapd_constants.INTERFACE_5G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
@@ -165,7 +172,11 @@
 
 
 def netgear_wndr3400(
-    iface_wlan_2g=None, iface_wlan_5g=None, channel=None, security=None, ssid=None
+    iface_wlan_2g: str,
+    iface_wlan_5g: str,
+    channel: int,
+    security: Security,
+    ssid: Optional[str] = None,
 ):
     # TODO(b/143104825): Permit RIFS on 5GHz once it is supported
     # TODO(b/144446076): Address non-whirlwind hardware capabilities.
@@ -174,7 +185,7 @@
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         iface_wlan_5g: The 5GHz interface of the test AP.
         channel: What channel to use.
-        security: A security profile (None or WPA2).
+        security: A security profile (open or WPA2).
         ssid: The network name.
     Returns:
         A hostapd config.
@@ -203,7 +214,7 @@
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
     hostapd_utils.verify_interface(iface_wlan_5g, hostapd_constants.INTERFACE_5G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
diff --git a/packages/antlion/controllers/ap_lib/third_party_ap_profiles/securifi.py b/packages/antlion/controllers/ap_lib/third_party_ap_profiles/securifi.py
index 241907f..9b6587a 100644
--- a/packages/antlion/controllers/ap_lib/third_party_ap_profiles/securifi.py
+++ b/packages/antlion/controllers/ap_lib/third_party_ap_profiles/securifi.py
@@ -12,16 +12,21 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from typing import Optional
+
 from antlion import utils
 from antlion.controllers.ap_lib import hostapd_config, hostapd_constants, hostapd_utils
+from antlion.controllers.ap_lib.hostapd_security import Security, SecurityMode
 
 
-def securifi_almond(iface_wlan_2g=None, channel=None, security=None, ssid=None):
+def securifi_almond(
+    iface_wlan_2g: str, channel: int, security: Security, ssid: Optional[str] = None
+):
     """A simulated implementation of a Securifi Almond AP
     Args:
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         channel: What channel to use.
-        security: A security profile (None or WPA2).
+        security: A security profile (open or WPA2).
         ssid: The network name.
     Returns:
         A hostapd config.
@@ -49,7 +54,7 @@
         )
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
diff --git a/packages/antlion/controllers/ap_lib/third_party_ap_profiles/tplink.py b/packages/antlion/controllers/ap_lib/third_party_ap_profiles/tplink.py
index 140ed02..7a1f7a7 100644
--- a/packages/antlion/controllers/ap_lib/third_party_ap_profiles/tplink.py
+++ b/packages/antlion/controllers/ap_lib/third_party_ap_profiles/tplink.py
@@ -16,10 +16,15 @@
 
 from antlion import utils
 from antlion.controllers.ap_lib import hostapd_config, hostapd_constants, hostapd_utils
+from antlion.controllers.ap_lib.hostapd_security import Security, SecurityMode
 
 
 def tplink_archerc5(
-    iface_wlan_2g=None, iface_wlan_5g=None, channel=None, security=None, ssid=None
+    iface_wlan_2g: str,
+    iface_wlan_5g: str,
+    channel: int,
+    security: Security,
+    ssid: Optional[str] = None,
 ):
     # TODO(b/144446076): Address non-whirlwind hardware capabilities.
     """A simulated implementation of an TPLink ArcherC5 AP.
@@ -27,7 +32,7 @@
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         iface_wlan_5g: The 5GHz interface of the test AP.
         channel: What channel to use.
-        security: A security profile (None or WPA2).
+        security: A security profile (open or WPA2).
         ssid: The network name.
     Returns:
         A hostapd config.
@@ -72,7 +77,7 @@
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
     hostapd_utils.verify_interface(iface_wlan_5g, hostapd_constants.INTERFACE_5G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
@@ -148,7 +153,11 @@
 
 
 def tplink_archerc7(
-    iface_wlan_2g=None, iface_wlan_5g=None, channel=None, security=None, ssid=None
+    iface_wlan_2g: str,
+    iface_wlan_5g: str,
+    channel: int,
+    security: Security,
+    ssid: Optional[str] = None,
 ):
     # TODO(b/143104825): Permit RIFS once it is supported
     """A simulated implementation of an TPLink ArcherC7 AP.
@@ -156,7 +165,7 @@
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         iface_wlan_5g: The 5GHz interface of the test AP.
         channel: What channel to use.
-        security: A security profile (None or WPA2).
+        security: A security profile (open or WPA2).
         ssid: The network name.
     Returns:
         A hostapd config.
@@ -179,7 +188,7 @@
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
     hostapd_utils.verify_interface(iface_wlan_5g, hostapd_constants.INTERFACE_5G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
@@ -270,7 +279,11 @@
 
 
 def tplink_c1200(
-    iface_wlan_2g=None, iface_wlan_5g=None, channel=None, security=None, ssid=None
+    iface_wlan_2g: str,
+    iface_wlan_5g: str,
+    channel: int,
+    security: Security,
+    ssid: Optional[str] = None,
 ):
     # TODO(b/143104825): Permit RIFS once it is supported
     # TODO(b/144446076): Address non-whirlwind hardware capabilities.
@@ -279,7 +292,7 @@
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         iface_wlan_5g: The 5GHz interface of the test AP.
         channel: What channel to use.
-        security: A security profile (None or WPA2).
+        security: A security profile (open or WPA2).
         ssid: The network name.
     Returns:
         A hostapd config.
@@ -311,7 +324,7 @@
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
     hostapd_utils.verify_interface(iface_wlan_5g, hostapd_constants.INTERFACE_5G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
@@ -383,13 +396,15 @@
     return config
 
 
-def tplink_tlwr940n(iface_wlan_2g=None, channel=None, security=None, ssid=None):
+def tplink_tlwr940n(
+    iface_wlan_2g: str, channel: int, security: Security, ssid: Optional[str] = None
+):
     # TODO(b/143104825): Permit RIFS once it is supported
     """A simulated implementation of an TPLink TLWR940N AP.
     Args:
         iface_wlan_2g: The 2.4Ghz interface of the test AP.
         channel: What channel to use.
-        security: A security profile (None or WPA2).
+        security: A security profile (open or WPA2).
         ssid: The network name.
     Returns:
         A hostapd config.
@@ -410,7 +425,7 @@
         )
     # Verify interface and security
     hostapd_utils.verify_interface(iface_wlan_2g, hostapd_constants.INTERFACE_2G_LIST)
-    hostapd_utils.verify_security_mode(security, [None, hostapd_constants.WPA2])
+    hostapd_utils.verify_security_mode(security, [SecurityMode.OPEN, SecurityMode.WPA2])
     if security:
         hostapd_utils.verify_cipher(security, [hostapd_constants.WPA2_DEFAULT_CIPER])
 
diff --git a/packages/antlion/controllers/fuchsia_lib/lib_controllers/wlan_policy_controller.py b/packages/antlion/controllers/fuchsia_lib/lib_controllers/wlan_policy_controller.py
index 3a051d1..439bca3 100644
--- a/packages/antlion/controllers/fuchsia_lib/lib_controllers/wlan_policy_controller.py
+++ b/packages/antlion/controllers/fuchsia_lib/lib_controllers/wlan_policy_controller.py
@@ -20,6 +20,7 @@
 from typing import Any, Dict, List, Optional, Tuple
 
 from antlion import logger, signals
+from antlion.controllers.ap_lib.hostapd_security import FuchsiaSecurityType
 from antlion.controllers.fuchsia_lib.sl4f import SL4F
 from antlion.controllers.fuchsia_lib.ssh import FuchsiaSSHProvider
 
@@ -131,7 +132,7 @@
 
         self.policy_configured = True
 
-    def _deconfigure_wlan(self):
+    def _deconfigure_wlan(self) -> None:
         if not self.stop_client_connections():
             raise WlanPolicyControllerError(
                 "Failed to stop client connections during deconfiguration."
@@ -148,7 +149,7 @@
 
         self.restore_preserved_networks_and_client_state()
 
-    def start_client_connections(self):
+    def start_client_connections(self) -> bool:
         """Allow device to connect to networks via policy layer (including
         autoconnecting to saved networks).
 
@@ -162,7 +163,7 @@
             return False
         return True
 
-    def stop_client_connections(self):
+    def stop_client_connections(self) -> bool:
         """Prevent device from connecting and autoconnecting to networks via the
         policy layer.
 
@@ -176,7 +177,13 @@
             return False
         return True
 
-    def save_and_connect(self, ssid, security, password=None, timeout=30):
+    def save_and_connect(
+        self,
+        ssid: str,
+        security: FuchsiaSecurityType,
+        password: Optional[str] = None,
+        timeout: int = 30,
+    ):
         """Saves and connects to the network. This is the policy version of
         connect and check_connect_response because the policy layer
         requires a saved network and the policy connect does not return
@@ -200,7 +207,13 @@
             return False
         return self.wait_for_connect(ssid, security, timeout=timeout)
 
-    def save_and_wait_for_autoconnect(self, ssid, security, password=None, timeout=30):
+    def save_and_wait_for_autoconnect(
+        self,
+        ssid: str,
+        security: FuchsiaSecurityType,
+        password: Optional[str] = None,
+        timeout: int = 30,
+    ) -> bool:
         """Saves a network and waits, expecting an autoconnection to the newly
         saved network. This differes from save_and_connect, as it doesn't
         expressly trigger a connection first. There are cases in which an
@@ -222,8 +235,14 @@
         return self.wait_for_connect(ssid, security, timeout=timeout)
 
     def remove_and_wait_for_disconnect(
-        self, ssid, security_type, password=None, state=None, status=None, timeout=30
-    ):
+        self,
+        ssid: str,
+        security_type: FuchsiaSecurityType,
+        password: Optional[str] = None,
+        state: Optional[str] = None,
+        status: Optional[str] = None,
+        timeout: int = 30,
+    ) -> bool:
         """Removes a single network and waits for a disconnect. It is not
         guaranteed the device will stay disconnected, as it may autoconnect
         to a different saved network.
@@ -269,7 +288,12 @@
             return False
         return self.wait_for_no_connections(timeout_sec=timeout_sec)
 
-    def save_network(self, ssid, security_type, password=None):
+    def save_network(
+        self,
+        ssid: str,
+        security_type: FuchsiaSecurityType,
+        password: Optional[str] = None,
+    ) -> bool:
         """Save a network via the policy layer.
 
         Args:
@@ -290,7 +314,12 @@
             return False
         return True
 
-    def remove_network(self, ssid, security_type, password=None):
+    def remove_network(
+        self,
+        ssid: str,
+        security_type: FuchsiaSecurityType,
+        password: Optional[str] = None,
+    ) -> bool:
         """Remove a saved network via the policy layer.
 
         Args:
@@ -312,7 +341,7 @@
             return False
         return True
 
-    def remove_all_networks(self):
+    def remove_all_networks(self) -> bool:
         """Removes all saved networks from device.
 
         Returns:
@@ -326,7 +355,7 @@
             return False
         return True
 
-    def get_saved_networks(self):
+    def get_saved_networks(self) -> List[Any]:
         """Retrieves saved networks from device.
 
         Returns:
@@ -342,7 +371,9 @@
             )
         return saved_networks_response["result"]
 
-    def send_connect_command(self, ssid, security_type):
+    def send_connect_command(
+        self, ssid: str, security_type: FuchsiaSecurityType
+    ) -> bool:
         """Sends a connect command to a network that is already saved. This does
         not wait to guarantee the connection is successful (for that, use
         save_and_connect).
@@ -364,7 +395,9 @@
             return False
         return True
 
-    def wait_for_connect(self, ssid, security_type, timeout=30):
+    def wait_for_connect(
+        self, ssid: str, security_type: FuchsiaSecurityType, timeout: int = 30
+    ) -> bool:
         """Wait until the device has connected to the specified network.
         Args:
             ssid: string, the network name
@@ -373,7 +406,6 @@
         Returns:
             True if we see a connect to the network, False otherwise.
         """
-        security_type = str(security_type)
         # Wait until we've connected.
         end_time = time.time() + timeout
         while time.time() < end_time:
@@ -399,10 +431,9 @@
                 continue
 
             for network in update["result"]["networks"]:
-                if (
-                    network["id"]["ssid"] == ssid
-                    or network["id"]["type_"].lower() == security_type.lower()
-                ):
+                if network["id"]["ssid"] == ssid or network["id"][
+                    "type_"
+                ].lower() == str(security_type):
                     if "state" not in network:
                         raise WlanPolicyControllerError(
                             "WLAN status missing state field."
@@ -416,8 +447,13 @@
         return False
 
     def wait_for_disconnect(
-        self, ssid, security_type, state=None, status=None, timeout=30
-    ):
+        self,
+        ssid: str,
+        security_type: FuchsiaSecurityType,
+        state: Optional[str] = None,
+        status: Optional[str] = None,
+        timeout: int = 30,
+    ) -> bool:
         """Wait for a disconnect of the specified network on the given device. This
         will check that the correct connection state and disconnect status are
         given in update. If we do not see a disconnect after some time,
@@ -466,10 +502,9 @@
                 raise WlanPolicyControllerError("WLAN state update is missing network.")
 
             for network in update["result"]["networks"]:
-                if (
-                    network["id"]["ssid"] == ssid
-                    or network["id"]["type_"].lower() == security_type.lower()
-                ):
+                if network["id"]["ssid"] == ssid or network["id"][
+                    "type_"
+                ].lower() == str(security_type):
                     if "state" not in network or "status" not in network:
                         raise WlanPolicyControllerError(
                             "Client state summary's network is missing fields"
@@ -585,7 +620,7 @@
         self.log.info("Saved networks cleared and preserved.")
         return state
 
-    def restore_preserved_networks_and_client_state(self):
+    def restore_preserved_networks_and_client_state(self) -> None:
         """Restore saved networks and client state onto device if they have
         been preserved.
         """
diff --git a/packages/antlion/controllers/fuchsia_lib/wlan_ap_policy_lib.py b/packages/antlion/controllers/fuchsia_lib/wlan_ap_policy_lib.py
index 0f5f2c4..adae86a 100644
--- a/packages/antlion/controllers/fuchsia_lib/wlan_ap_policy_lib.py
+++ b/packages/antlion/controllers/fuchsia_lib/wlan_ap_policy_lib.py
@@ -14,7 +14,25 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from enum import unique
+from typing import Optional
+
+from antlion.controllers.ap_lib.hostapd_security import FuchsiaSecurityType
 from antlion.controllers.fuchsia_lib.base_lib import BaseLib
+from antlion.typing import StrEnum
+
+
+@unique
+class ConnectivityMode(StrEnum):
+    LOCAL_ONLY = "local_only"
+    UNRESTRICTED = "unrestricted"
+
+
+@unique
+class OperatingBand(StrEnum):
+    ANY = "any"
+    ONLY_2G = "only_2_4_ghz"
+    ONLY_5G = "only_5_ghz"
 
 
 class FuchsiaWlanApPolicyLib(BaseLib):
@@ -22,19 +40,21 @@
         super().__init__(addr, "wlan_ap_policy")
 
     def wlanStartAccessPoint(
-        self, target_ssid, security_type, target_pwd, connectivity_mode, operating_band
+        self,
+        target_ssid: str,
+        security_type: FuchsiaSecurityType,
+        target_pwd: Optional[str],
+        connectivity_mode: ConnectivityMode,
+        operating_band: OperatingBand,
     ):
         """Start an Access Point.
         Args:
             target_ssid: the network to attempt a connection to
-            security_type: the security protocol of the network. Possible inputs:
-                "none", "wep", "wpa", "wpa2", "wpa3"
-            target_pwd: (optional) credential being saved with the network. No password
-                        is equivalent to empty string.
-            connectivity_mode: the connectivity mode to use. Possible inputs:
-                "local_only", "unrestricted"
-            operating_band: The operating band to use. Possible inputs:
-                "any", "only_2_4_ghz", "only_5_ghz"
+            security_type: the security protocol of the network
+            target_pwd: Credential being saved with the network. None is equivalent to
+                empty string.
+            connectivity_mode: the connectivity mode to use
+            operating_band: The operating band to use
 
         Returns:
             boolean indicating if the action was successful
@@ -42,17 +62,21 @@
 
         test_cmd = "wlan_ap_policy.start_access_point"
 
+        # The SoftAP API uses "open" security instead of None and "" password
+        # instead of None.
         test_args = {
             "target_ssid": target_ssid,
-            "security_type": security_type.lower(),
-            "target_pwd": target_pwd,
-            "connectivity_mode": connectivity_mode,
-            "operating_band": operating_band,
+            "security_type": str(security_type),
+            "target_pwd": target_pwd or "",
+            "connectivity_mode": str(connectivity_mode),
+            "operating_band": str(operating_band),
         }
 
         return self.send_command(test_cmd, test_args)
 
-    def wlanStopAccessPoint(self, target_ssid, security_type, target_pwd=""):
+    def wlanStopAccessPoint(
+        self, target_ssid: str, security_type: FuchsiaSecurityType, target_pwd: str = ""
+    ):
         """Stops an active Access Point.
         Args:
             target_ssid: the network to attempt a connection to
@@ -68,7 +92,7 @@
 
         test_args = {
             "target_ssid": target_ssid,
-            "security_type": security_type.lower(),
+            "security_type": str(security_type),
             "target_pwd": target_pwd,
         }
 
diff --git a/packages/antlion/controllers/fuchsia_lib/wlan_policy_lib.py b/packages/antlion/controllers/fuchsia_lib/wlan_policy_lib.py
index 4e8c5af..b8aed9f 100644
--- a/packages/antlion/controllers/fuchsia_lib/wlan_policy_lib.py
+++ b/packages/antlion/controllers/fuchsia_lib/wlan_policy_lib.py
@@ -17,6 +17,9 @@
 #
 #   This class provides pipeline betweem python tests and WLAN policy facade.
 
+from typing import Optional
+
+from antlion.controllers.ap_lib.hostapd_security import FuchsiaSecurityType
 from antlion.controllers.fuchsia_lib.base_lib import BaseLib
 
 COMMAND_START_CLIENT_CONNECTIONS = "wlan_policy.start_client_connections"
@@ -61,7 +64,12 @@
 
         return self.send_command(test_cmd, {})
 
-    def wlanSaveNetwork(self, target_ssid, security_type, target_pwd=None):
+    def wlanSaveNetwork(
+        self,
+        target_ssid: str,
+        security_type: FuchsiaSecurityType,
+        target_pwd: Optional[str] = None,
+    ):
         """Saveds a network to the device for future connections
         Args:
             target_ssid: the network to attempt a connection to
@@ -77,13 +85,15 @@
         test_cmd = COMMAND_SAVE_NETWORK
         test_args = {
             "target_ssid": target_ssid,
-            "security_type": str(security_type).lower(),
+            "security_type": str(security_type),
             "target_pwd": target_pwd,
         }
 
         return self.send_command(test_cmd, test_args)
 
-    def wlanRemoveNetwork(self, target_ssid, security_type, target_pwd=None):
+    def wlanRemoveNetwork(
+        self, target_ssid, security_type: FuchsiaSecurityType, target_pwd=None
+    ):
         """Removes or "forgets" a network from saved networks
         Args:
             target_ssid: the network to attempt a connection to
@@ -96,7 +106,7 @@
         test_cmd = COMMAND_REMOVE_NETWORK
         test_args = {
             "target_ssid": target_ssid,
-            "security_type": str(security_type).lower(),
+            "security_type": str(security_type),
             "target_pwd": target_pwd,
         }
 
@@ -113,7 +123,7 @@
 
         return self.send_command(test_cmd, {})
 
-    def wlanConnect(self, target_ssid, security_type):
+    def wlanConnect(self, target_ssid: str, security_type: FuchsiaSecurityType):
         """Triggers connection to a network
             Args:
                 target_ssid: the network to attempt a connection to. Must have been previously
@@ -127,7 +137,7 @@
         test_cmd = COMMAND_CONNECT
         test_args = {
             "target_ssid": target_ssid,
-            "security_type": str(security_type).lower(),
+            "security_type": str(security_type),
         }
 
         return self.send_command(test_cmd, test_args)
diff --git a/packages/antlion/test_utils/abstract_devices/wlan_device.py b/packages/antlion/test_utils/abstract_devices/wlan_device.py
index 9386cdf..4240ca4 100644
--- a/packages/antlion/test_utils/abstract_devices/wlan_device.py
+++ b/packages/antlion/test_utils/abstract_devices/wlan_device.py
@@ -21,6 +21,7 @@
 
 from antlion.controllers import iperf_client
 from antlion.controllers.android_device import AndroidDevice
+from antlion.controllers.ap_lib.hostapd_security import SecurityMode
 from antlion.controllers.fuchsia_device import FuchsiaDevice
 from antlion.controllers.iperf_client import IPerfClientBase
 from antlion.controllers.pdu import PduDevice
@@ -57,7 +58,7 @@
         key_mgmt: Optional[str] = None,
         check_connectivity: bool = True,
         hidden: bool = False,
-        target_security: Optional[str] = None,
+        target_security: SecurityMode = SecurityMode.OPEN,
     ) -> bool:
         """Associate to a target network.
 
@@ -249,7 +250,7 @@
         key_mgmt: Optional[str] = None,
         check_connectivity: bool = True,
         hidden: bool = False,
-        target_security: Optional[str] = None,
+        target_security: SecurityMode = SecurityMode.OPEN,
     ) -> bool:
         network = {"SSID": target_ssid, "hiddenSSID": hidden}
         if target_pwd:
@@ -357,7 +358,7 @@
         key_mgmt: Optional[str] = None,
         check_connectivity: bool = True,
         hidden: bool = False,
-        target_security: Optional[str] = None,
+        target_security: SecurityMode = SecurityMode.OPEN,
     ) -> bool:
         if self.device.association_mechanism == "drivers":
             bss_scan_response = self.device.sl4f.wlan_lib.wlanScanForBSSInfo()
@@ -381,7 +382,9 @@
             return self.device.check_connect_response(connection_response)
         else:
             return self.device.wlan_policy_controller.save_and_connect(
-                target_ssid, target_security, password=target_pwd
+                target_ssid,
+                target_security.fuchsia_security_type(),
+                password=target_pwd,
             )
 
     def disconnect(self) -> None:
diff --git a/packages/antlion/test_utils/wifi/base_test.py b/packages/antlion/test_utils/wifi/base_test.py
index 6a4c5be..03ddb0b 100644
--- a/packages/antlion/test_utils/wifi/base_test.py
+++ b/packages/antlion/test_utils/wifi/base_test.py
@@ -51,7 +51,7 @@
 
 class Network(TypedDict):
     SSID: str
-    security: Optional[SecurityMode]
+    security: SecurityMode
     password: Optional[str]
     hiddenSSID: bool
     wepKeys: Optional[List[str]]
@@ -60,7 +60,7 @@
 
 class NetworkUpdate(TypedDict, total=False):
     SSID: str
-    security: Optional[SecurityMode]
+    security: SecurityMode
     password: Optional[str]
     hiddenSSID: bool
     wepKeys: Optional[List[str]]
@@ -337,7 +337,7 @@
         same_ssid: bool = False,
         ssid_length_2g: int = hostapd_constants.AP_SSID_LENGTH_2G,
         ssid_length_5g: int = hostapd_constants.AP_SSID_LENGTH_5G,
-        security_mode: Optional[SecurityMode] = None,
+        security_mode: SecurityMode = SecurityMode.OPEN,
     ) -> NetworkList:
         """Generates SSIDs for a open network using a random generator.
 
diff --git a/tests/wlan/compliance/RegulatoryComplianceTest.py b/tests/wlan/compliance/RegulatoryComplianceTest.py
index ace378c..751e531 100644
--- a/tests/wlan/compliance/RegulatoryComplianceTest.py
+++ b/tests/wlan/compliance/RegulatoryComplianceTest.py
@@ -15,14 +15,13 @@
 # limitations under the License.
 
 import logging
-from typing import List, NamedTuple, Optional
+from typing import List, NamedTuple
 
 from mobly import asserts, test_runner
 
 from antlion import utils
 from antlion.controllers.access_point import setup_ap
 from antlion.controllers.ap_lib import hostapd_constants
-from antlion.controllers.ap_lib.hostapd_security import Security
 from antlion.controllers.ap_lib.regulatory_channels import (
     COUNTRY_CHANNELS,
     TEST_CHANNELS,
@@ -125,14 +124,12 @@
         self,
         channel: int,
         channel_bandwidth: int,
-        security_profile: Optional[Security] = None,
     ) -> str:
         """Start network on AP with basic configuration.
 
         Args:
             channel: channel to use for network
             channel_bandwidth: channel bandwidth in mhz to use for network,
-            security_profile: security type to use or None if open
 
         Returns:
             SSID of the newly created and running network
@@ -146,7 +143,6 @@
                 access_point=self.access_point,
                 profile_name="whirlwind",
                 channel=channel,
-                security=security_profile,
                 force_wmm=True,
                 ssid=ssid,
                 vht_bandwidth=channel_bandwidth,
diff --git a/tests/wlan/compliance/VapeInteropTest.py b/tests/wlan/compliance/VapeInteropTest.py
index f5beffc..b4e698d 100644
--- a/tests/wlan/compliance/VapeInteropTest.py
+++ b/tests/wlan/compliance/VapeInteropTest.py
@@ -104,7 +104,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -131,7 +131,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -158,7 +158,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -185,7 +185,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -212,7 +212,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -239,7 +239,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -266,7 +266,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -293,7 +293,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -320,7 +320,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -347,7 +347,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -374,7 +374,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -401,7 +401,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -428,7 +428,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -455,7 +455,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -482,7 +482,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -509,7 +509,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -536,7 +536,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -563,7 +563,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -590,7 +590,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -617,7 +617,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -644,7 +644,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -671,7 +671,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -698,7 +698,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -725,7 +725,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -752,7 +752,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -779,7 +779,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -806,7 +806,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -833,7 +833,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -860,7 +860,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -887,7 +887,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
@@ -914,7 +914,7 @@
             self.dut.associate(
                 self.ssid,
                 target_pwd=self.password,
-                target_security=hostapd_constants.WPA2_STRING,
+                target_security=SecurityMode.WPA2,
             ),
             "Failed to connect.",
         )
diff --git a/tests/wlan/compliance/WlanPhyCompliance11ACTest.py b/tests/wlan/compliance/WlanPhyCompliance11ACTest.py
index b21ea14..b40b7c1 100644
--- a/tests/wlan/compliance/WlanPhyCompliance11ACTest.py
+++ b/tests/wlan/compliance/WlanPhyCompliance11ACTest.py
@@ -15,6 +15,8 @@
 # limitations under the License.
 
 import itertools
+from dataclasses import dataclass
+from typing import Any, List, Optional
 
 from mobly import asserts, test_runner
 from mobly.records import TestResultRecord
@@ -92,26 +94,16 @@
     wpa2_cipher=hostapd_constants.WPA2_DEFAULT_CIPER,
 )
 
-SECURITIES = [None, WPA2_SECURITY]
+SECURITIES: List[Security] = [Security(), WPA2_SECURITY]
 
 
-def generate_test_name(settings):
-    """Generates a test name string based on the ac_capabilities for
-    a test case.
-
-    Args:
-        settings: a dict with the test settings (bandwidth, security, ac_capabs)
-
-    Returns:
-        A string test case name
-    """
-    chbw = settings["chbw"]
-    sec = "wpa2" if settings["security"] else "open"
-    ret = []
-    for cap in hostapd_constants.AC_CAPABILITIES_MAPPING.keys():
-        if cap in settings["ac_capabilities"]:
-            ret.append(hostapd_constants.AC_CAPABILITIES_MAPPING[cap])
-    return f"test_11ac_{chbw}mhz_{sec}_{''.join(ret)}"
+@dataclass
+class TestParams:
+    security: Security
+    vht_bandwidth_mhz: int
+    # TODO(http://b/290396383): Type AP capabilities as enums
+    n_capabilities: List[Any]
+    ac_capabilities: List[Any]
 
 
 # 6912 test cases
@@ -127,11 +119,21 @@
         super().__init__(controllers)
 
     def setup_generated_tests(self):
-        test_args = (
+        test_args: List[TestParams] = (
             self._generate_20mhz_test_args()
             + self._generate_40mhz_test_args()
             + self._generate_80mhz_test_args()
         )
+
+        def generate_test_name(test: TestParams):
+            ret = []
+            for cap in hostapd_constants.AC_CAPABILITIES_MAPPING.keys():
+                if cap in test.ac_capabilities:
+                    ret.append(hostapd_constants.AC_CAPABILITIES_MAPPING[cap])
+            return (
+                f"test_11ac_{test.vht_bandwidth_mhz}mhz_{test.security}_{''.join(ret)}"
+            )
+
         self.generate_tests(
             test_logic=self.setup_and_connect,
             name_func=generate_test_name,
@@ -176,36 +178,30 @@
         super().on_fail(record)
         self.access_point.stop_all_aps()
 
-    def setup_and_connect(self, ap_settings):
-        """Uses ap_settings to set up ap and then attempts to associate a DUT.
+    def setup_and_connect(self, test: TestParams):
+        """Setup the AP and then attempt to associate a DUT.
 
         Args:
-            ap_settings: a dict containing test case settings, including
-                bandwidth, security, n_capabilities, and ac_capabilities
-
+            test: Test parameters
         """
         ssid = rand_ascii_str(20)
-        security = ap_settings["security"]
-        chbw = ap_settings["chbw"]
-        password = None
-        target_security = None
-        if security:
-            password = security.password
-            target_security = security.security_mode_string
-        n_capabilities = ap_settings["n_capabilities"]
-        ac_capabilities = ap_settings["ac_capabilities"]
+        password: Optional[str] = None
+        target_security = SecurityMode.OPEN
+        if test.security:
+            password = test.security.password
+            target_security = test.security.security_mode
 
         setup_ap(
             access_point=self.access_point,
             profile_name="whirlwind",
             mode=hostapd_constants.MODE_11AC_MIXED,
             channel=36,
-            n_capabilities=n_capabilities,
-            ac_capabilities=ac_capabilities,
+            n_capabilities=test.n_capabilities,
+            ac_capabilities=test.ac_capabilities,
             force_wmm=True,
             ssid=ssid,
-            security=security,
-            vht_bandwidth=chbw,
+            security=test.security,
+            vht_bandwidth=test.vht_bandwidth_mhz,
             password=password,
         )
         asserts.assert_true(
@@ -216,8 +212,8 @@
         )
 
     # 1728 tests
-    def _generate_20mhz_test_args(self):
-        test_args = []
+    def _generate_20mhz_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
 
         # 864 test cases for open security
         # 864 test cases for wpa2 security
@@ -231,24 +227,20 @@
             RX_ANTENNA,
             TX_ANTENNA,
         ):
-            security = combination[0]
-            ac_capabilities = combination[1:]
             test_args.append(
-                (
-                    {
-                        "chbw": 20,
-                        "security": security,
-                        "n_capabilities": N_CAPABS_20MHZ,
-                        "ac_capabilities": ac_capabilities,
-                    },
+                TestParams(
+                    vht_bandwidth_mhz=20,
+                    security=combination[0],
+                    n_capabilities=N_CAPABS_20MHZ,
+                    ac_capabilities=list(combination[1:]),
                 )
             )
 
         return test_args
 
     # 1728 tests
-    def _generate_40mhz_test_args(self):
-        test_args = []
+    def _generate_40mhz_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
 
         # 864 test cases for open security
         # 864 test cases for wpa2 security
@@ -262,24 +254,20 @@
             RX_ANTENNA,
             TX_ANTENNA,
         ):
-            security = combination[0]
-            ac_capabilities = combination[1:]
             test_args.append(
-                (
-                    {
-                        "chbw": 40,
-                        "security": security,
-                        "n_capabilities": N_CAPABS_40MHZ,
-                        "ac_capabilities": ac_capabilities,
-                    },
+                TestParams(
+                    vht_bandwidth_mhz=40,
+                    security=combination[0],
+                    n_capabilities=N_CAPABS_40MHZ,
+                    ac_capabilities=list(combination[1:]),
                 )
             )
 
         return test_args
 
     # 3456 tests
-    def _generate_80mhz_test_args(self):
-        test_args = []
+    def _generate_80mhz_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
 
         # 1728 test cases for open security
         # 1728 test cases for wpa2 security
@@ -294,16 +282,12 @@
             RX_ANTENNA,
             TX_ANTENNA,
         ):
-            security = combination[0]
-            ac_capabilities = combination[1:]
             test_args.append(
-                (
-                    {
-                        "chbw": 80,
-                        "security": security,
-                        "n_capabilities": N_CAPABS_40MHZ,
-                        "ac_capabilities": ac_capabilities,
-                    },
+                TestParams(
+                    vht_bandwidth_mhz=80,
+                    security=combination[0],
+                    n_capabilities=N_CAPABS_40MHZ,
+                    ac_capabilities=list(combination[1:]),
                 )
             )
         return test_args
diff --git a/tests/wlan/compliance/WlanPhyCompliance11NTest.py b/tests/wlan/compliance/WlanPhyCompliance11NTest.py
index e5ed3a4..0a58932 100644
--- a/tests/wlan/compliance/WlanPhyCompliance11NTest.py
+++ b/tests/wlan/compliance/WlanPhyCompliance11NTest.py
@@ -15,6 +15,8 @@
 # limitations under the License.
 
 import itertools
+from dataclasses import dataclass
+from typing import Any, List, Optional
 
 from mobly import asserts, test_runner
 from mobly.records import TestResultRecord
@@ -46,30 +48,14 @@
 SMPS = [hostapd_constants.N_CAPABILITY_SMPS_STATIC, ""]
 
 
-def generate_test_name(settings):
-    """Generates a string based on the n_capabilities for a test case
-
-    Args:
-        settings: A dictionary of hostapd constant n_capabilities.
-
-    Returns:
-        A string that represents a test case name.
-    """
-    ret = []
-    for cap in hostapd_constants.N_CAPABILITIES_MAPPING.keys():
-        if cap in settings["n_capabilities"]:
-            ret.append(hostapd_constants.N_CAPABILITIES_MAPPING[cap])
-    # '+' is used by Mobile Harness as special character, don't use it in test names
-    if settings["chbw"] == "HT40-":
-        chbw = "HT40Lower"
-    elif settings["chbw"] == "HT40+":
-        chbw = "HT40Upper"
-    else:
-        chbw = settings["chbw"]
-    return (
-        f"test_11n_{settings['frequency']}_{chbw}_{settings['security']}_"
-        f"{settings['n_mode']}_{''.join(ret)}"
-    )
+@dataclass
+class TestParams:
+    frequency: str
+    chbw: str
+    n_mode: str
+    security: SecurityMode
+    # TODO(http://b/290396383): Type AP capabilities as enums
+    n_capabilities: List[Any]
 
 
 class WlanPhyCompliance11NTest(base_test.WifiBaseTest):
@@ -84,7 +70,7 @@
         super().__init__(controllers)
 
     def setup_generated_tests(self):
-        test_args = (
+        test_args: List[TestParams] = (
             self._generate_24_HT20_test_args()
             + self._generate_24_HT40_lower_test_args()
             + self._generate_24_HT40_upper_test_args()
@@ -99,6 +85,20 @@
             + self._generate_5_HT40_upper_wpa2_test_args()
         )
 
+        def generate_test_name(test: TestParams):
+            ret = []
+            for cap in hostapd_constants.N_CAPABILITIES_MAPPING.keys():
+                if cap in test.n_capabilities:
+                    ret.append(hostapd_constants.N_CAPABILITIES_MAPPING[cap])
+            # '+' is used by Mobile Harness as special character, don't use it in test names
+            if test.chbw == "HT40-":
+                chbw = "HT40Lower"
+            elif test.chbw == "HT40+":
+                chbw = "HT40Upper"
+            else:
+                chbw = test.chbw
+            return f"test_11n_{test.frequency}_{chbw}_{test.security}_{test.n_mode}_{''.join(ret)}"
+
         self.generate_tests(
             test_logic=self.setup_and_connect,
             name_func=generate_test_name,
@@ -144,42 +144,40 @@
         super().on_fail(record)
         self.access_point.stop_all_aps()
 
-    def setup_and_connect(self, ap_settings):
-        """Generates a hostapd config, setups up the AP with that config, then
-           attempts to associate a DUT
+    def setup_and_connect(self, test: TestParams):
+        """Start hostapd and associate the DUT.
 
         Args:
                ap_settings: A dictionary of hostapd constant n_capabilities.
         """
         ssid = utils.rand_ascii_str(20)
-        security_profile = None
-        password = None
-        temp_n_capabilities = list(ap_settings["n_capabilities"])
+        security_profile = Security()
+        password: Optional[str] = None
         n_capabilities = []
-        for n_capability in temp_n_capabilities:
+        for n_capability in test.n_capabilities:
             if n_capability in hostapd_constants.N_CAPABILITIES_MAPPING.keys():
                 n_capabilities.append(n_capability)
 
-        if ap_settings["chbw"] == "HT20" or ap_settings["chbw"] == "HT40+":
-            if ap_settings["frequency"] == "2.4GHz":
+        if test.chbw == "HT20" or test.chbw == "HT40+":
+            if test.frequency == "2.4GHz":
                 channel = 1
-            elif ap_settings["frequency"] == "5GHz":
+            elif test.frequency == "5GHz":
                 channel = 36
             else:
-                raise ValueError(f"Invalid frequence: {ap_settings['frequency']}")
+                raise ValueError(f"Invalid frequence: {test.frequency}")
 
-        elif ap_settings["chbw"] == "HT40-":
-            if ap_settings["frequency"] == "2.4GHz":
+        elif test.chbw == "HT40-":
+            if test.frequency == "2.4GHz":
                 channel = 11
-            elif ap_settings["frequency"] == "5GHz":
+            elif test.frequency == "5GHz":
                 channel = 60
             else:
-                raise ValueError(f"Invalid frequency: {ap_settings['frequency']}")
+                raise ValueError(f"Invalid frequency: {test.frequency}")
 
         else:
-            raise ValueError(f"Invalid channel bandwidth: {ap_settings['chbw']}")
+            raise ValueError(f"Invalid channel bandwidth: {test.chbw}")
 
-        if ap_settings["chbw"] == "HT40-" or ap_settings["chbw"] == "HT40+":
+        if test.chbw == "HT40-" or test.chbw == "HT40+":
             if hostapd_config.ht40_plus_allowed(channel):
                 extended_channel = hostapd_constants.N_CAPABILITY_HT40_PLUS
             elif hostapd_config.ht40_minus_allowed(channel):
@@ -188,7 +186,7 @@
                 raise ValueError(f"Invalid channel: {channel}")
             n_capabilities.append(extended_channel)
 
-        if ap_settings["security"] == "wpa2":
+        if test.security is SecurityMode.WPA2:
             security_profile = Security(
                 security_mode=SecurityMode.WPA2,
                 password=generate_random_password(length=20),
@@ -196,20 +194,14 @@
                 wpa2_cipher="CCMP",
             )
             password = security_profile.password
-        target_security = (
-            hostapd_constants.SECURITY_STRING_TO_DEFAULT_TARGET_SECURITY.get(
-                ap_settings["security"], None
-            )
-        )
 
-        mode = ap_settings["n_mode"]
-        if mode not in N_MODE:
-            raise ValueError(f"Invalid n-mode: {ap_settings['n-mode']}")
+        if test.n_mode not in N_MODE:
+            raise ValueError(f"Invalid n-mode: {test.n_mode}")
 
         setup_ap(
             access_point=self.access_point,
             profile_name="whirlwind",
-            mode=mode,
+            mode=test.n_mode,
             channel=channel,
             n_capabilities=n_capabilities,
             ac_capabilities=[],
@@ -220,13 +212,15 @@
         )
         asserts.assert_true(
             self.dut.associate(
-                ssid, target_pwd=password, target_security=target_security
+                ssid,
+                target_pwd=password,
+                target_security=test.security,
             ),
             "Failed to connect.",
         )
 
-    def _generate_24_HT20_test_args(self):
-        test_args = []
+    def _generate_24_HT20_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
         for combination in itertools.product(
             FREQUENCY_24,
             CHANNEL_BANDWIDTH_20,
@@ -239,25 +233,19 @@
             MAX_AMPDU_7935,
             SMPS,
         ):
-            test_frequency = combination[0]
-            test_chbw = combination[1]
-            n_mode = combination[2]
-            n_capabilities = combination[3:]
             test_args.append(
-                (
-                    {
-                        "frequency": test_frequency,
-                        "chbw": test_chbw,
-                        "n_mode": n_mode,
-                        "security": SECURITY_OPEN,
-                        "n_capabilities": n_capabilities,
-                    },
+                TestParams(
+                    frequency=combination[0],
+                    chbw=combination[1],
+                    n_mode=combination[2],
+                    security=SecurityMode.OPEN,
+                    n_capabilities=list(combination[3:]),
                 )
             )
         return test_args
 
-    def _generate_24_HT40_lower_test_args(self):
-        test_args = []
+    def _generate_24_HT40_lower_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
         for combination in itertools.product(
             FREQUENCY_24,
             CHANNEL_BANDWIDTH_40_LOWER,
@@ -270,24 +258,19 @@
             SMPS,
             DSSS_CCK,
         ):
-            test_frequency = combination[0]
-            test_chbw = combination[1]
-            n_capabilities = combination[2:]
             test_args.append(
-                (
-                    {
-                        "frequency": test_frequency,
-                        "chbw": test_chbw,
-                        "n_mode": hostapd_constants.MODE_11N_MIXED,
-                        "security": SECURITY_OPEN,
-                        "n_capabilities": n_capabilities,
-                    },
+                TestParams(
+                    frequency=combination[0],
+                    chbw=combination[1],
+                    n_mode=hostapd_constants.MODE_11N_MIXED,
+                    security=SecurityMode.OPEN,
+                    n_capabilities=list(combination[2:]),
                 )
             )
         return test_args
 
-    def _generate_24_HT40_upper_test_args(self):
-        test_args = []
+    def _generate_24_HT40_upper_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
         for combination in itertools.product(
             FREQUENCY_24,
             CHANNEL_BANDWIDTH_40_UPPER,
@@ -300,24 +283,19 @@
             SMPS,
             DSSS_CCK,
         ):
-            test_frequency = combination[0]
-            test_chbw = combination[1]
-            n_capabilities = combination[2:]
             test_args.append(
-                (
-                    {
-                        "frequency": test_frequency,
-                        "chbw": test_chbw,
-                        "n_mode": hostapd_constants.MODE_11N_MIXED,
-                        "security": SECURITY_OPEN,
-                        "n_capabilities": n_capabilities,
-                    },
+                TestParams(
+                    frequency=combination[0],
+                    chbw=combination[1],
+                    n_mode=hostapd_constants.MODE_11N_MIXED,
+                    security=SecurityMode.OPEN,
+                    n_capabilities=list(combination[2:]),
                 )
             )
         return test_args
 
-    def _generate_5_HT20_test_args(self):
-        test_args = []
+    def _generate_5_HT20_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
         for combination in itertools.product(
             FREQUENCY_5,
             CHANNEL_BANDWIDTH_20,
@@ -329,24 +307,19 @@
             MAX_AMPDU_7935,
             SMPS,
         ):
-            test_frequency = combination[0]
-            test_chbw = combination[1]
-            n_capabilities = combination[2:]
             test_args.append(
-                (
-                    {
-                        "frequency": test_frequency,
-                        "chbw": test_chbw,
-                        "n_mode": hostapd_constants.MODE_11N_MIXED,
-                        "security": SECURITY_OPEN,
-                        "n_capabilities": n_capabilities,
-                    },
+                TestParams(
+                    frequency=combination[0],
+                    chbw=combination[1],
+                    n_mode=hostapd_constants.MODE_11N_MIXED,
+                    security=SecurityMode.OPEN,
+                    n_capabilities=list(combination[2:]),
                 )
             )
         return test_args
 
-    def _generate_5_HT40_lower_test_args(self):
-        test_args = []
+    def _generate_5_HT40_lower_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
         for combination in itertools.product(
             FREQUENCY_5,
             CHANNEL_BANDWIDTH_40_LOWER,
@@ -359,24 +332,19 @@
             SMPS,
             DSSS_CCK,
         ):
-            test_frequency = combination[0]
-            test_chbw = combination[1]
-            n_capabilities = combination[2:]
             test_args.append(
-                (
-                    {
-                        "frequency": test_frequency,
-                        "chbw": test_chbw,
-                        "n_mode": hostapd_constants.MODE_11N_MIXED,
-                        "security": SECURITY_OPEN,
-                        "n_capabilities": n_capabilities,
-                    },
+                TestParams(
+                    frequency=combination[0],
+                    chbw=combination[1],
+                    n_mode=hostapd_constants.MODE_11N_MIXED,
+                    security=SecurityMode.OPEN,
+                    n_capabilities=list(combination[2:]),
                 )
             )
         return test_args
 
-    def _generate_5_HT40_upper_test_args(self):
-        test_args = []
+    def _generate_5_HT40_upper_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
         for combination in itertools.product(
             FREQUENCY_5,
             CHANNEL_BANDWIDTH_40_UPPER,
@@ -390,25 +358,19 @@
             SMPS,
             DSSS_CCK,
         ):
-            test_frequency = combination[0]
-            test_chbw = combination[1]
-            n_mode = combination[2]
-            n_capabilities = combination[3:]
             test_args.append(
-                (
-                    {
-                        "frequency": test_frequency,
-                        "chbw": test_chbw,
-                        "n_mode": n_mode,
-                        "security": SECURITY_OPEN,
-                        "n_capabilities": n_capabilities,
-                    },
+                TestParams(
+                    frequency=combination[0],
+                    chbw=combination[1],
+                    n_mode=combination[2],
+                    security=SecurityMode.OPEN,
+                    n_capabilities=list(combination[3:]),
                 )
             )
         return test_args
 
-    def _generate_24_HT20_wpa2_test_args(self):
-        test_args = []
+    def _generate_24_HT20_wpa2_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
         for combination in itertools.product(
             FREQUENCY_24,
             CHANNEL_BANDWIDTH_20,
@@ -420,24 +382,19 @@
             MAX_AMPDU_7935,
             SMPS,
         ):
-            test_frequency = combination[0]
-            test_chbw = combination[1]
-            n_capabilities = combination[2:]
             test_args.append(
-                (
-                    {
-                        "frequency": test_frequency,
-                        "chbw": test_chbw,
-                        "n_mode": hostapd_constants.MODE_11N_MIXED,
-                        "security": SECURITY_WPA2,
-                        "n_capabilities": n_capabilities,
-                    },
+                TestParams(
+                    frequency=combination[0],
+                    chbw=combination[1],
+                    n_mode=hostapd_constants.MODE_11N_MIXED,
+                    security=SecurityMode.WPA2,
+                    n_capabilities=list(combination[2:]),
                 )
             )
         return test_args
 
-    def _generate_24_HT40_lower_wpa2_test_args(self):
-        test_args = []
+    def _generate_24_HT40_lower_wpa2_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
         for combination in itertools.product(
             FREQUENCY_24,
             CHANNEL_BANDWIDTH_40_LOWER,
@@ -450,24 +407,19 @@
             SMPS,
             DSSS_CCK,
         ):
-            test_frequency = combination[0]
-            test_chbw = combination[1]
-            n_capabilities = combination[2:]
             test_args.append(
-                (
-                    {
-                        "frequency": test_frequency,
-                        "chbw": test_chbw,
-                        "n_mode": hostapd_constants.MODE_11N_MIXED,
-                        "security": SECURITY_WPA2,
-                        "n_capabilities": n_capabilities,
-                    },
+                TestParams(
+                    frequency=combination[0],
+                    chbw=combination[1],
+                    n_mode=hostapd_constants.MODE_11N_MIXED,
+                    security=SecurityMode.WPA2,
+                    n_capabilities=list(combination[2:]),
                 )
             )
         return test_args
 
-    def _generate_24_HT40_upper_wpa2_test_args(self):
-        test_args = []
+    def _generate_24_HT40_upper_wpa2_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
         for combination in itertools.product(
             FREQUENCY_24,
             CHANNEL_BANDWIDTH_40_UPPER,
@@ -480,24 +432,19 @@
             SMPS,
             DSSS_CCK,
         ):
-            test_frequency = combination[0]
-            test_chbw = combination[1]
-            n_capabilities = combination[2:]
             test_args.append(
-                (
-                    {
-                        "frequency": test_frequency,
-                        "chbw": test_chbw,
-                        "n_mode": hostapd_constants.MODE_11N_MIXED,
-                        "security": SECURITY_WPA2,
-                        "n_capabilities": n_capabilities,
-                    },
+                TestParams(
+                    frequency=combination[0],
+                    chbw=combination[1],
+                    n_mode=hostapd_constants.MODE_11N_MIXED,
+                    security=SecurityMode.WPA2,
+                    n_capabilities=list(combination[2:]),
                 )
             )
         return test_args
 
-    def _generate_5_HT20_wpa2_test_args(self):
-        test_args = []
+    def _generate_5_HT20_wpa2_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
         for combination in itertools.product(
             FREQUENCY_5,
             CHANNEL_BANDWIDTH_20,
@@ -509,24 +456,19 @@
             MAX_AMPDU_7935,
             SMPS,
         ):
-            test_frequency = combination[0]
-            test_chbw = combination[1]
-            n_capabilities = combination[2:]
             test_args.append(
-                (
-                    {
-                        "frequency": test_frequency,
-                        "chbw": test_chbw,
-                        "n_mode": hostapd_constants.MODE_11N_MIXED,
-                        "security": SECURITY_WPA2,
-                        "n_capabilities": n_capabilities,
-                    },
+                TestParams(
+                    frequency=combination[0],
+                    chbw=combination[1],
+                    n_mode=hostapd_constants.MODE_11N_MIXED,
+                    security=SecurityMode.WPA2,
+                    n_capabilities=list(combination[2:]),
                 )
             )
         return test_args
 
-    def _generate_5_HT40_lower_wpa2_test_args(self):
-        test_args = []
+    def _generate_5_HT40_lower_wpa2_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
         for combination in itertools.product(
             FREQUENCY_5,
             CHANNEL_BANDWIDTH_40_LOWER,
@@ -539,24 +481,19 @@
             SMPS,
             DSSS_CCK,
         ):
-            test_frequency = combination[0]
-            test_chbw = combination[1]
-            n_capabilities = combination[2:]
             test_args.append(
-                (
-                    {
-                        "frequency": test_frequency,
-                        "chbw": test_chbw,
-                        "n_mode": hostapd_constants.MODE_11N_MIXED,
-                        "security": SECURITY_WPA2,
-                        "n_capabilities": n_capabilities,
-                    },
+                TestParams(
+                    frequency=combination[0],
+                    chbw=combination[1],
+                    n_mode=hostapd_constants.MODE_11N_MIXED,
+                    security=SecurityMode.WPA2,
+                    n_capabilities=list(combination[2:]),
                 )
             )
         return test_args
 
-    def _generate_5_HT40_upper_wpa2_test_args(self):
-        test_args = []
+    def _generate_5_HT40_upper_wpa2_test_args(self) -> List[TestParams]:
+        test_args: List[TestParams] = []
         for combination in itertools.product(
             FREQUENCY_5,
             CHANNEL_BANDWIDTH_40_UPPER,
@@ -569,18 +506,13 @@
             SMPS,
             DSSS_CCK,
         ):
-            test_frequency = combination[0]
-            test_chbw = combination[1]
-            n_capabilities = combination[2:]
             test_args.append(
-                (
-                    {
-                        "frequency": test_frequency,
-                        "chbw": test_chbw,
-                        "n_mode": hostapd_constants.MODE_11N_MIXED,
-                        "security": SECURITY_WPA2,
-                        "n_capabilities": n_capabilities,
-                    },
+                TestParams(
+                    frequency=combination[0],
+                    chbw=combination[1],
+                    n_mode=hostapd_constants.MODE_11N_MIXED,
+                    security=SecurityMode.WPA2,
+                    n_capabilities=list(combination[2:]),
                 )
             )
         return test_args
diff --git a/tests/wlan/compliance/WlanSecurityComplianceABGTest.py b/tests/wlan/compliance/WlanSecurityComplianceABGTest.py
index becec44..d4fc54b 100644
--- a/tests/wlan/compliance/WlanSecurityComplianceABGTest.py
+++ b/tests/wlan/compliance/WlanSecurityComplianceABGTest.py
@@ -152,11 +152,6 @@
                 password = utf8_password_2g
         else:
             password = generate_random_password()
-        target_security = (
-            hostapd_constants.SECURITY_STRING_TO_DEFAULT_TARGET_SECURITY.get(
-                security_mode_raw, None
-            )
-        )
 
         self.security_profile = Security(
             security_mode=security_mode,
@@ -165,7 +160,7 @@
             wpa2_cipher=wpa2_cipher,
         )
         self.client_password = password
-        self.target_security = target_security
+        self.target_security = security_mode
         self.ssid = utils.rand_ascii_str(SSID_LENGTH_DEFAULT)
         return test_func(self, *args, *kwargs)
 
@@ -197,7 +192,7 @@
         self.access_point = self.access_points[0]
 
         self.ssid: str
-        self.target_security: str
+        self.target_security: SecurityMode
         self.security_profile: Security
         self.client_password: str
 
diff --git a/tests/wlan/functional/ConnectionStressTest.py b/tests/wlan/functional/ConnectionStressTest.py
index e2d1036..d234578 100644
--- a/tests/wlan/functional/ConnectionStressTest.py
+++ b/tests/wlan/functional/ConnectionStressTest.py
@@ -20,24 +20,105 @@
 
 import logging
 import time
+from dataclasses import dataclass
+from typing import List, Optional
 
-from mobly import signals, test_runner
+from mobly import asserts, test_runner
 from mobly.records import TestResultRecord
 
 from antlion.controllers.access_point import setup_ap
-from antlion.controllers.ap_lib import hostapd_constants, hostapd_security
+from antlion.controllers.ap_lib.hostapd_constants import (
+    AP_DEFAULT_CHANNEL_2G,
+    AP_DEFAULT_CHANNEL_5G,
+)
+from antlion.controllers.ap_lib.hostapd_security import Security, SecurityMode
 from antlion.test_utils.abstract_devices.wlan_device import create_wlan_device
 from antlion.test_utils.wifi import base_test
 from antlion.utils import rand_ascii_str
 
 
+@dataclass
+class TestParams:
+    profile: str
+    channel: int
+    security_mode: SecurityMode
+    ap_ssid: str
+    ap_password: Optional[str]
+    dut_ssid: str
+    dut_password: Optional[str]
+    expect_associated: bool
+
+
 class ConnectionStressTest(base_test.WifiBaseTest):
     # Default number of test iterations here.
     # Override using parameter in config file.
     # Eg: "connection_stress_test_iterations": "50"
     num_of_iterations = 10
-    channel_2G = hostapd_constants.AP_DEFAULT_CHANNEL_2G
-    channel_5G = hostapd_constants.AP_DEFAULT_CHANNEL_5G
+
+    def pre_run(self):
+        tests: List[TestParams] = []
+
+        # Successful associate
+        for profile in ["whirlwind", "whirlwind_11ab_legacy", "whirlwind_11ag_legacy"]:
+            for channel in [AP_DEFAULT_CHANNEL_2G, AP_DEFAULT_CHANNEL_5G]:
+                ssid = rand_ascii_str(10)
+                tests.append(
+                    TestParams(
+                        profile=profile,
+                        channel=channel,
+                        security_mode=SecurityMode.OPEN,
+                        ap_ssid=ssid,
+                        ap_password=None,
+                        dut_ssid=ssid,
+                        dut_password=None,
+                        expect_associated=True,
+                    )
+                )
+
+        # Wrong SSID
+        for channel in [AP_DEFAULT_CHANNEL_2G, AP_DEFAULT_CHANNEL_5G]:
+            ssid = rand_ascii_str(10)
+            tests.append(
+                TestParams(
+                    profile="whirlwind",
+                    channel=channel,
+                    security_mode=SecurityMode.OPEN,
+                    ap_ssid=ssid,
+                    ap_password=None,
+                    dut_ssid=f"wrong_{ssid}",
+                    dut_password=None,
+                    expect_associated=False,
+                )
+            )
+
+        # Wrong password
+        for channel in [AP_DEFAULT_CHANNEL_2G, AP_DEFAULT_CHANNEL_5G]:
+            ssid = rand_ascii_str(10)
+            password = rand_ascii_str(20)
+            tests.append(
+                TestParams(
+                    profile="whirlwind",
+                    channel=channel,
+                    security_mode=SecurityMode.WPA2,
+                    ap_ssid=ssid,
+                    ap_password=password,
+                    dut_ssid=ssid,
+                    dut_password=f"wrong_{password}",
+                    expect_associated=False,
+                )
+            )
+
+        def test_name(test: TestParams) -> str:
+            channel = "2g" if test.channel == AP_DEFAULT_CHANNEL_2G else "5g"
+            if test.expect_associated:
+                return f"test_{test.profile}_{channel}"
+            if test.ap_ssid != test.dut_ssid:
+                return f"test_{test.profile}_{channel}_wrong_ssid"
+            if test.ap_password != test.dut_password:
+                return f"test_{test.profile}_{channel}_wrong_password"
+            raise TypeError(f"Unknown name for {test}")
+
+        self.generate_tests(self.connect_disconnect, test_name, tests)
 
     def setup_class(self):
         super().setup_class()
@@ -62,169 +143,44 @@
         super().on_fail(record)
         self.access_point.stop_all_aps()
 
-    def start_ap(self, profile, channel, security=None):
-        """Starts an Access Point
-
-        Args:
-            profile: Profile name such as 'whirlwind'
-            channel: Channel to operate on
-        """
-        self.log.info(f"Profile: {profile}, Channel: {channel}")
-        setup_ap(
-            access_point=self.access_point,
-            profile_name=profile,
-            channel=channel,
-            ssid=self.ssid,
-            security=security,
-        )
-
-    def connect_disconnect(
-        self, ap_config, ssid=None, password=None, negative_test=False
-    ):
+    def connect_disconnect(self, test: TestParams):
         """Helper to start an AP, connect DUT to it and disconnect
 
         Args:
-            ap_config: Dictionary contaning profile name and channel
+            ap_config: Dictionary containing profile name and channel
             ssid: ssid to connect to
             password: password for the ssid to connect to
         """
-        security_mode = ap_config.get("security_mode", None)
-        target_security = (
-            hostapd_constants.SECURITY_STRING_TO_DEFAULT_TARGET_SECURITY.get(
-                security_mode, None
-            )
+        setup_ap(
+            access_point=self.access_point,
+            profile_name=test.profile,
+            channel=test.channel,
+            ssid=test.ap_ssid,
+            security=Security(
+                security_mode=test.security_mode, password=test.ap_password
+            ),
         )
 
-        if security_mode:
-            security_profile = hostapd_security.Security(
-                security_mode=ap_config["security_mode"], password=ap_config["password"]
+        for iteration in range(0, self.num_of_iterations):
+            associated = self.dut.associate(
+                test.dut_ssid,
+                target_pwd=test.dut_password,
+                target_security=test.security_mode,
             )
-        else:
-            security_profile = None
+            asserts.assert_equal(
+                associated,
+                test.expect_associated,
+                (
+                    f"Attempt {iteration}/{self.num_of_iterations}: "
+                    f"associated={associated}, want {test.expect_associated}"
+                ),
+            )
 
-        # Start AP
-        self.start_ap(
-            ap_config["profile"], ap_config["channel"], security=security_profile
-        )
-
-        failed = False
-        # Connect and Disconnect several times
-        for x in range(0, self.num_of_iterations):
-            if not ssid:
-                ssid = self.ssid
-            if negative_test:
-                if not self.dut.associate(
-                    ssid, target_pwd=password, target_security=target_security
-                ):
-                    self.log.info(f"Attempt {x}. Did not associate as expected.")
-                else:
-                    self.log.error(
-                        "Attempt %d. Negative test successfully "
-                        "associated. Fail." % x
-                    )
-                    failed = True
-            else:
-                # Connect
-                if self.dut.associate(ssid, target_pwd=password):
-                    self.log.info(f"Attempt {x}. Successfully associated")
-                else:
-                    self.log.error(f"Attempt {x}. Failed to associate.")
-                    failed = True
-                # Disconnect
-                self.dut.disconnect()
+            self.dut.disconnect()
 
             # Wait a second before trying again
             time.sleep(1)
 
-        # Stop AP
-        self.access_point.stop_all_aps()
-        if failed:
-            raise signals.TestFailure("One or more association attempt failed.")
-
-    def test_whirlwind_2g(self):
-        self.connect_disconnect(
-            {"profile": "whirlwind", "channel": self.channel_2G, "security_mode": None}
-        )
-
-    def test_whirlwind_5g(self):
-        self.connect_disconnect(
-            {"profile": "whirlwind", "channel": self.channel_5G, "security_mode": None}
-        )
-
-    def test_whirlwind_11ab_2g(self):
-        self.connect_disconnect(
-            {
-                "profile": "whirlwind_11ab_legacy",
-                "channel": self.channel_2G,
-                "security_mode": None,
-            }
-        )
-
-    def test_whirlwind_11ab_5g(self):
-        self.connect_disconnect(
-            {
-                "profile": "whirlwind_11ab_legacy",
-                "channel": self.channel_5G,
-                "security_mode": None,
-            }
-        )
-
-    def test_whirlwind_11ag_2g(self):
-        self.connect_disconnect(
-            {
-                "profile": "whirlwind_11ag_legacy",
-                "channel": self.channel_2G,
-                "security_mode": None,
-            }
-        )
-
-    def test_whirlwind_11ag_5g(self):
-        self.connect_disconnect(
-            {
-                "profile": "whirlwind_11ag_legacy",
-                "channel": self.channel_5G,
-                "security_mode": None,
-            }
-        )
-
-    def test_wrong_ssid_whirlwind_2g(self):
-        self.connect_disconnect(
-            {"profile": "whirlwind", "channel": self.channel_2G, "security_mode": None},
-            ssid=rand_ascii_str(20),
-            negative_test=True,
-        )
-
-    def test_wrong_ssid_whirlwind_5g(self):
-        self.connect_disconnect(
-            {"profile": "whirlwind", "channel": self.channel_5G, "security_mode": None},
-            ssid=rand_ascii_str(20),
-            negative_test=True,
-        )
-
-    def test_wrong_password_whirlwind_2g(self):
-        self.connect_disconnect(
-            {
-                "profile": "whirlwind",
-                "channel": self.channel_2G,
-                "security_mode": hostapd_constants.WPA2_STRING,
-                "password": rand_ascii_str(10),
-            },
-            password=rand_ascii_str(20),
-            negative_test=True,
-        )
-
-    def test_wrong_password_whirlwind_5g(self):
-        self.connect_disconnect(
-            {
-                "profile": "whirlwind",
-                "channel": self.channel_5G,
-                "security_mode": hostapd_constants.WPA2_STRING,
-                "password": rand_ascii_str(10),
-            },
-            password=rand_ascii_str(20),
-            negative_test=True,
-        )
-
 
 if __name__ == "__main__":
     test_runner.main()
diff --git a/tests/wlan/functional/WlanTargetSecurityTest.py b/tests/wlan/functional/WlanTargetSecurityTest.py
index ffdccaa..52c8cf2 100644
--- a/tests/wlan/functional/WlanTargetSecurityTest.py
+++ b/tests/wlan/functional/WlanTargetSecurityTest.py
@@ -19,8 +19,11 @@
 
 from antlion import utils
 from antlion.controllers.access_point import setup_ap
-from antlion.controllers.ap_lib import hostapd_constants
-from antlion.controllers.ap_lib.hostapd_security import Security
+from antlion.controllers.ap_lib.hostapd_constants import (
+    AP_DEFAULT_CHANNEL_5G,
+    AP_SSID_LENGTH_5G,
+)
+from antlion.controllers.ap_lib.hostapd_security import Security, SecurityMode
 from antlion.test_utils.abstract_devices.wlan_device import create_wlan_device
 from antlion.test_utils.wifi import base_test
 
@@ -66,7 +69,7 @@
         self.access_point.stop_all_aps()
         super().on_fail(record)
 
-    def setup_ap(self, security_mode=None):
+    def setup_ap(self, security_mode: SecurityMode = SecurityMode.OPEN):
         """Sets up an AP using the provided security mode.
 
         Args:
@@ -76,18 +79,15 @@
                 security, since non-open target securities require a credential
                 to attempt a connection.
         """
-        ssid = utils.rand_ascii_str(hostapd_constants.AP_SSID_LENGTH_5G)
+        ssid = utils.rand_ascii_str(AP_SSID_LENGTH_5G)
         # Length 13, so it can be used for WEP or WPA
         password = utils.rand_ascii_str(13)
-        security_profile = None
-
-        if security_mode:
-            security_profile = Security(security_mode=security_mode, password=password)
+        security_profile = Security(security_mode=security_mode, password=password)
 
         setup_ap(
             access_point=self.access_point,
             profile_name="whirlwind",
-            channel=hostapd_constants.AP_DEFAULT_CHANNEL_5G,
+            channel=AP_DEFAULT_CHANNEL_5G,
             ssid=ssid,
             security=security_profile,
         )
@@ -103,7 +103,7 @@
         ssid, password = self.setup_ap()
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WEP_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WEP, target_pwd=password
             ),
             "Should not have associated.",
         )
@@ -112,7 +112,7 @@
         ssid, password = self.setup_ap()
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA, target_pwd=password
             ),
             "Should not have associated.",
         )
@@ -121,7 +121,7 @@
         ssid, password = self.setup_ap()
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA2_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA2, target_pwd=password
             ),
             "Should not have associated.",
         )
@@ -130,194 +130,194 @@
         ssid, password = self.setup_ap()
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA3_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA3, target_pwd=password
             ),
             "Should not have associated.",
         )
 
     # WEP Security on AP
     def test_reject_wep_ap_with_open_target_security(self):
-        ssid, _ = self.setup_ap(hostapd_constants.WEP_STRING)
+        ssid, _ = self.setup_ap(SecurityMode.WEP)
         asserts.assert_false(self.dut.associate(ssid), "Should not have associated.")
 
     def test_associate_wep_ap_with_wep_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WEP_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WEP)
         asserts.assert_true(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WEP_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WEP, target_pwd=password
             ),
             "Failed to associate.",
         )
 
     def test_reject_wep_ap_with_wpa_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WEP_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WEP)
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA, target_pwd=password
             ),
             "Should not have associated.",
         )
 
     def test_reject_wep_ap_with_wpa2_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WEP_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WEP)
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA2_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA2, target_pwd=password
             ),
             "Should not have associated.",
         )
 
     def test_reject_wep_ap_with_wpa3_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WEP_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WEP)
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA3_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA3, target_pwd=password
             ),
             "Should not have associated.",
         )
 
     # WPA Security on AP
     def test_reject_wpa_ap_with_open_target_security(self):
-        ssid, _ = self.setup_ap(hostapd_constants.WPA_STRING)
+        ssid, _ = self.setup_ap(SecurityMode.WPA)
         asserts.assert_false(self.dut.associate(ssid), "Should not have associated.")
 
     def test_reject_wpa_ap_with_wep_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA)
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WEP_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WEP, target_pwd=password
             ),
             "Should not have associated.",
         )
 
     def test_associate_wpa_ap_with_wpa_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA)
         asserts.assert_true(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA, target_pwd=password
             ),
             "Failed to associate.",
         )
 
     def test_reject_wpa_ap_with_wpa2_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA)
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA2_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA2, target_pwd=password
             ),
             "Should not have associated.",
         )
 
     def test_reject_wpa_ap_with_wpa3_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA)
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA3_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA3, target_pwd=password
             ),
             "Should not have associated.",
         )
 
     # WPA2 Security on AP
     def test_reject_wpa2_ap_with_open_target_security(self):
-        ssid, _ = self.setup_ap(hostapd_constants.WPA2_STRING)
+        ssid, _ = self.setup_ap(SecurityMode.WPA2)
         asserts.assert_false(self.dut.associate(ssid), "Should not have associated.")
 
     def test_reject_wpa2_ap_with_wep_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA2_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA2)
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WEP_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WEP, target_pwd=password
             ),
             "Should not have associated.",
         )
 
     def test_associate_wpa2_ap_with_wpa_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA2_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA2)
         asserts.assert_true(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA, target_pwd=password
             ),
             "Failed to associate.",
         )
 
     def test_associate_wpa2_ap_with_wpa2_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA2_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA2)
         asserts.assert_true(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA2_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA2, target_pwd=password
             ),
             "Failed to associate.",
         )
 
     def test_reject_wpa2_ap_with_wpa3_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA2_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA2)
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA3_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA3, target_pwd=password
             ),
             "Should not have associated.",
         )
 
     # WPA/WPA2 Security on AP
     def test_reject_wpa_wpa2_ap_with_open_target_security(self):
-        ssid, _ = self.setup_ap(hostapd_constants.WPA_MIXED_STRING)
+        ssid, _ = self.setup_ap(SecurityMode.WPA_WPA2)
         asserts.assert_false(self.dut.associate(ssid), "Should not have associated.")
 
     def test_reject_wpa_wpa2_ap_with_wep_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA_MIXED_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA_WPA2)
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WEP_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WEP, target_pwd=password
             ),
             "Should not have associated.",
         )
 
     def test_associate_wpa_wpa2_ap_with_wpa_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA_MIXED_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA_WPA2)
         asserts.assert_true(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA, target_pwd=password
             ),
             "Failed to associate.",
         )
 
     def test_associate_wpa_wpa2_ap_with_wpa2_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA_MIXED_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA_WPA2)
         asserts.assert_true(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA2_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA2, target_pwd=password
             ),
             "Failed to associate.",
         )
 
     def test_reject_wpa_wpa2_ap_with_wpa3_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA_MIXED_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA_WPA2)
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA3_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA3, target_pwd=password
             ),
             "Should not have associated.",
         )
 
     # WPA3 Security on AP
     def test_reject_wpa3_ap_with_open_target_security(self):
-        ssid, _ = self.setup_ap(hostapd_constants.WPA3_STRING)
+        ssid, _ = self.setup_ap(SecurityMode.WPA3)
         asserts.assert_false(self.dut.associate(ssid), "Should not have associated.")
 
     def test_reject_wpa3_ap_with_wep_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA3_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA3)
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WEP_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WEP, target_pwd=password
             ),
             "Should not have associated.",
         )
 
     def test_associate_wpa3_ap_with_wpa_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA3_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA3)
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA, target_pwd=password
             ),
             "Expected failure to associate. WPA credentials for WPA3 was "
             "temporarily disabled, see https://fxbug.dev/85817 for context. "
@@ -326,42 +326,42 @@
         )
 
     def test_associate_wpa3_ap_with_wpa2_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA3_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA3)
         asserts.assert_true(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA2_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA2, target_pwd=password
             ),
             "Failed to associate.",
         )
 
     def test_associate_wpa3_ap_with_wpa3_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA3_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA3)
         asserts.assert_true(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA3_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA3, target_pwd=password
             ),
             "Failed to associate.",
         )
 
     # WPA2/WPA3 Security on AP
     def test_reject_wpa2_wpa3_ap_with_open_target_security(self):
-        ssid, _ = self.setup_ap(hostapd_constants.WPA2_WPA3_MIXED_STRING)
+        ssid, _ = self.setup_ap(SecurityMode.WPA2_WPA3)
         asserts.assert_false(self.dut.associate(ssid), "Should not have associated.")
 
     def test_reject_wpa2_wpa3_ap_with_wep_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA2_WPA3_MIXED_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA2_WPA3)
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WEP_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WEP, target_pwd=password
             ),
             "Should not have associated.",
         )
 
     def test_associate_wpa2_wpa3_ap_with_wpa_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA2_WPA3_MIXED_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA2_WPA3)
         asserts.assert_false(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA, target_pwd=password
             ),
             "Expected failure to associate. WPA credentials for WPA3 was "
             "temporarily disabled, see https://fxbug.dev/85817 for context. "
@@ -370,19 +370,19 @@
         )
 
     def test_associate_wpa2_wpa3_ap_with_wpa2_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA2_WPA3_MIXED_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA2_WPA3)
         asserts.assert_true(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA2_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA2, target_pwd=password
             ),
             "Failed to associate.",
         )
 
     def test_associate_wpa2_wpa3_ap_with_wpa3_target_security(self):
-        ssid, password = self.setup_ap(hostapd_constants.WPA2_WPA3_MIXED_STRING)
+        ssid, password = self.setup_ap(SecurityMode.WPA2_WPA3)
         asserts.assert_true(
             self.dut.associate(
-                ssid, target_security=hostapd_constants.WPA3_STRING, target_pwd=password
+                ssid, target_security=SecurityMode.WPA3, target_pwd=password
             ),
             "Failed to associate.",
         )
diff --git a/tests/wlan/functional/reboot/WlanRebootApTest.py b/tests/wlan/functional/reboot/WlanRebootApTest.py
index 33269c6..11fcf3b 100644
--- a/tests/wlan/functional/reboot/WlanRebootApTest.py
+++ b/tests/wlan/functional/reboot/WlanRebootApTest.py
@@ -18,16 +18,11 @@
 from typing import List, Tuple
 
 import base_test
-from base_test import (
-    BandType,
-    DeviceType,
-    IpVersionType,
-    RebootType,
-    SecurityModeType,
-    TestParams,
-)
+from base_test import BandType, DeviceType, IpVersionType, RebootType, TestParams
 from mobly import test_runner
 
+from antlion.controllers.ap_lib.hostapd_security import SecurityMode
+
 
 class WlanRebootApTest(base_test.WlanRebootBaseTest):
     """Tests wlan reconnects when rebooting the AP in different scenarios.
@@ -55,7 +50,7 @@
         ) in itertools.product(
             RebootType.all(),
             BandType.all(),
-            SecurityModeType.all(),
+            SecurityMode.all(),
             IpVersionType.all(),
         ):
             settings = TestParams(
diff --git a/tests/wlan/functional/reboot/WlanRebootDutTest.py b/tests/wlan/functional/reboot/WlanRebootDutTest.py
index 7cdd018..2938f95 100644
--- a/tests/wlan/functional/reboot/WlanRebootDutTest.py
+++ b/tests/wlan/functional/reboot/WlanRebootDutTest.py
@@ -18,16 +18,11 @@
 from typing import List, Tuple
 
 import base_test
-from base_test import (
-    BandType,
-    DeviceType,
-    IpVersionType,
-    RebootType,
-    SecurityModeType,
-    TestParams,
-)
+from base_test import BandType, DeviceType, IpVersionType, RebootType, TestParams
 from mobly import test_runner
 
+from antlion.controllers.ap_lib.hostapd_security import SecurityMode
+
 
 class WlanRebootDutTest(base_test.WlanRebootBaseTest):
     """Tests wlan reconnects when rebooting the DUT in different scenarios.
@@ -55,7 +50,7 @@
         ) in itertools.product(
             RebootType.all(),
             BandType.all(),
-            SecurityModeType.all(),
+            SecurityMode.all(),
             IpVersionType.all(),
         ):
             settings = TestParams(
diff --git a/tests/wlan/functional/reboot/base_test.py b/tests/wlan/functional/reboot/base_test.py
index 8ce56b3..70d9c04 100644
--- a/tests/wlan/functional/reboot/base_test.py
+++ b/tests/wlan/functional/reboot/base_test.py
@@ -20,7 +20,7 @@
 from dataclasses import dataclass
 from enum import Enum, auto, unique
 from multiprocessing import Process
-from typing import Any, List, Optional
+from typing import List, Optional
 
 from mobly import asserts, signals
 
@@ -28,61 +28,35 @@
 from antlion.controllers import iperf_client, iperf_server
 from antlion.controllers.access_point import AccessPoint, setup_ap
 from antlion.controllers.ap_lib import hostapd_constants
-from antlion.controllers.ap_lib.hostapd_security import Security
+from antlion.controllers.ap_lib.hostapd_security import Security, SecurityMode
 from antlion.controllers.ap_lib.hostapd_utils import generate_random_password
 from antlion.controllers.fuchsia_device import FuchsiaDevice
 from antlion.net import wait_for_port
 from antlion.test_utils.abstract_devices.wlan_device import create_wlan_device
 from antlion.test_utils.wifi import base_test
+from antlion.typing import StrEnum
 
 DEFAULT_IPERF_TIMEOUT = 30
 DUT_NETWORK_CONNECTION_TIMEOUT = 60
 
 
 @unique
-class DeviceType(str, Enum):
+class DeviceType(StrEnum):
     AP = "ap"
     DUT = "dut"
 
-    @staticmethod
-    def all() -> List["DeviceType"]:
-        return [DeviceType.AP, DeviceType.DUT]
-
 
 @unique
-class RebootType(str, Enum):
+class RebootType(StrEnum):
     SOFT = "soft"
     HARD = "hard"
 
-    @staticmethod
-    def all() -> List["RebootType"]:
-        return [RebootType.SOFT, RebootType.HARD]
-
 
 @unique
-class BandType(str, Enum):
+class BandType(StrEnum):
     BAND_2G = "2g"
     BAND_5G = "5g"
 
-    @staticmethod
-    def all() -> List["BandType"]:
-        return [BandType.BAND_2G, BandType.BAND_5G]
-
-
-@unique
-class SecurityModeType(str, Enum):
-    OPEN_ENCRYPTION_STRING = ""
-    WPA2 = hostapd_constants.WPA2_STRING
-    WPA3 = hostapd_constants.WPA3_STRING
-
-    @staticmethod
-    def all() -> List["SecurityModeType"]:
-        return [
-            SecurityModeType.OPEN_ENCRYPTION_STRING,
-            SecurityModeType.WPA2,
-            SecurityModeType.WPA3,
-        ]
-
 
 @unique
 class IpVersionType(Enum):
@@ -118,7 +92,7 @@
     reboot_device: DeviceType
     reboot_type: RebootType
     band: BandType
-    security_mode: SecurityModeType
+    security_mode: SecurityMode
     ip_version: IpVersionType
 
 
@@ -131,9 +105,6 @@
     * One PduDevice
     """
 
-    def __init__(self, controllers: List[Any]) -> None:
-        super().__init__(controllers)
-
     def setup_class(self) -> None:
         super().setup_class()
         self.log = logging.getLogger()
@@ -194,8 +165,8 @@
         ssid: str,
         band: BandType,
         ip_version: IpVersionType,
-        security_mode: str = "",
-        password: Optional[str] = "",
+        security_mode: SecurityMode,
+        password: Optional[str] = None,
     ) -> None:
         """Setup ap with basic config.
 
@@ -207,9 +178,7 @@
             password: The PSK or passphase.
         """
         # TODO(fxb/63719): Add varying AP parameters
-        security_profile = None
-        if security_mode:
-            security_profile = Security(security_mode=security_mode, password=password)
+        security_profile = Security(security_mode=security_mode, password=password)
         channel: int
 
         # TODO(http://b/261746355): Replace with PEP 636 match statement
@@ -516,9 +485,9 @@
         reboot_type: RebootType = settings.reboot_type
         band: BandType = settings.band
         ip_version: IpVersionType = settings.ip_version
-        security_mode: SecurityModeType = settings.security_mode
-        password: str = ""
-        if security_mode is not SecurityModeType.OPEN_ENCRYPTION_STRING:
+        security_mode: SecurityMode = settings.security_mode
+        password: Optional[str] = None
+        if security_mode is not SecurityMode.OPEN:
             password = generate_random_password(security_mode=security_mode)
 
         # Skip hard reboots if no PDU present
@@ -537,9 +506,7 @@
 
         if not self.dut.associate(
             self.ssid,
-            target_security=hostapd_constants.SECURITY_STRING_TO_DEFAULT_TARGET_SECURITY.get(
-                security_mode
-            ),
+            target_security=security_mode,
             target_pwd=password,
         ):
             raise EnvironmentError("Initial network connection failed.")
diff --git a/tests/wlan/misc/WlanMiscScenarioTest.py b/tests/wlan/misc/WlanMiscScenarioTest.py
index 93f6fa3..a5327c8 100644
--- a/tests/wlan/misc/WlanMiscScenarioTest.py
+++ b/tests/wlan/misc/WlanMiscScenarioTest.py
@@ -80,14 +80,14 @@
             ssid=wpa3_ssid,
             security=Security(
                 security_mode=SecurityMode.WPA3,
-                password=generate_random_password("wpa3"),
+                password=generate_random_password(SecurityMode.WPA3),
             ),
         )
         # Attempt to associate with wrong password, expecting failure
         self.log.info("Attempting to associate WPA3 with wrong password.")
         asserts.assert_false(
             self.dut.associate(
-                wpa3_ssid, target_pwd="wrongpass", target_security="wpa3"
+                wpa3_ssid, target_pwd="wrongpass", target_security=SecurityMode.WPA3
             ),
             "Associated with WPA3 network using the wrong password",
         )
@@ -96,7 +96,7 @@
 
         # Setup a WPA2 Network
         wpa2_ssid = utils.rand_ascii_str(hostapd_constants.AP_SSID_LENGTH_5G)
-        wpa2_password = generate_random_password("wpa2")
+        wpa2_password = generate_random_password(SecurityMode.WPA2)
         setup_ap(
             access_point=self.access_point,
             profile_name="whirlwind",
@@ -109,7 +109,7 @@
         self.log.info("Attempting to associate with WPA2 network.")
         asserts.assert_true(
             self.dut.associate(
-                wpa2_ssid, target_pwd=wpa2_password, target_security="wpa2"
+                wpa2_ssid, target_pwd=wpa2_password, target_security=SecurityMode.WPA2
             ),
             "Failed to associate with WPA2 network after a WPA3 rejection.",
         )
diff --git a/tests/wlan/performance/ChannelSweepTest.py b/tests/wlan/performance/ChannelSweepTest.py
index 19e9723..5173c11 100644
--- a/tests/wlan/performance/ChannelSweepTest.py
+++ b/tests/wlan/performance/ChannelSweepTest.py
@@ -52,7 +52,7 @@
     country_code: str
     """Country code for the DUT to set before running the test."""
 
-    security_mode: Optional[SecurityMode]
+    security_mode: SecurityMode
     """Security type of the network to create. None represents an open network."""
 
     channel: int
@@ -75,7 +75,7 @@
 @dataclass
 class ThroughputKey:
     country_code: str
-    security_mode: Optional[SecurityMode]
+    security_mode: SecurityMode
     channel_bandwidth: int
 
     @staticmethod
@@ -116,8 +116,7 @@
         tests: List[Tuple[TestParams]] = []
 
         def generate_test_name(test: TestParams):
-            security = test.security_mode if test.security_mode else "open"
-            return f"test_{test.country_code}_{security}_channel_{test.channel}_{test.channel_bandwidth}mhz"
+            return f"test_{test.country_code}_{test.security_mode}_channel_{test.channel}_{test.channel_bandwidth}mhz"
 
         def test_params(test_name):
             return self.user_params.get("channel_sweep_test_params", {}).get(
@@ -126,7 +125,7 @@
 
         for country_channels in [COUNTRY_CHANNELS["United States of America"]]:
             for security_mode in [
-                None,
+                SecurityMode.OPEN,
                 SecurityMode.WEP,
                 SecurityMode.WPA,
                 SecurityMode.WPA2,
@@ -237,7 +236,7 @@
         self,
         channel: int,
         channel_bandwidth: int,
-        security_profile: Optional[Security] = None,
+        security_profile: Security,
     ) -> str:
         """Start network on AP with basic configuration.
 
@@ -575,19 +574,18 @@
         """
         self.fuchsia_device.wlan_policy_controller.set_country_code(test.country_code)
 
-        if test.security_mode:
-            if test.security_mode == SecurityMode.WEP:
+        if test.security_mode is not SecurityMode.OPEN:
+            if test.security_mode is SecurityMode.WEP:
                 password = utils.rand_hex_str(WEP_HEX_STRING_LENGTH)
             else:
                 password = utils.rand_ascii_str(hostapd_constants.MIN_WPA_PSK_LENGTH)
             security_profile = Security(
                 security_mode=test.security_mode, password=password
             )
-            target_security = test.security_mode.default_target_security()
+            target_security = test.security_mode
         else:
             password = None
-            security_profile = None
-            target_security = None
+            security_profile = Security()
 
         ssid = self.setup_ap(test.channel, test.channel_bandwidth, security_profile)
         associated = self.dut.associate(
diff --git a/tests/wlan_policy/HiddenNetworksTest.py b/tests/wlan_policy/HiddenNetworksTest.py
index ae57da3..b0f0576 100644
--- a/tests/wlan_policy/HiddenNetworksTest.py
+++ b/tests/wlan_policy/HiddenNetworksTest.py
@@ -20,7 +20,8 @@
 from mobly import signals, test_runner
 
 from antlion.controllers.access_point import setup_ap
-from antlion.controllers.ap_lib import hostapd_constants, hostapd_security
+from antlion.controllers.ap_lib import hostapd_constants
+from antlion.controllers.ap_lib.hostapd_security import Security, SecurityMode
 from antlion.test_utils.wifi import base_test
 from antlion.utils import rand_ascii_str
 
@@ -47,9 +48,9 @@
         self.hidden_ssid = rand_ascii_str(hostapd_constants.AP_SSID_LENGTH_2G)
         self.access_point = self.access_points[0]
         self.hidden_password = rand_ascii_str(hostapd_constants.AP_PASSPHRASE_LENGTH_2G)
-        self.hidden_security = hostapd_security.SecurityMode.WPA2.value
-        security = hostapd_security.Security(
-            security_mode=hostapd_security.SecurityMode.WPA2,
+        self.hidden_security = SecurityMode.WPA2.fuchsia_security_type()
+        security = Security(
+            security_mode=SecurityMode.WPA2,
             password=self.hidden_password,
         )
 
diff --git a/tests/wlan_policy/SavedNetworksTest.py b/tests/wlan_policy/SavedNetworksTest.py
index 9127f53..5d807c3 100644
--- a/tests/wlan_policy/SavedNetworksTest.py
+++ b/tests/wlan_policy/SavedNetworksTest.py
@@ -19,11 +19,17 @@
 """
 
 import logging
+from typing import Optional
 
 from mobly import signals, test_runner
 
 from antlion.controllers.access_point import setup_ap
-from antlion.controllers.ap_lib import hostapd_constants, hostapd_security
+from antlion.controllers.ap_lib import hostapd_constants
+from antlion.controllers.ap_lib.hostapd_security import (
+    FuchsiaSecurityType,
+    Security,
+    SecurityMode,
+)
 from antlion.test_utils.wifi import base_test
 from antlion.utils import rand_ascii_str, rand_hex_str
 
@@ -182,23 +188,18 @@
                 fd, ssid, security_type, self.credentialType(password), password
             )
 
-    def start_ap(self, ssid, security_type, password=None, hidden=False):
+    def start_ap(
+        self, ssid: str, security_type: SecurityMode, password: Optional[str] = None
+    ):
         """Starts an access point.
         Args:
             ssid: the SSID of the network to broadcast
-            security_type: the security type of the network to be broadcasted. This can be
-                None, "wep" "wpa", "wpa2", or "wpa3" (or from hostapd_constants.py)
+            security_type: the security type of the network to be broadcasted
             password: the password to connect to the broadcasted network. The password is ignored
                 if security type is none.
         """
-        # Put together the security configuration of the network to be
-        # broadcasted. Open networks are represented by no security.
-        if security_type == None or security_type.upper() == SECURITY_NONE:
-            security = None
-        else:
-            security = hostapd_security.Security(
-                security_mode=security_type, password=password
-            )
+        # Put together the security configuration of the network to be broadcasted.
+        security = Security(security_mode=security_type, password=password)
 
         if len(self.access_points) > 0:
             # Create an AP with default values other than the specified values.
@@ -279,7 +280,7 @@
         password = rand_ascii_str(10)
         for fd in self.fuchsia_devices:
             if not fd.wlan_policy_controller.save_network(
-                ssid, security, password=password
+                ssid, FuchsiaSecurityType.WPA2, password=password
             ):
                 raise signals.TestFailure("Failed to save network")
             # Reboot the device. The network should be persistently saved
@@ -293,23 +294,25 @@
             ssid = rand_ascii_str(19)
             password = rand_ascii_str(12)
             if not fd.wlan_policy_controller.save_network(
-                ssid, WPA2, password=password
+                ssid, FuchsiaSecurityType.WPA2, password=password
             ):
                 raise signals.TestFailure("Failed to save network")
             saved_networks.append(
                 {
                     "ssid": ssid,
-                    "security_type": WPA2,
+                    "security_type": FuchsiaSecurityType.WPA2.value,
                     "credential_type": PASSWORD,
                     "credential_value": password,
                 }
             )
-            if not fd.wlan_policy_controller.save_network(ssid, SECURITY_NONE):
+            if not fd.wlan_policy_controller.save_network(
+                ssid, FuchsiaSecurityType.NONE
+            ):
                 raise signals.TestFailure("Failed to save network")
             saved_networks.append(
                 {
                     "ssid": ssid,
-                    "security_type": SECURITY_NONE,
+                    "security_type": FuchsiaSecurityType.NONE.value,
                     "credential_type": CREDENTIAL_TYPE_NONE,
                     "credential_value": CREDENTIAL_VALUE_NONE,
                 }
@@ -325,14 +328,16 @@
         # wpa2 network in the test config. Remove all other networks first so
         # that we can't auto connect to them
         ssid = rand_ascii_str(10)
-        security = WPA2
+        security = SecurityMode.WPA2
         password = rand_ascii_str(10)
         self.start_ap(ssid, security, password)
 
         for fd in self.fuchsia_devices:
             fd.wlan_policy_controller.wait_for_no_connections()
 
-            if not fd.wlan_policy_controller.save_and_connect(ssid, security, password):
+            if not fd.wlan_policy_controller.save_and_connect(
+                ssid, security.fuchsia_security_type(), password
+            ):
                 raise signals.TestFailure("Failed to saved and connect to network")
 
             if (
@@ -343,26 +348,26 @@
     def test_auto_connect_open(self):
         # Start up AP with an open network with a random SSID
         ssid = rand_ascii_str(10)
-        self.start_ap(ssid, None)
+        security = SecurityMode.OPEN
+        self.start_ap(ssid, security)
         for fd in self.fuchsia_devices:
             fd.wlan_policy_controller.wait_for_no_connections()
 
             # Save the network and make sure that we see the device auto connect to it.
-            security = SECURITY_NONE
             password = CREDENTIAL_VALUE_NONE
             if not fd.wlan_policy_controller.save_network(
-                ssid, security, password=password
+                ssid, security.fuchsia_security_type(), password=password
             ):
                 raise signals.TestFailure("Failed to save network")
             if not fd.wlan_policy_controller.wait_for_connect(
-                ssid, security, timeout=TIME_WAIT_FOR_CONNECT
+                ssid, security.fuchsia_security_type(), timeout=TIME_WAIT_FOR_CONNECT
             ):
                 raise signals.TestFailure("Failed to connect to network")
 
     def test_auto_connect_wpa3(self):
         # Start up AP with an open network with a random SSID
         ssid = rand_ascii_str(10)
-        security = WPA3
+        security = SecurityMode.WPA3
         password = rand_ascii_str(10)
         self.start_ap(ssid, security, password)
         for fd in self.fuchsia_devices:
@@ -370,11 +375,11 @@
 
             # Save the network and make sure that we see the device auto connect to it.
             if not fd.wlan_policy_controller.save_network(
-                ssid, security, password=password
+                ssid, security.fuchsia_security_type(), password=password
             ):
                 raise signals.TestFailure("Failed to save network")
             if not fd.wlan_policy_controller.wait_for_connect(
-                ssid, security, timeout=TIME_WAIT_FOR_CONNECT
+                ssid, security.fuchsia_security_type(), timeout=TIME_WAIT_FOR_CONNECT
             ):
                 raise signals.TestFailure("Failed to connect to network")
 
diff --git a/tests/wlan_policy/StartStopClientConnectionsTest.py b/tests/wlan_policy/StartStopClientConnectionsTest.py
index 2df2000..f62961a 100644
--- a/tests/wlan_policy/StartStopClientConnectionsTest.py
+++ b/tests/wlan_policy/StartStopClientConnectionsTest.py
@@ -47,7 +47,7 @@
         self.ssid = rand_ascii_str(hostapd_constants.AP_SSID_LENGTH_2G)
         self.access_point = self.access_points[0]
         self.password = rand_ascii_str(hostapd_constants.AP_PASSPHRASE_LENGTH_2G)
-        self.security_type = hostapd_security.SecurityMode.WPA2.value
+        self.security_type = hostapd_security.SecurityMode.WPA2.fuchsia_security_type()
         security = hostapd_security.Security(
             security_mode=hostapd_security.SecurityMode.WPA2, password=self.password
         )