[PATCH 1/5] wpa_supplicant: allow pre-shared (CAK,CKN) pair for MKA

Sabrina Dubroca sd at queasysnail.net
Wed Nov 2 08:38:35 PDT 2016


This enables configuring key_mgmt=NONE + mka_ckn + mka_cak.
This allows wpa_supplicant to work in a peer-to-peer mode, where peers
are authenticated by the pre-shared (CAK,CKN) pair. In this mode, peers
can act as key server to distribute keys for the MACsec instances.

This is what some MACsec switches support, and even without HW
support, it's a convenient way to setup a network.

Signed-off-by: Sabrina Dubroca <sd at queasysnail.net>
---
 wpa_supplicant/config.c            | 60 ++++++++++++++++++++++++++++++++++++++
 wpa_supplicant/config_ssid.h       | 20 +++++++++++++
 wpa_supplicant/wpa_supplicant.c    |  5 +++-
 wpa_supplicant/wpa_supplicant.conf |  7 +++++
 wpa_supplicant/wpas_kay.c          | 53 +++++++++++++++++++++++++++++++++
 wpa_supplicant/wpas_kay.h          |  9 ++++++
 6 files changed, 153 insertions(+), 1 deletion(-)

diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index a0b64b22a236..6d75ef646d6f 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1828,6 +1828,64 @@ static char * wpa_config_write_mesh_basic_rates(const struct parse_data *data,
 #endif /* CONFIG_MESH */
 
 
+#ifdef CONFIG_MACSEC
+static int wpa_config_parse_mka_cak(const struct parse_data *data,
+				struct wpa_ssid *ssid, int line,
+				const char *value)
+{
+	if (hexstr2bin(value, ssid->mka_cak, MACSEC_CAK_LEN) ||
+	    value[MACSEC_CAK_LEN * 2] != '\0') {
+		wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CAK '%s'.",
+			   line, value);
+		return -1;
+	}
+
+	ssid->mka_psk_set |= MKA_PSK_SET_CAK;
+
+	wpa_hexdump_key(MSG_MSGDUMP, "MKA-CAK", ssid->mka_cak, MACSEC_CAK_LEN);
+	return 0;
+}
+
+static int wpa_config_parse_mka_ckn(const struct parse_data *data,
+				struct wpa_ssid *ssid, int line,
+				const char *value)
+{
+	if (hexstr2bin(value, ssid->mka_ckn, MACSEC_CKN_LEN) ||
+	    value[MACSEC_CKN_LEN * 2] != '\0') {
+		wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
+			   line, value);
+		return -1;
+	}
+
+	ssid->mka_psk_set |= MKA_PSK_SET_CKN;
+
+	wpa_hexdump_key(MSG_MSGDUMP, "MKA-CKN", ssid->mka_ckn, MACSEC_CKN_LEN);
+	return 0;
+}
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_mka_cak(const struct parse_data *data,
+				   struct wpa_ssid *ssid)
+{
+	if (ssid->mka_psk_set & MKA_PSK_SET_CAK)
+		return wpa_config_write_string_hex(ssid->mka_cak, MACSEC_CAK_LEN);
+
+	return NULL;
+}
+static char * wpa_config_write_mka_ckn(const struct parse_data *data,
+				   struct wpa_ssid *ssid)
+{
+	if (ssid->mka_psk_set & MKA_PSK_SET_CKN)
+		return wpa_config_write_string_hex(ssid->mka_ckn, MACSEC_CKN_LEN);
+
+	return NULL;
+}
+#endif /* NO_CONFIG_WRITE */
+
+#endif /* CONFIG_MACSEC */
+
+
+
 /* Helper macros for network block parser */
 
 #ifdef OFFSET
