[PATCH 21/29] EPPKE: Pass hash algorithm to kernel via NL80211_ATTR_HASH_ALG

Sai Pratyusha Magam smagam at qti.qualcomm.com
Thu Dec 11 05:14:35 PST 2025


From: Ainy Kumari <ainy.kumari at oss.qualcomm.com>

Add support for passing the Secure Hash Algorithm(SHA) to the kernel
via NL80211_CMD_AUTHENTICATE using NL80211_ATTR_HASH_ALG, allowing
kernel to compute the MIC and generate the hash of the Authentication
frame as required.

Signed-off-by: Ainy Kumari <ainy.kumari at oss.qualcomm.com>
---
 src/common/defs.h            |  4 ++++
 src/common/wpa_common.c      |  6 +++++-
 src/common/wpa_common.h      |  2 +-
 src/drivers/driver.h         |  1 +
 src/drivers/driver_nl80211.c | 21 +++++++++++++++++++++
 src/pasn/pasn_common.h       |  1 +
 src/pasn/pasn_initiator.c    |  2 +-
 src/pasn/pasn_responder.c    |  4 ++--
 wpa_supplicant/sme.c         |  7 ++++---
 9 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/src/common/defs.h b/src/common/defs.h
index eb410386a..1a0056132 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -213,6 +213,10 @@ static inline int wpa_key_mgmt_cross_akm(int akm)
 #define WPA_AUTH_ALG_FILS_SK_PFS BIT(6)
 #define WPA_AUTH_ALG_EPPKE BIT(10)
 
