aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--wpa_supplicant/config.c65
-rw-r--r--wpa_supplicant/config_file.c36
-rw-r--r--wpa_supplicant/config_ssid.h20
-rw-r--r--wpa_supplicant/wpa_supplicant.c7
-rw-r--r--wpa_supplicant/wpa_supplicant.conf8
-rw-r--r--wpa_supplicant/wpas_kay.c48
-rw-r--r--wpa_supplicant/wpas_kay.h10
7 files changed, 193 insertions, 1 deletions
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index a0b64b2..9011389 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1828,6 +1828,69 @@ 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 NULL;
+
+ return wpa_config_write_string_hex(ssid->mka_cak, MACSEC_CAK_LEN);
+}
+
+
+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 NULL;
+ return wpa_config_write_string_hex(ssid->mka_ckn, MACSEC_CKN_LEN);
+}
+
+#endif /* NO_CONFIG_WRITE */
+
+#endif /* CONFIG_MACSEC */
+
+
/* Helper macros for network block parser */
#ifdef OFFSET
@@ -2062,6 +2125,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_file.c b/wpa_supplicant/config_file.c
index 7ae1654..172508e 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -662,6 +662,40 @@ static void write_psk_list(FILE *f, struct wpa_ssid *ssid)
#endif /* CONFIG_P2P */
+#ifdef CONFIG_MACSEC
+
+static void write_mka_cak(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value;
+
+ if (!(ssid->mka_psk_set & MKA_PSK_SET_CAK))
+ return;
+
+ value = wpa_config_get(ssid, "mka_cak");
+ if (!value)
+ return;
+ fprintf(f, "\tmka_cak=%s\n", value);
+ os_free(value);
+}
+
+
+static void write_mka_ckn(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value;
+
+ if (!(ssid->mka_psk_set & MKA_PSK_SET_CKN))
+ return;
+
+ value = wpa_config_get(ssid, "mka_ckn");
+ if (!value)
+ return;
+ fprintf(f, "\tmka_ckn=%s\n", value);
+ os_free(value);
+}
+
+#endif /* CONFIG_MACSEC */
+
+
static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
{
int i;
@@ -772,6 +806,8 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
INT(beacon_int);
#ifdef CONFIG_MACSEC
INT(macsec_policy);
+ write_mka_cak(f, ssid);
+ write_mka_ckn(f, ssid);
#endif /* CONFIG_MACSEC */
#ifdef CONFIG_HS20
INT(update_identifier);
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 010b594..a530cda 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 BIT(0)
+#define MKA_PSK_SET_CAK BIT(1)
+#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 5d6326a..0bfc39d 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -329,7 +329,12 @@ 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);
+#ifdef CONFIG_MACSEC
+ 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 /* CONFIG_MACSEC */
#endif /* IEEE8021X_EAPOL */
}
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 047ca90..8fa740b 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -892,6 +892,14 @@ 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 key using a (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 (CAK = Secure Connectivity Association Key) takes a 16-bytes (128 bit)
+# hex-string (32 hex-digits)
+# mka_ckn (CKN = CAK Name) takes a 32-bytes (256 bit) 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 e032330..80b98d9 100644
--- a/wpa_supplicant/wpas_kay.c
+++ b/wpa_supplicant/wpas_kay.c
@@ -371,3 +371,51 @@ 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;
+
+ 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;
+
+ 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);
+ if (res)
+ return res;
+
+ /* Failed to create MKA */
+ 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 b7236d0..81f8e0c 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,13 @@ 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 */