@@ -2062,6 +2120,8 @@ static const struct parse_data ssid_fields[] = {
 	{ INT(beacon_int) },
 #ifdef CONFIG_MACSEC
 	{ INT_RANGE(macsec_policy, 0, 1) },
+	{ FUNC_KEY(mka_cak) },
+	{ FUNC_KEY(mka_ckn) },
 #endif /* CONFIG_MACSEC */
 #ifdef CONFIG_HS20
 	{ INT(update_identifier) },
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 010b594af85e..b3cb1ea47227 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -728,6 +728,26 @@ struct wpa_ssid {
 	 *    determine whether to use a secure session or not.
 	 */
 	int macsec_policy;
+
+	/**
+	 * mka_ckn - MKA pre-shared CKN
+	 */
+#define MACSEC_CKN_LEN 32
+	u8 mka_ckn[MACSEC_CKN_LEN];
+
+	/**
+	 * mka_cak - MKA pre-shared CAK
+	 */
+#define MACSEC_CAK_LEN 16
+	u8 mka_cak[MACSEC_CAK_LEN];
+
+#define MKA_PSK_SET_CKN 1
+#define MKA_PSK_SET_CAK 2
+#define MKA_PSK_SET (MKA_PSK_SET_CKN | MKA_PSK_SET_CAK)
+	/**
+	 * mka_psk_set - whether mka_ckn and mka_cak are set
+	 */
+	u8 mka_psk_set;
 #endif /* CONFIG_MACSEC */
 
 #ifdef CONFIG_HS20
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 5d6326a5d212..8644e00cfd74 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -329,7 +329,10 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
 
 	eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
 
-	ieee802_1x_alloc_kay_sm(wpa_s, ssid);
+	if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
+		ieee802_1x_create_preshared_mka(wpa_s, ssid);
+	else
+		ieee802_1x_alloc_kay_sm(wpa_s, ssid);
 #endif /* IEEE8021X_EAPOL */
 }
 
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 047ca9001d8d..5f85c4320ede 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -892,6 +892,13 @@ fast_reauth=1
 # 1: MACsec enabled - Should secure, accept key server's advice to
 #    determine whether to use a secure session or not.
 #
+# mka_cak and mka_ckn: IEEE 802.1X/MACsec pre-shared authentication mode
+# This allows to configure MACsec with a pre-shared (CAK,CKN) pair.
+# In this mode, instances of wpa_supplicant can act as peers, one of
+# which will become the key server and start distributing SAKs.
+# mka_cak takes a 16-bytes hex-string (32 hex-digits)
+# mka_ckn takes a 32-bytes hex-string (64 hex-digits)
+#
 # mixed_cell: This option can be used to configure whether so called mixed
 # cells, i.e., networks that use both plaintext and encryption in the same
 # SSID, are allowed when selecting a BSS from scan results.
diff --git a/wpa_supplicant/wpas_kay.c b/wpa_supplicant/wpas_kay.c
index e03233003f51..e8580339361b 100644
--- a/wpa_supplicant/wpas_kay.c
+++ b/wpa_supplicant/wpas_kay.c
@@ -371,3 +371,56 @@ fail:
 
 	return res;
 }
+
+void * ieee802_1x_create_preshared_mka(struct wpa_supplicant *wpa_s,
+				       struct wpa_ssid *ssid)
+{
+	struct mka_key *cak;
+	struct mka_key_name *ckn;
+	void * res;
+
+	wpa_printf(MSG_DEBUG, "%s:%d\n", __FUNCTION__, __LINE__);
+
+	if ((ssid->mka_psk_set & MKA_PSK_SET) != MKA_PSK_SET)
+		return NULL;
+
+	if (ieee802_1x_alloc_kay_sm(wpa_s, ssid) < 0)
+		return NULL;
+
+	if (!wpa_s->kay || wpa_s->kay->policy == DO_NOT_SECURE)
+		return NULL;
+
+	ckn = os_zalloc(sizeof(*ckn));
+	if (!ckn)
+		goto dealloc;
+
+	cak = os_zalloc(sizeof(*cak));
+	if (!cak)
+		goto free_ckn;
+
+	wpa_printf(MSG_DEBUG, "%s:%d\n", __FUNCTION__, __LINE__);
+
+	cak->len = MACSEC_CAK_LEN;
+	os_memcpy(cak->key, ssid->mka_cak, cak->len);
+
+	ckn->len = MACSEC_CKN_LEN;
+	os_memcpy(ckn->name, ssid->mka_ckn, ckn->len);
+
+	res = ieee802_1x_kay_create_mka(wpa_s->kay, ckn, cak, 0, PSK, FALSE);
+
+	wpa_printf(MSG_DEBUG, "%s:%d\n", __FUNCTION__, __LINE__);
+
+	if (res)
+		return res;
+
+	os_free(cak);
+
+	/* fallthrough */
+
+free_ckn:
+	os_free(ckn);
+dealloc:
+	ieee802_1x_dealloc_kay_sm(wpa_s);
+
+	return NULL;
+}
diff --git a/wpa_supplicant/wpas_kay.h b/wpa_supplicant/wpas_kay.h
index b7236d0776c4..d5a678f22c07 100644
--- a/wpa_supplicant/wpas_kay.h
+++ b/wpa_supplicant/wpas_kay.h
@@ -17,6 +17,9 @@ void * ieee802_1x_notify_create_actor(struct wpa_supplicant *wpa_s,
 				      const u8 *peer_addr);
 void ieee802_1x_dealloc_kay_sm(struct wpa_supplicant *wpa_s);
 
+void * ieee802_1x_create_preshared_mka(struct wpa_supplicant *wpa_s,
+				       struct wpa_ssid *ssid);
+
 #else /* CONFIG_MACSEC */
 
 static inline int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s,
@@ -36,6 +39,12 @@ static inline void ieee802_1x_dealloc_kay_sm(struct wpa_supplicant *wpa_s)
 {
 }
 
+static inline void * ieee802_1x_create_preshared_mka(struct wpa_supplicant *wpa_s,
+						     struct wpa_ssid *ssid)
+{
+	return 0;
+}
+
 #endif /* CONFIG_MACSEC */
 
 #endif /* WPAS_KAY_H */
-- 
2.10.1




More information about the Hostap mailing list