You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
318 lines
8.9 KiB
318 lines
8.9 KiB
7 years ago
|
From ad51731abf06efb284d020578eb34e7b1daeb23e Mon Sep 17 00:00:00 2001
|
||
|
Message-Id: <ad51731abf06efb284d020578eb34e7b1daeb23e.1488376601.git.dcaratti@redhat.com>
|
||
|
From: Sabrina Dubroca <sd@queasysnail.net>
|
||
|
Date: Wed, 2 Nov 2016 16:38:35 +0100
|
||
|
Subject: [PATCH] wpa_supplicant: Allow pre-shared (CAK,CKN) pair for MKA
|
||
|
|
||
|
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 | 65 ++++++++++++++++++++++++++++++++++++++
|
||
|
wpa_supplicant/config_file.c | 36 +++++++++++++++++++++
|
||
|
wpa_supplicant/config_ssid.h | 20 ++++++++++++
|
||
|
wpa_supplicant/wpa_supplicant.c | 7 +++-
|
||
|
wpa_supplicant/wpa_supplicant.conf | 8 +++++
|
||
|
wpa_supplicant/wpas_kay.c | 48 ++++++++++++++++++++++++++++
|
||
|
wpa_supplicant/wpas_kay.h | 10 ++++++
|
||
|
7 files changed, 193 insertions(+), 1 deletion(-)
|
||
|
|
||
|
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 */
|
||
|
--
|
||
|
2.7.4
|
||
|
|