]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Fetch supported AKM list from the driver
authorVeerendranath Jakkam <vjakkam@codeaurora.org>
Fri, 21 Dec 2018 10:32:24 +0000 (16:02 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 21 Dec 2018 19:49:02 +0000 (21:49 +0200)
Try to fetch the list of supported AKM suite selectors from the driver
through the vendor interface
QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS. If that command is
available and succeeds, use the returned list to populate the
wpa_driver_capa key_mgmt information instead of assuming all
cfg80211-based drivers support all AKMs. If the driver does not support
this command, the previous behavior is maintained.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
src/drivers/driver.h
src/drivers/driver_nl80211.h
src/drivers/driver_nl80211_capa.c

index 4250caa043e2f59e76ed1c97dfb136e083a2d306..f09f0f70f7e74a9b1891c8de2caaf7be9189703e 100644 (file)
@@ -1441,6 +1441,7 @@ struct wpa_driver_capa {
 #define WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384    0x00002000
 #define WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 0x00004000
 #define WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 0x00008000
+#define WPA_DRIVER_CAPA_KEY_MGMT_SAE           0x00010000
        /** Bitfield of supported key management suites */
        unsigned int key_mgmt;
 
index bc562ba7a8cca8940c4857acd06bfec103cfda2c..1e7fe7a98fff365462269822d019017966749b3f 100644 (file)
@@ -166,6 +166,7 @@ struct wpa_driver_nl80211_data {
        unsigned int he_capab_vendor_cmd_avail:1;
        unsigned int fetch_bss_trans_status:1;
        unsigned int roam_vendor_cmd_avail:1;
+       unsigned int get_supported_akm_suites_avail:1;
 
        u64 vendor_scan_cookie;
        u64 remain_on_chan_cookie;
index 8e2ebd210224b2004c4f14e462967665cdac4c48..bc2f9acf040dce74a08e6a8265e763ec012f1f83 100644 (file)
@@ -786,6 +786,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
                                case QCA_NL80211_VENDOR_SUBCMD_ROAM:
                                        drv->roam_vendor_cmd_avail = 1;
                                        break;
+                               case QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS:
+                                       drv->get_supported_akm_suites_avail = 1;
+                                       break;
 #endif /* CONFIG_DRIVER_NL80211_QCA */
                                }
                        }
@@ -958,6 +961,126 @@ static void qca_nl80211_check_dfs_capa(struct wpa_driver_nl80211_data *drv)
 }
 
 
+static unsigned int get_akm_suites_info(struct nlattr *tb)
+{
+       int i, num;
+       unsigned int key_mgmt = 0;
+       u32 *akms;
+
+       if (!tb)
+               return 0;
+
+       num = nla_len(tb) / sizeof(u32);
+       akms = nla_data(tb);
+       for (i = 0; i < num; i++) {
+               u32 a = akms[i];
+
+               wpa_printf(MSG_DEBUG,
+                          "nl80211: Supported AKM %02x-%02x-%02x:%u",
+                          a >> 24, (a >> 16) & 0xff,
+                          (a >> 8) & 0xff, a & 0xff);
+               switch (a) {
+               case RSN_AUTH_KEY_MGMT_UNSPEC_802_1X:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA |
+                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2;
+                       break;
+               case RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
+                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
+                       break;
+               case RSN_AUTH_KEY_MGMT_FT_802_1X:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT;
+                       break;
+               case RSN_AUTH_KEY_MGMT_FT_PSK:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
+                       break;
+               case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B;
+                       break;
+               case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192;
+                       break;
+               case RSN_AUTH_KEY_MGMT_OWE:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_OWE;
+                       break;
+               case RSN_AUTH_KEY_MGMT_DPP:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_DPP;
+                       break;
+               case RSN_AUTH_KEY_MGMT_FILS_SHA256:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256;
+                       break;
+               case RSN_AUTH_KEY_MGMT_FILS_SHA384:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384;
+                       break;
+               case RSN_AUTH_KEY_MGMT_FT_FILS_SHA256:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256;
+                       break;
+               case RSN_AUTH_KEY_MGMT_FT_FILS_SHA384:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384;
+                       break;
+               case RSN_AUTH_KEY_MGMT_SAE:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SAE;
+                       break;
+               }
+       }
+
+       return key_mgmt;
+}
+
+
+static int get_akm_suites_handler(struct nl_msg *msg, void *arg)
+{
+       struct nlattr *tb[NL80211_ATTR_MAX + 1];
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+       unsigned int *key_mgmt = arg;
+
+       nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+                 genlmsg_attrlen(gnlh, 0), NULL);
+
+       if (tb[NL80211_ATTR_VENDOR_DATA]) {
+               struct nlattr *nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
+               struct nlattr *tb_data[NL80211_ATTR_MAX + 1];
+
+               nla_parse(tb_data, NL80211_ATTR_MAX,
+                         nla_data(nl_vend), nla_len(nl_vend), NULL);
+
+               *key_mgmt =
+                       get_akm_suites_info(tb_data[NL80211_ATTR_AKM_SUITES]);
+       }
+
+       return NL_SKIP;
+}
+
+
+static int qca_nl80211_get_akm_suites(struct wpa_driver_nl80211_data *drv)
+{
+       struct nl_msg *msg;
+       unsigned int key_mgmt = 0;
+       int ret;
+
+       if (!drv->get_supported_akm_suites_avail)
+               return -1;
+
+       if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+           nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
+           nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+                       QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS)) {
+               nlmsg_free(msg);
+               return -1;
+       }
+
+       ret = send_and_recv_msgs(drv, msg, get_akm_suites_handler, &key_mgmt);
+       if (!ret) {
+               wpa_printf(MSG_DEBUG,
+                          "nl80211: Replace capa.key_mgmt based on driver advertised capabilities: 0x%x",
+                          key_mgmt);
+               drv->capa.key_mgmt = key_mgmt;
+       }
+
+       return ret;
+}
+
+
 static int qca_nl80211_he_capab_handler(struct nl_msg *msg, void *arg)
 {
        struct nlattr *tb[NL80211_ATTR_MAX + 1];
@@ -1183,11 +1306,18 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
                drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 |
                        WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 |
                        WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 |
-                       WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384;
+                       WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 |
+                       WPA_DRIVER_CAPA_KEY_MGMT_SAE;
        else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)
                drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 |
                        WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384;
 
+#ifdef CONFIG_DRIVER_NL80211_QCA
+       /* Override drv->capa.key_mgmt based on driver advertised capability
+        * constraints, if available. */
+       qca_nl80211_get_akm_suites(drv);
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+
        drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
                WPA_DRIVER_AUTH_SHARED |
                WPA_DRIVER_AUTH_LEAP;