Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cfg80211/nl80211: Optional authentication offload to userspace

This interface allows the host driver to offload the authentication to
user space. This is exclusively defined for host drivers that do not
define separate commands for authentication and association, but rely on
userspace SME (e.g., in wpa_supplicant for the ~WPA_DRIVER_FLAGS_SME
case) for the authentication to happen. This can be used to implement
SAE without full implementation in the kernel/firmware while still being
able to use NL80211_CMD_CONNECT with driver-based BSS selection.

Host driver sends NL80211_CMD_EXTERNAL_AUTH event to start/abort
authentication to the port on which connect is triggered and status
of authentication is further indicated by user space to host
driver through the same command response interface.

User space entities advertise this capability through the
NL80211_ATTR_EXTERNAL_AUTH_SUPP flag in the NL80211_CMD_CONNECT request.
Host drivers shall look at this capability to offload the authentication.

Signed-off-by: Srinivas Dasari <dasaris@qti.qualcomm.com>
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
[add socket connection ownership check]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Srinivas Dasari and committed by
Johannes Berg
40cbfa90 5037a009

+230 -3
+51 -3
include/net/cfg80211.h
··· 1905 1905 * @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n) 1906 1906 * @ASSOC_REQ_DISABLE_VHT: Disable VHT 1907 1907 * @ASSOC_REQ_USE_RRM: Declare RRM capability in this association 1908 + * @CONNECT_REQ_EXTERNAL_AUTH_SUPPORT: User space indicates external 1909 + * authentication capability. Drivers can offload authentication to 1910 + * userspace if this flag is set. Only applicable for cfg80211_connect() 1911 + * request (connect callback). 1908 1912 */ 1909 1913 enum cfg80211_assoc_req_flags { 1910 - ASSOC_REQ_DISABLE_HT = BIT(0), 1911 - ASSOC_REQ_DISABLE_VHT = BIT(1), 1912 - ASSOC_REQ_USE_RRM = BIT(2), 1914 + ASSOC_REQ_DISABLE_HT = BIT(0), 1915 + ASSOC_REQ_DISABLE_VHT = BIT(1), 1916 + ASSOC_REQ_USE_RRM = BIT(2), 1917 + CONNECT_REQ_EXTERNAL_AUTH_SUPPORT = BIT(3), 1913 1918 }; 1914 1919 1915 1920 /** ··· 2606 2601 }; 2607 2602 2608 2603 /** 2604 + * struct cfg80211_external_auth_params - Trigger External authentication. 2605 + * 2606 + * Commonly used across the external auth request and event interfaces. 2607 + * 2608 + * @action: action type / trigger for external authentication. Only significant 2609 + * for the authentication request event interface (driver to user space). 2610 + * @bssid: BSSID of the peer with which the authentication has 2611 + * to happen. Used by both the authentication request event and 2612 + * authentication response command interface. 2613 + * @ssid: SSID of the AP. Used by both the authentication request event and 2614 + * authentication response command interface. 2615 + * @key_mgmt_suite: AKM suite of the respective authentication. Used by the 2616 + * authentication request event interface. 2617 + * @status: status code, %WLAN_STATUS_SUCCESS for successful authentication, 2618 + * use %WLAN_STATUS_UNSPECIFIED_FAILURE if user space cannot give you 2619 + * the real status code for failures. Used only for the authentication 2620 + * response command interface (user space to driver). 2621 + */ 2622 + struct cfg80211_external_auth_params { 2623 + enum nl80211_external_auth_action action; 2624 + u8 bssid[ETH_ALEN] __aligned(2); 2625 + struct cfg80211_ssid ssid; 2626 + unsigned int key_mgmt_suite; 2627 + u16 status; 2628 + }; 2629 + 2630 + /** 2609 2631 * struct cfg80211_ops - backend description for wireless configuration 2610 2632 * 2611 2633 * This struct is registered by fullmac card drivers and/or wireless stacks ··· 2955 2923 * (invoked with the wireless_dev mutex held) 2956 2924 * @del_pmk: delete the previously configured PMK for the given authenticator. 2957 2925 * (invoked with the wireless_dev mutex held) 2926 + * 2927 + * @external_auth: indicates result of offloaded authentication processing from 2928 + * user space 2958 2929 */ 2959 2930 struct cfg80211_ops { 2960 2931 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); ··· 3251 3216 const struct cfg80211_pmk_conf *conf); 3252 3217 int (*del_pmk)(struct wiphy *wiphy, struct net_device *dev, 3253 3218 const u8 *aa); 3219 + int (*external_auth)(struct wiphy *wiphy, struct net_device *dev, 3220 + struct cfg80211_external_auth_params *params); 3254 3221 }; 3255 3222 3256 3223 /* ··· 6238 6201 6239 6202 /* ethtool helper */ 6240 6203 void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info); 6204 + 6205 + /** 6206 + * cfg80211_external_auth_request - userspace request for authentication 6207 + * @netdev: network device 6208 + * @params: External authentication parameters 6209 + * @gfp: allocation flags 6210 + * Returns: 0 on success, < 0 on error 6211 + */ 6212 + int cfg80211_external_auth_request(struct net_device *netdev, 6213 + struct cfg80211_external_auth_params *params, 6214 + gfp_t gfp); 6241 6215 6242 6216 /* Logging, debugging and troubleshooting/diagnostic helpers. */ 6243 6217
+47
include/uapi/linux/nl80211.h
··· 992 992 * 993 993 * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded. 994 994 * 995 + * @NL80211_CMD_EXTERNAL_AUTH: This interface is exclusively defined for host 996 + * drivers that do not define separate commands for authentication and 997 + * association, but rely on user space for the authentication to happen. 998 + * This interface acts both as the event request (driver to user space) 999 + * to trigger the authentication and command response (userspace to 1000 + * driver) to indicate the authentication status. 1001 + * 1002 + * User space uses the %NL80211_CMD_CONNECT command to the host driver to 1003 + * trigger a connection. The host driver selects a BSS and further uses 1004 + * this interface to offload only the authentication part to the user 1005 + * space. Authentication frames are passed between the driver and user 1006 + * space through the %NL80211_CMD_FRAME interface. Host driver proceeds 1007 + * further with the association after getting successful authentication 1008 + * status. User space indicates the authentication status through 1009 + * %NL80211_ATTR_STATUS_CODE attribute in %NL80211_CMD_EXTERNAL_AUTH 1010 + * command interface. 1011 + * 1012 + * Host driver reports this status on an authentication failure to the 1013 + * user space through the connect result as the user space would have 1014 + * initiated the connection through the connect request. 1015 + * 995 1016 * @NL80211_CMD_MAX: highest used command number 996 1017 * @__NL80211_CMD_AFTER_LAST: internal use 997 1018 */ ··· 1218 1197 NL80211_CMD_PORT_AUTHORIZED, 1219 1198 1220 1199 NL80211_CMD_RELOAD_REGDB, 1200 + 1201 + NL80211_CMD_EXTERNAL_AUTH, 1221 1202 1222 1203 /* add new commands above here */ 1223 1204 ··· 2176 2153 * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT. 2177 2154 * @NL80211_ATTR_PORT_AUTHORIZED: (reserved) 2178 2155 * 2156 + * @NL80211_ATTR_EXTERNAL_AUTH_ACTION: Identify the requested external 2157 + * authentication operation (u32 attribute with an 2158 + * &enum nl80211_external_auth_action value). This is used with the 2159 + * &NL80211_CMD_EXTERNAL_AUTH request event. 2160 + * @NL80211_ATTR_EXTERNAL_AUTH_SUPPORT: Flag attribute indicating that the user 2161 + * space supports external authentication. This attribute shall be used 2162 + * only with %NL80211_CMD_CONNECT request. The driver may offload 2163 + * authentication processing to user space if this capability is indicated 2164 + * in NL80211_CMD_CONNECT requests from the user space. 2165 + * 2179 2166 * @NUM_NL80211_ATTR: total number of nl80211_attrs available 2180 2167 * @NL80211_ATTR_MAX: highest attribute number currently defined 2181 2168 * @__NL80211_ATTR_AFTER_LAST: internal use ··· 2611 2578 NL80211_ATTR_WANT_1X_4WAY_HS, 2612 2579 NL80211_ATTR_PMKR0_NAME, 2613 2580 NL80211_ATTR_PORT_AUTHORIZED, 2581 + 2582 + NL80211_ATTR_EXTERNAL_AUTH_ACTION, 2583 + NL80211_ATTR_EXTERNAL_AUTH_SUPPORT, 2614 2584 2615 2585 /* add attributes here, update the policy in nl80211.c */ 2616 2586 ··· 5529 5493 /* keep last */ 5530 5494 NUM_NL80211_NAN_MATCH_ATTR, 5531 5495 NL80211_NAN_MATCH_ATTR_MAX = NUM_NL80211_NAN_MATCH_ATTR - 1 5496 + }; 5497 + 5498 + /** 5499 + * nl80211_external_auth_action - Action to perform with external 5500 + * authentication request. Used by NL80211_ATTR_EXTERNAL_AUTH_ACTION. 5501 + * @NL80211_EXTERNAL_AUTH_START: Start the authentication. 5502 + * @NL80211_EXTERNAL_AUTH_ABORT: Abort the ongoing authentication. 5503 + */ 5504 + enum nl80211_external_auth_action { 5505 + NL80211_EXTERNAL_AUTH_START, 5506 + NL80211_EXTERNAL_AUTH_ABORT, 5532 5507 }; 5533 5508 5534 5509 #endif /* __LINUX_NL80211_H */
+94
net/wireless/nl80211.c
··· 420 420 [NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 }, 421 421 [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN }, 422 422 [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG }, 423 + [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG }, 423 424 }; 424 425 425 426 /* policy for the key attributes */ ··· 9162 9161 return -EINVAL; 9163 9162 } 9164 9163 9164 + if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) { 9165 + if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) { 9166 + GENL_SET_ERR_MSG(info, 9167 + "external auth requires connection ownership"); 9168 + return -EINVAL; 9169 + } 9170 + connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT; 9171 + } 9172 + 9165 9173 wdev_lock(dev->ieee80211_ptr); 9166 9174 9167 9175 err = cfg80211_connect(rdev, dev, &connect, connkeys, ··· 12479 12469 return ret; 12480 12470 } 12481 12471 12472 + static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info) 12473 + { 12474 + struct cfg80211_registered_device *rdev = info->user_ptr[0]; 12475 + struct net_device *dev = info->user_ptr[1]; 12476 + struct cfg80211_external_auth_params params; 12477 + 12478 + if (rdev->ops->external_auth) 12479 + return -EOPNOTSUPP; 12480 + 12481 + if (!info->attrs[NL80211_ATTR_SSID]) 12482 + return -EINVAL; 12483 + 12484 + if (!info->attrs[NL80211_ATTR_BSSID]) 12485 + return -EINVAL; 12486 + 12487 + if (!info->attrs[NL80211_ATTR_STATUS_CODE]) 12488 + return -EINVAL; 12489 + 12490 + memset(&params, 0, sizeof(params)); 12491 + 12492 + params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); 12493 + if (params.ssid.ssid_len == 0 || 12494 + params.ssid.ssid_len > IEEE80211_MAX_SSID_LEN) 12495 + return -EINVAL; 12496 + memcpy(params.ssid.ssid, nla_data(info->attrs[NL80211_ATTR_SSID]), 12497 + params.ssid.ssid_len); 12498 + 12499 + memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]), 12500 + ETH_ALEN); 12501 + 12502 + params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]); 12503 + 12504 + return rdev_external_auth(rdev, dev, &params); 12505 + } 12506 + 12482 12507 #define NL80211_FLAG_NEED_WIPHY 0x01 12483 12508 #define NL80211_FLAG_NEED_NETDEV 0x02 12484 12509 #define NL80211_FLAG_NEED_RTNL 0x04 ··· 13406 13361 .cmd = NL80211_CMD_DEL_PMK, 13407 13362 .doit = nl80211_del_pmk, 13408 13363 .policy = nl80211_policy, 13364 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 13365 + NL80211_FLAG_NEED_RTNL, 13366 + }, 13367 + { 13368 + .cmd = NL80211_CMD_EXTERNAL_AUTH, 13369 + .doit = nl80211_external_auth, 13370 + .policy = nl80211_policy, 13371 + .flags = GENL_ADMIN_PERM, 13409 13372 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 13410 13373 NL80211_FLAG_NEED_RTNL, 13411 13374 }, ··· 15427 15374 out: 15428 15375 nlmsg_free(msg); 15429 15376 } 15377 + 15378 + int cfg80211_external_auth_request(struct net_device *dev, 15379 + struct cfg80211_external_auth_params *params, 15380 + gfp_t gfp) 15381 + { 15382 + struct wireless_dev *wdev = dev->ieee80211_ptr; 15383 + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); 15384 + struct sk_buff *msg; 15385 + void *hdr; 15386 + 15387 + if (!wdev->conn_owner_nlportid) 15388 + return -EINVAL; 15389 + 15390 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); 15391 + if (!msg) 15392 + return -ENOMEM; 15393 + 15394 + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH); 15395 + if (!hdr) 15396 + goto nla_put_failure; 15397 + 15398 + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || 15399 + nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || 15400 + nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) || 15401 + nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION, 15402 + params->action) || 15403 + nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) || 15404 + nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len, 15405 + params->ssid.ssid)) 15406 + goto nla_put_failure; 15407 + 15408 + genlmsg_end(msg, hdr); 15409 + genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, 15410 + wdev->conn_owner_nlportid); 15411 + return 0; 15412 + 15413 + nla_put_failure: 15414 + nlmsg_free(msg); 15415 + return -ENOBUFS; 15416 + } 15417 + EXPORT_SYMBOL(cfg80211_external_auth_request); 15430 15418 15431 15419 /* initialisation/exit functions */ 15432 15420
+15
net/wireless/rdev-ops.h
··· 1190 1190 trace_rdev_return_int(&rdev->wiphy, ret); 1191 1191 return ret; 1192 1192 } 1193 + 1194 + static inline int 1195 + rdev_external_auth(struct cfg80211_registered_device *rdev, 1196 + struct net_device *dev, 1197 + struct cfg80211_external_auth_params *params) 1198 + { 1199 + int ret = -EOPNOTSUPP; 1200 + 1201 + trace_rdev_external_auth(&rdev->wiphy, dev, params); 1202 + if (rdev->ops->external_auth) 1203 + ret = rdev->ops->external_auth(&rdev->wiphy, dev, params); 1204 + trace_rdev_return_int(&rdev->wiphy, ret); 1205 + return ret; 1206 + } 1207 + 1193 1208 #endif /* __CFG80211_RDEV_OPS */
+23
net/wireless/trace.h
··· 2319 2319 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(aa)) 2320 2320 ); 2321 2321 2322 + TRACE_EVENT(rdev_external_auth, 2323 + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, 2324 + struct cfg80211_external_auth_params *params), 2325 + TP_ARGS(wiphy, netdev, params), 2326 + TP_STRUCT__entry(WIPHY_ENTRY 2327 + NETDEV_ENTRY 2328 + MAC_ENTRY(bssid) 2329 + __array(u8, ssid, IEEE80211_MAX_SSID_LEN + 1) 2330 + __field(u16, status) 2331 + ), 2332 + TP_fast_assign(WIPHY_ASSIGN; 2333 + NETDEV_ASSIGN; 2334 + MAC_ASSIGN(bssid, params->bssid); 2335 + memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); 2336 + memcpy(__entry->ssid, params->ssid.ssid, 2337 + params->ssid.ssid_len); 2338 + __entry->status = params->status; 2339 + ), 2340 + TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT 2341 + ", ssid: %s, status: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, 2342 + __entry->bssid, __entry->ssid, __entry->status) 2343 + ); 2344 + 2322 2345 /************************************************************* 2323 2346 * cfg80211 exported functions traces * 2324 2347 *************************************************************/