From 3b2b4cde7b63625b6aab827f5cc51a66ef73abac Mon Sep 17 00:00:00 2001 From: Andrew Beltrano Date: Wed, 24 Jan 2024 16:37:25 +0000 Subject: [PATCH 1/3] Add akm suites vector to wiphy. --- src/linux/libnl-helpers/Netlink80211Wiphy.cxx | 8 ++++++-- .../microsoft/net/netlink/nl80211/Netlink80211Wiphy.hxx | 5 ++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/linux/libnl-helpers/Netlink80211Wiphy.cxx b/src/linux/libnl-helpers/Netlink80211Wiphy.cxx index 749e2105..4d64d518 100644 --- a/src/linux/libnl-helpers/Netlink80211Wiphy.cxx +++ b/src/linux/libnl-helpers/Netlink80211Wiphy.cxx @@ -17,9 +17,10 @@ using namespace Microsoft::Net::Netlink::Nl80211; -Nl80211Wiphy::Nl80211Wiphy(uint32_t index, std::string_view name, std::vector cipherSuites, std::unordered_map bands, std::vector supportedInterfaceTypes, bool supportsRoaming) noexcept : +Nl80211Wiphy::Nl80211Wiphy(uint32_t index, std::string_view name, std::vector akmSuites, std::vector cipherSuites, std::unordered_map bands, std::vector supportedInterfaceTypes, bool supportsRoaming) noexcept : Index(index), Name(name), + AkmSuites(std::move(akmSuites)), CipherSuites(std::move(cipherSuites)), Bands(std::move(bands)), SupportedInterfaceTypes(std::move(supportedInterfaceTypes)), @@ -191,6 +192,9 @@ Nl80211Wiphy::Parse(struct nl_msg *nl80211Message) noexcept } } + // Process akm suites. + std::vector akmSuites{}; + // Process cipher suites. uint32_t *wiphyCipherSuites; auto wiphyNumCipherSuites = static_cast(nla_len(wiphyAttributes[NL80211_ATTR_CIPHER_SUITES])) / sizeof(*wiphyCipherSuites); @@ -212,7 +216,7 @@ Nl80211Wiphy::Parse(struct nl_msg *nl80211Message) noexcept // Process roaming support. auto wiphySupportsRoaming = wiphyAttributes[NL80211_ATTR_ROAM_SUPPORT] != nullptr; - Nl80211Wiphy nl80211Wiphy{ wiphyIndex, wiphyName, std::move(cipherSuites), std::move(wiphyBandMap), std::move(supportedInterfaceTypes), wiphySupportsRoaming }; + Nl80211Wiphy nl80211Wiphy{ wiphyIndex, wiphyName, std::move(akmSuites), std::move(cipherSuites), std::move(wiphyBandMap), std::move(supportedInterfaceTypes), wiphySupportsRoaming }; return nl80211Wiphy; } diff --git a/src/linux/libnl-helpers/include/microsoft/net/netlink/nl80211/Netlink80211Wiphy.hxx b/src/linux/libnl-helpers/include/microsoft/net/netlink/nl80211/Netlink80211Wiphy.hxx index 403ce6f4..9610b739 100644 --- a/src/linux/libnl-helpers/include/microsoft/net/netlink/nl80211/Netlink80211Wiphy.hxx +++ b/src/linux/libnl-helpers/include/microsoft/net/netlink/nl80211/Netlink80211Wiphy.hxx @@ -26,6 +26,9 @@ struct Nl80211Wiphy { uint32_t Index; std::string Name; + // TODO: Add parsing for AKM suites via NL80211_ATTR_AKM_SUITES (count), NL80211_ATTR_IFTYPE_AKM_SUITES, + // NL80211_IFTYPE_AKM_ATTR_IFTYPES, NL80211_IFTYPE_AKM_ATTR_SUITES. + std::vector AkmSuites; std::vector CipherSuites; std::unordered_map Bands; std::vector SupportedInterfaceTypes; @@ -75,7 +78,7 @@ private: * @param index The wiphy index. * @param name The wiphy name. */ - Nl80211Wiphy(uint32_t index, std::string_view name, std::vector cipherSuites, std::unordered_map bands, std::vector supportedInterfaceTypes, bool supportsRoaming) noexcept; + Nl80211Wiphy(uint32_t index, std::string_view name, std::vector akmSuites, std::vector cipherSuites, std::unordered_map bands, std::vector supportedInterfaceTypes, bool supportsRoaming) noexcept; /** * @brief Creates a new Nl80211Wiphy object, using the specified function to add an identifier to the message, From 72216fa468c80b877dc68dc5f0c3dc779d0df9dc Mon Sep 17 00:00:00 2001 From: Andrew Beltrano Date: Wed, 24 Jan 2024 16:58:58 +0000 Subject: [PATCH 2/3] Update capabilities to expose AKM suites instead of auth algorithms. --- protocol/protos/WifiCore.proto | 2 +- src/common/service/NetRemoteService.cxx | 10 +++++----- src/common/tools/cli/NetRemoteCliHandlerOperations.cxx | 10 ++++++---- .../net/wifi/Ieee80211AccessPointCapabilities.hxx | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/protocol/protos/WifiCore.proto b/protocol/protos/WifiCore.proto index 35c9ce1a..3aa62171 100644 --- a/protocol/protos/WifiCore.proto +++ b/protocol/protos/WifiCore.proto @@ -149,7 +149,7 @@ message Dot11AccessPointCapabilities { repeated Microsoft.Net.Wifi.Dot11FrequencyBand Bands = 1; repeated Microsoft.Net.Wifi.Dot11PhyType PhyTypes = 2; - repeated Microsoft.Net.Wifi.Dot11AuthenticationAlgorithm AuthenticationAlgorithms = 3; + repeated Microsoft.Net.Wifi.Dot11AkmSuite AkmSuites = 3; repeated Microsoft.Net.Wifi.Dot11CipherSuite CipherSuites = 4; } diff --git a/src/common/service/NetRemoteService.cxx b/src/common/service/NetRemoteService.cxx index b95a77de..f4b209bf 100644 --- a/src/common/service/NetRemoteService.cxx +++ b/src/common/service/NetRemoteService.cxx @@ -226,12 +226,12 @@ IeeeAccessPointCapabilitiesToNetRemoteAccessPointCapabilities(const Microsoft::N std::make_move_iterator(std::end(bands)) }; - std::vector authenticationAlgorithms(std::size(ieeeCapabilities.AuthenticationAlgorithms)); - std::ranges::transform(ieeeCapabilities.AuthenticationAlgorithms, std::begin(authenticationAlgorithms), IeeeAuthenticationAlgorithmToNetRemoteAuthenticationAlgorithm); + std::vector akmSuites(std::size(ieeeCapabilities.AkmSuites)); + std::ranges::transform(ieeeCapabilities.AkmSuites, std::begin(akmSuites), Ieee80211AkmSuiteToNetRemoteAkm); - *capabilities.mutable_authenticationalgorithms() = { - std::make_move_iterator(std::begin(authenticationAlgorithms)), - std::make_move_iterator(std::end(authenticationAlgorithms)) + *capabilities.mutable_akmsuites() = { + std::make_move_iterator(std::begin(akmSuites)), + std::make_move_iterator(std::end(akmSuites)) }; std::vector cipherSuites(std::size(ieeeCapabilities.CipherSuites)); diff --git a/src/common/tools/cli/NetRemoteCliHandlerOperations.cxx b/src/common/tools/cli/NetRemoteCliHandlerOperations.cxx index 802301a6..6acf86db 100644 --- a/src/common/tools/cli/NetRemoteCliHandlerOperations.cxx +++ b/src/common/tools/cli/NetRemoteCliHandlerOperations.cxx @@ -60,13 +60,15 @@ NetRemoteAccessPointCapabilitiesToString(const Microsoft::Net::Wifi::Dot11Access << indent1 << bandName; } + constexpr auto AkmSuitePrefixLength = std::size(std::string_view("Dot11AuthenticationAlgorithm")); ss << '\n' << indent0 - << "Authentication Algorithms:"; - for (const auto& authenticationAlgorithm : accessPointCapabilities.authenticationalgorithms()) { + << "Authentication and Key Management (AKM) Suites:"; + for (const auto& akmSuite : accessPointCapabilities.akmsuites()) { + std::string_view akmSuiteName(magic_enum::enum_name(static_cast(akmSuite))); + akmSuiteName.remove_prefix(AkmSuitePrefixLength); ss << '\n' - << indent1 - << magic_enum::enum_name(static_cast(authenticationAlgorithm)); + << indent1 << akmSuiteName; } constexpr auto CipherAlgorithmPrefixLength = std::size(std::string_view("Dot11CipherSuite")); diff --git a/src/common/wifi/core/include/microsoft/net/wifi/Ieee80211AccessPointCapabilities.hxx b/src/common/wifi/core/include/microsoft/net/wifi/Ieee80211AccessPointCapabilities.hxx index 89b0d9cf..560aa834 100644 --- a/src/common/wifi/core/include/microsoft/net/wifi/Ieee80211AccessPointCapabilities.hxx +++ b/src/common/wifi/core/include/microsoft/net/wifi/Ieee80211AccessPointCapabilities.hxx @@ -15,7 +15,7 @@ struct Ieee80211AccessPointCapabilities { std::vector Protocols; std::vector FrequencyBands; - std::vector AuthenticationAlgorithms; + std::vector AkmSuites; std::vector CipherSuites; }; } // namespace Microsoft::Net::Wifi From 77eb5d4fdba3ff2c3aaa83ee8ca625321de05912 Mon Sep 17 00:00:00 2001 From: Andrew Beltrano Date: Wed, 24 Jan 2024 20:49:28 +0000 Subject: [PATCH 3/3] Populate AKMs. --- src/common/service/NetRemoteService.cxx | 2 +- .../cli/NetRemoteCliHandlerOperations.cxx | 4 +-- src/common/wifi/core/CMakeLists.txt | 5 +++ .../include/microsoft/net/wifi/Ieee80211.hxx | 33 ++++++++++++++++++- src/linux/libnl-helpers/CMakeLists.txt | 1 + src/linux/libnl-helpers/Netlink80211Wiphy.cxx | 26 ++++++++++++--- .../wifi/core/AccessPointControllerLinux.cxx | 18 +++++++--- 7 files changed, 74 insertions(+), 15 deletions(-) diff --git a/src/common/service/NetRemoteService.cxx b/src/common/service/NetRemoteService.cxx index f4b209bf..0bb57fb6 100644 --- a/src/common/service/NetRemoteService.cxx +++ b/src/common/service/NetRemoteService.cxx @@ -145,7 +145,7 @@ Ieee80211AkmSuiteToNetRemoteAkm(Ieee80211AkmSuite akmSuite) return Dot11AkmSuite::Dot11AkmSuiteFt8021xSha384; case Ieee80211AkmSuite::FilsSha256: return Dot11AkmSuite::Dot11AkmSuiteFilsSha256; - case Ieee80211AkmSuite::FilsSha284: + case Ieee80211AkmSuite::FilsSha384: return Dot11AkmSuite::Dot11AkmSuiteFilsSha384; case Ieee80211AkmSuite::FtFilsSha256: return Dot11AkmSuite::Dot11AkmSuiteFtFilsSha256; diff --git a/src/common/tools/cli/NetRemoteCliHandlerOperations.cxx b/src/common/tools/cli/NetRemoteCliHandlerOperations.cxx index 6acf86db..ddc952ee 100644 --- a/src/common/tools/cli/NetRemoteCliHandlerOperations.cxx +++ b/src/common/tools/cli/NetRemoteCliHandlerOperations.cxx @@ -8,8 +8,6 @@ #include #include -using namespace Microsoft::Net::Remote; - using namespace Microsoft::Net::Remote; using namespace Microsoft::Net::Remote::Service; using namespace Microsoft::Net::Remote::Wifi; @@ -60,7 +58,7 @@ NetRemoteAccessPointCapabilitiesToString(const Microsoft::Net::Wifi::Dot11Access << indent1 << bandName; } - constexpr auto AkmSuitePrefixLength = std::size(std::string_view("Dot11AuthenticationAlgorithm")); + constexpr auto AkmSuitePrefixLength = std::size(std::string_view("Dot11AkmSuite")); ss << '\n' << indent0 << "Authentication and Key Management (AKM) Suites:"; diff --git a/src/common/wifi/core/CMakeLists.txt b/src/common/wifi/core/CMakeLists.txt index 83a5fa5a..c0e40117 100644 --- a/src/common/wifi/core/CMakeLists.txt +++ b/src/common/wifi/core/CMakeLists.txt @@ -22,6 +22,11 @@ target_sources(wifi-core ${WIFI_CORE_PUBLIC_INCLUDE_PREFIX}/Ieee80211AccessPointCapabilities.hxx ) +target_link_libraries(wifi-core + PUBLIC + notstd +) + install( TARGETS wifi-core EXPORT ${PROJECT_NAME} diff --git a/src/common/wifi/core/include/microsoft/net/wifi/Ieee80211.hxx b/src/common/wifi/core/include/microsoft/net/wifi/Ieee80211.hxx index 56940f72..0e725082 100644 --- a/src/common/wifi/core/include/microsoft/net/wifi/Ieee80211.hxx +++ b/src/common/wifi/core/include/microsoft/net/wifi/Ieee80211.hxx @@ -4,6 +4,9 @@ #include #include +#include + +#include namespace Microsoft::Net::Wifi { @@ -187,7 +190,7 @@ enum class Ieee80211AkmSuite : uint32_t { Ieee8011xSuiteB192 = MakeIeee80211Suite(Ieee80211AkmSuiteId8021xSuiteB192), Ft8021xSha384 = MakeIeee80211Suite(Ieee80211AkmSuiteIdFt8021xSha384), FilsSha256 = MakeIeee80211Suite(Ieee80211AkmSuiteIdFilsSha256), - FilsSha284 = MakeIeee80211Suite(Ieee80211AkmSuiteIdFilsSha384), + FilsSha384 = MakeIeee80211Suite(Ieee80211AkmSuiteIdFilsSha384), FtFilsSha256 = MakeIeee80211Suite(Ieee80211AkmSuiteIdFtFilsSha256), FtFilsSha384 = MakeIeee80211Suite(Ieee80211AkmSuiteIdFtFilsSha384), Owe = MakeIeee80211Suite(Ieee80211AkmSuiteIdOwe), @@ -195,6 +198,34 @@ enum class Ieee80211AkmSuite : uint32_t { PskSha384 = MakeIeee80211Suite(Ieee80211AkmSuiteIdPskSha384), }; +/** + * @brief A listing of all known AKMs. Normally, these would be enumerated with magic_enum::enum_values(), however, that + * only supports enums with values up to UINT16_MAX-1, and the AKM suite underlying type is uint32_t, so cannot be used. + */ +constexpr std::initializer_list AllIeee80211Akms{ + notstd::to_underlying(Ieee80211AkmSuite::Reserved0), + notstd::to_underlying(Ieee80211AkmSuite::Ieee8021x), + notstd::to_underlying(Ieee80211AkmSuite::Psk), + notstd::to_underlying(Ieee80211AkmSuite::Ft8021x), + notstd::to_underlying(Ieee80211AkmSuite::FtPsk), + notstd::to_underlying(Ieee80211AkmSuite::Ieee8021xSha256), + notstd::to_underlying(Ieee80211AkmSuite::PskSha256), + notstd::to_underlying(Ieee80211AkmSuite::Tdls), + notstd::to_underlying(Ieee80211AkmSuite::Sae), + notstd::to_underlying(Ieee80211AkmSuite::FtSae), + notstd::to_underlying(Ieee80211AkmSuite::ApPeerKey), + notstd::to_underlying(Ieee80211AkmSuite::Ieee8021xSuiteB), + notstd::to_underlying(Ieee80211AkmSuite::Ieee8011xSuiteB192), + notstd::to_underlying(Ieee80211AkmSuite::Ft8021xSha384), + notstd::to_underlying(Ieee80211AkmSuite::FilsSha256), + notstd::to_underlying(Ieee80211AkmSuite::FilsSha384), + notstd::to_underlying(Ieee80211AkmSuite::FtFilsSha256), + notstd::to_underlying(Ieee80211AkmSuite::FtFilsSha384), + notstd::to_underlying(Ieee80211AkmSuite::Owe), + notstd::to_underlying(Ieee80211AkmSuite::FtPskSha384), + notstd::to_underlying(Ieee80211AkmSuite::PskSha384), +}; + /** * @brief Cipher suite identifiers or "selectors". * diff --git a/src/linux/libnl-helpers/CMakeLists.txt b/src/linux/libnl-helpers/CMakeLists.txt index e4534415..ccaf1940 100644 --- a/src/linux/libnl-helpers/CMakeLists.txt +++ b/src/linux/libnl-helpers/CMakeLists.txt @@ -31,6 +31,7 @@ target_link_libraries(libnl-helpers PRIVATE magic_enum::magic_enum plog::plog + wifi-core PUBLIC nl nl-genl diff --git a/src/linux/libnl-helpers/Netlink80211Wiphy.cxx b/src/linux/libnl-helpers/Netlink80211Wiphy.cxx index 4d64d518..3583e74d 100644 --- a/src/linux/libnl-helpers/Netlink80211Wiphy.cxx +++ b/src/linux/libnl-helpers/Netlink80211Wiphy.cxx @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -192,14 +193,29 @@ Nl80211Wiphy::Parse(struct nl_msg *nl80211Message) noexcept } } - // Process akm suites. + // Process AKM suites. + // Note: NL80211_ATTR_AKM_SUITES describes the AKMs supported by the PHY (wiphy) and is not specific to an interface. + uint32_t *wiphyAkmSuites; + std::size_t wiphyNumAkmSuites = 0; std::vector akmSuites{}; + if (wiphyAttributes[NL80211_ATTR_AKM_SUITES] != nullptr) { + wiphyAkmSuites = static_cast(nla_data(wiphyAttributes[NL80211_ATTR_AKM_SUITES])); + wiphyNumAkmSuites = static_cast(nla_len(wiphyAttributes[NL80211_ATTR_AKM_SUITES])) / sizeof(*wiphyAkmSuites); + akmSuites = std::vector(wiphyAkmSuites, wiphyAkmSuites + wiphyNumAkmSuites); + } else { + // Per nl80211 documentation, if this attribute is not present, userspace should assume all AKMs are supported. + akmSuites = Microsoft::Net::Wifi::AllIeee80211Akms; + } // Process cipher suites. - uint32_t *wiphyCipherSuites; - auto wiphyNumCipherSuites = static_cast(nla_len(wiphyAttributes[NL80211_ATTR_CIPHER_SUITES])) / sizeof(*wiphyCipherSuites); - wiphyCipherSuites = static_cast(nla_data(wiphyAttributes[NL80211_ATTR_CIPHER_SUITES])); - std::vector cipherSuites(wiphyCipherSuites, wiphyCipherSuites + wiphyNumCipherSuites); + std::size_t wiphyNumCipherSuites = 0; + std::vector cipherSuites{}; + if (wiphyAttributes[NL80211_ATTR_CIPHER_SUITES] != nullptr) { + uint32_t *wiphyCipherSuites; + wiphyNumCipherSuites = static_cast(nla_len(wiphyAttributes[NL80211_ATTR_CIPHER_SUITES])) / sizeof(*wiphyCipherSuites); + wiphyCipherSuites = static_cast(nla_data(wiphyAttributes[NL80211_ATTR_CIPHER_SUITES])); + cipherSuites = std::vector(wiphyCipherSuites, wiphyCipherSuites + wiphyNumCipherSuites); + } // Process supported interface types. std::vector supportedInterfaceTypes{}; diff --git a/src/linux/wifi/core/AccessPointControllerLinux.cxx b/src/linux/wifi/core/AccessPointControllerLinux.cxx index fed5989f..26d70a4f 100644 --- a/src/linux/wifi/core/AccessPointControllerLinux.cxx +++ b/src/linux/wifi/core/AccessPointControllerLinux.cxx @@ -3,13 +3,12 @@ #include #include -#include -#include -#include #include #include #include #include +#include +#include using namespace Microsoft::Net::Wifi; @@ -29,6 +28,12 @@ Nl80211CipherSuiteToIeee80211CipherSuite(uint32_t nl80211CipherSuite) noexcept return static_cast(nl80211CipherSuite); } +Ieee80211AkmSuite +Nl80211AkmSuiteToIeee80211AkmSuite(uint32_t nl80211AkmSuite) noexcept +{ + return static_cast(nl80211AkmSuite); +} + Ieee80211FrequencyBand Nl80211BandToIeee80211FrequencyBand(nl80211_band nl80211Band) noexcept { @@ -48,7 +53,7 @@ std::vector Nl80211WiphyToIeee80211Protocols(const Nl80211Wiphy& nl80211Wiphy) { // Ieee80211 B & G are always supported. - std::vector protocols{ + std::vector protocols{ Ieee80211Protocol::B, Ieee80211Protocol::G, }; @@ -63,7 +68,6 @@ Nl80211WiphyToIeee80211Protocols(const Nl80211Wiphy& nl80211Wiphy) // TODO: once Nl80211WiphyBand is updated to support HE (AX) and EHT (BE), add them here. } - // Remove duplicates. std::ranges::sort(protocols); protocols.erase(std::ranges::begin(std::ranges::unique(protocols)), std::ranges::end(protocols)); @@ -89,6 +93,10 @@ AccessPointControllerLinux::GetCapabilities() capabilities.FrequencyBands = std::vector(std::size(wiphy->Bands)); std::ranges::transform(std::views::keys(wiphy->Bands), std::begin(capabilities.FrequencyBands), detail::Nl80211BandToIeee80211FrequencyBand); + // Convert AKM suites. + capabilities.AkmSuites = std::vector(std::size(wiphy->AkmSuites)); + std::ranges::transform(wiphy->AkmSuites, std::begin(capabilities.AkmSuites), detail::Nl80211AkmSuiteToIeee80211AkmSuite); + // Convert cipher suites. capabilities.CipherSuites = std::vector(std::size(wiphy->CipherSuites)); std::ranges::transform(wiphy->CipherSuites, std::begin(capabilities.CipherSuites), detail::Nl80211CipherSuiteToIeee80211CipherSuite);