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.
317 lines
8.9 KiB
317 lines
8.9 KiB
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 |
|
|
|
|