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>
This commit is contained in:
parent
5acbf22bb0
commit
ad51731abf
7 changed files with 193 additions and 1 deletions
|
@ -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) },
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue