@@ -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) },
@@ -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
@@ -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 */
}
@@ -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.
@@ -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;
+}
@@ -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 */
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@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(-)