+#define WPA_HASH_SHA256 BIT(0)
+#define WPA_HASH_SHA384 BIT(1)
+#define WPA_HASH_SHA512 BIT(2)
+
 static inline int wpa_auth_alg_fils(int alg)
 {
 	return !!(alg & (WPA_AUTH_ALG_FILS | WPA_AUTH_ALG_FILS_SK_PFS));
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index c18e71cf5..29cd21515 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -1932,10 +1932,11 @@ err:
  * @hash: On return would hold the computed hash. Should be big enough to handle
  *	SHA384.
  * @group: Finite Cyclic Group ID for PASN authentication
+ * @hash_algo: Hash algorithm used for authentication frame hashing
  * Returns: 0 on success, -1 on failure
  */
 int pasn_auth_frame_hash(int akmp, int cipher, const u8 *data, size_t len,
-			 u8 *hash, int group)
+			 u8 *hash, int group, u32 *hash_algo)
 {
 	enum rsn_hash_alg hash_alg;
 
@@ -1945,16 +1946,19 @@ int pasn_auth_frame_hash(int akmp, int cipher, const u8 *data, size_t len,
 	case HASH_SHA512:
 #ifdef CONFIG_SHA512
 		wpa_printf(MSG_DEBUG, "PASN: Frame hash using SHA-512");
+		*hash_algo = WPA_HASH_SHA512;
 		return sha512_vector(1, &data, &len, hash);
 #endif
 	case HASH_SHA384:
 #ifdef CONFIG_SHA384
 		wpa_printf(MSG_DEBUG, "PASN: Frame hash using SHA-384");
+		*hash_algo = WPA_HASH_SHA384;
 		return sha384_vector(1, &data, &len, hash);
 #endif
 	case HASH_SHA256:
 	default:
 		wpa_printf(MSG_DEBUG, "PASN: Frame hash using SHA-256");
+		*hash_algo = WPA_HASH_SHA256;
 		return sha256_vector(1, &data, &len, hash);
 	}
 }
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index 083e5ba2d..ad3c017ec 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -787,7 +787,7 @@ int pasn_mic(const u8 *kck, size_t kck_len, int akmp, int cipher,
 int wpa_ltf_keyseed(struct wpa_ptk *ptk, int akmp, int cipher);
 
 int pasn_auth_frame_hash(int akmp, int cipher, const u8 *data, size_t len,
-			 u8 *hash, int group);
+			 u8 *hash, int group, u32 *hash_algo);
 
 void wpa_pasn_build_auth_header(struct wpabuf *buf, const u8 *bssid,
 				const u8 *src, const u8 *dst,
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 53fb9c81f..126ec56a1 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -767,6 +767,7 @@ struct wpa_driver_auth_params {
 	size_t wep_key_len[4];
 	int wep_tx_keyidx;
 	int local_state_change;
+	u32 hash_alg;
 
 	/**
 	 * p2p - Whether this connection is a P2P group
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index d071caa93..daf22320a 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -4283,6 +4283,18 @@ static enum nl80211_auth_type get_nl_auth_type(int wpa_auth_alg)
 }
 
 
+static enum nl80211_hash_alg get_nl_hash_alg(int wpa_hash_alg)
+{
+	if (wpa_hash_alg & WPA_HASH_SHA256)
+		return NL80211_HASH_ALG_SHA256;
+	if (wpa_hash_alg & WPA_HASH_SHA384)
+		return NL80211_HASH_ALG_SHA384;
+	if (wpa_hash_alg & WPA_HASH_SHA512)
+		return NL80211_HASH_ALG_SHA512;
+	return __NL80211_HASH_ALG_INVALID;
+}
+
+
 static int
 nl80211_put_bss_membership_selectors(struct wpa_driver_nl80211_data *drv,
 				     struct nl_msg *msg)
@@ -4317,6 +4329,7 @@ static int wpa_driver_nl80211_authenticate(
 	int ret = -1, i;
 	struct nl_msg *msg;
 	enum nl80211_auth_type type;
+	enum nl80211_hash_alg hash_alg;
 	enum nl80211_iftype nlmode;
 	int count = 0;
 	int is_retry;
@@ -4400,6 +4413,14 @@ retry:
 			    params->auth_data))
 			goto fail;
 	}
+#ifdef CONFIG_ENC_ASSOC
+	if (params->auth_alg == WPA_AUTH_ALG_EPPKE) {
+		hash_alg = get_nl_hash_alg(params->hash_alg);
+		wpa_printf(MSG_DEBUG, "  * Hash Algo %d", hash_alg);
+		if (nla_put_u32(msg, NL80211_ATTR_HASH_ALG, hash_alg))
+			goto fail;
+	}
+#endif /* CONFIG_ENC_ASSOC */
 	type = get_nl_auth_type(params->auth_alg);
 	wpa_printf(MSG_DEBUG, "  * Auth Type %d", type);
 	if (type > NL80211_AUTHTYPE_MAX ||
diff --git a/src/pasn/pasn_common.h b/src/pasn/pasn_common.h
index 09a6a15b0..4d35bffd0 100644
--- a/src/pasn/pasn_common.h
+++ b/src/pasn/pasn_common.h
@@ -54,6 +54,7 @@ struct pasn_data {
 	unsigned int auth_alg;
 	u8 mld_addr[ETH_ALEN];
 	bool is_ml_sta;
+	u32 hash_alg;
 
 #ifdef CONFIG_SAE
 	struct sae_pt *pt;
diff --git a/src/pasn/pasn_initiator.c b/src/pasn/pasn_initiator.c
index 5669daa84..814014051 100644
--- a/src/pasn/pasn_initiator.c
+++ b/src/pasn/pasn_initiator.c
@@ -667,7 +667,7 @@ struct wpabuf *wpas_pasn_build_auth_1(struct pasn_data *pasn,
 	ret = pasn_auth_frame_hash(pasn->akmp, pasn->cipher,
 				   wpabuf_head_u8(buf) + IEEE80211_HDRLEN,
 				   wpabuf_len(buf) - IEEE80211_HDRLEN,
-				   pasn->hash, pasn->group);
+				   pasn->hash, pasn->group, &pasn->hash_alg);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "PASN: Failed to compute hash");
 		goto fail;
diff --git a/src/pasn/pasn_responder.c b/src/pasn/pasn_responder.c
index a1d2974e8..b4dea5ee5 100644
--- a/src/pasn/pasn_responder.c
+++ b/src/pasn/pasn_responder.c
@@ -967,7 +967,7 @@ int handle_auth_pasn_1(struct pasn_data *pasn,
 	ret = pasn_auth_frame_hash(pasn->akmp, pasn->cipher,
 				   ((const u8 *) mgmt) + IEEE80211_HDRLEN,
 				   len - IEEE80211_HDRLEN, pasn->hash,
-				   pasn->group);
+				   pasn->group, &pasn->hash_alg);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "PASN: Failed to compute hash");
 		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -1052,7 +1052,7 @@ int handle_auth_pasn_1(struct pasn_data *pasn,
 	ret = pasn_auth_frame_hash(pasn->akmp, pasn->cipher,
 				   ((const u8 *) mgmt) + IEEE80211_HDRLEN,
 				   len - IEEE80211_HDRLEN, pasn->hash,
-				   pasn->group);
+				   pasn->group, &pasn->hash_alg);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "PASN: Failed to compute hash");
 		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 50b56aaa1..478ce5b60 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -1168,12 +1168,13 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
 #ifdef CONFIG_ENC_ASSOC
 	if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_EPPKE) {
 		wpas_eppke_initialize(wpa_s, bss, ssid);
-		if (start)
+		if (start) {
 			resp = wpas_pasn_build_auth_1(&wpa_s->pasn, NULL,
 							    false, 0);
-		else
+			params.hash_alg = wpa_s->pasn.hash_alg;
+		} else {
 			resp = wpas_pasn_build_auth_3(&wpa_s->pasn, 0);
-
+		}
 		params.auth_data = wpabuf_head(resp);
 		params.auth_data_len = wpabuf_len(resp);
 	}
-- 
2.34.1




More information about the Hostap mailing list