6c9f0c
From 23c3528a8461681b23c94ed441cd94c8d528bebe Mon Sep 17 00:00:00 2001
6c9f0c
Message-Id: <23c3528a8461681b23c94ed441cd94c8d528bebe.1488376601.git.dcaratti@redhat.com>
6c9f0c
From: Sabrina Dubroca <sd@queasysnail.net>
6c9f0c
Date: Fri, 21 Oct 2016 14:45:28 +0200
6c9f0c
Subject: [PATCH] mka: Add support for removing SAs
6c9f0c
6c9f0c
So that the core can notify drivers that need to perform some operations
6c9f0c
when an SA is deleted.
6c9f0c
6c9f0c
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
6c9f0c
---
6c9f0c
 src/drivers/driver.h          | 16 +++++++++
6c9f0c
 src/pae/ieee802_1x_kay.c      | 81 +++++++++++++++++++++++++++++++++----------
6c9f0c
 src/pae/ieee802_1x_kay.h      |  2 ++
6c9f0c
 src/pae/ieee802_1x_secy_ops.c | 41 ++++++++++++++++++++++
6c9f0c
 src/pae/ieee802_1x_secy_ops.h |  3 ++
6c9f0c
 wpa_supplicant/driver_i.h     | 16 +++++++++
6c9f0c
 wpa_supplicant/wpas_kay.c     | 14 ++++++++
6c9f0c
 7 files changed, 154 insertions(+), 19 deletions(-)
6c9f0c
6c9f0c
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
6c9f0c
index 54ae6b7..9a6db90 100644
6c9f0c
--- a/src/drivers/driver.h
6c9f0c
+++ b/src/drivers/driver.h
6c9f0c
@@ -3419,6 +3419,14 @@ struct wpa_driver_ops {
6c9f0c
 	int (*create_receive_sa)(void *priv, struct receive_sa *sa);
6c9f0c
 
6c9f0c
 	/**
6c9f0c
+	 * delete_receive_sa - Delete secure association for receive
6c9f0c
+	 * @priv: Private driver interface data from init()
6c9f0c
+	 * @sa: Secure association
6c9f0c
+	 * Returns: 0 on success, -1 on failure
6c9f0c
+	 */
6c9f0c
+	int (*delete_receive_sa)(void *priv, struct receive_sa *sa);
6c9f0c
+
6c9f0c
+	/**
6c9f0c
 	 * enable_receive_sa - enable the SA for receive
6c9f0c
 	 * @priv: private driver interface data from init()
6c9f0c
 	 * @sa: secure association
6c9f0c
@@ -3461,6 +3469,14 @@ struct wpa_driver_ops {
6c9f0c
 	int (*create_transmit_sa)(void *priv, struct transmit_sa *sa);
6c9f0c
 
6c9f0c
 	/**
6c9f0c
+	 * delete_transmit_sa - Delete secure association for transmit
6c9f0c
+	 * @priv: Private driver interface data from init()
6c9f0c
+	 * @sa: Secure association
6c9f0c
+	 * Returns: 0 on success, -1 on failure
6c9f0c
+	 */
6c9f0c
+	int (*delete_transmit_sa)(void *priv, struct transmit_sa *sa);
6c9f0c
+
6c9f0c
+	/**
6c9f0c
 	 * enable_transmit_sa - enable SA for transmit
6c9f0c
 	 * @priv: private driver interface data from init()
6c9f0c
 	 * @sa: secure association
6c9f0c
diff --git a/src/pae/ieee802_1x_kay.c b/src/pae/ieee802_1x_kay.c
6c9f0c
index 38a8293..e312d04 100644
6c9f0c
--- a/src/pae/ieee802_1x_kay.c
6c9f0c
+++ b/src/pae/ieee802_1x_kay.c
6c9f0c
@@ -491,6 +491,15 @@ ieee802_1x_kay_init_receive_sc(const struct ieee802_1x_mka_sci *psci)
6c9f0c
 }
6c9f0c
 
6c9f0c
 
6c9f0c
+static void ieee802_1x_delete_receive_sa(struct ieee802_1x_kay *kay,
6c9f0c
+					 struct receive_sa *sa)
6c9f0c
+{
6c9f0c
+	secy_disable_receive_sa(kay, sa);
6c9f0c
+	secy_delete_receive_sa(kay, sa);
6c9f0c
+	ieee802_1x_kay_deinit_receive_sa(sa);
6c9f0c
+}
6c9f0c
+
6c9f0c
+
6c9f0c
 /**
6c9f0c
  * ieee802_1x_kay_deinit_receive_sc -
6c9f0c
  **/
6c9f0c
@@ -502,10 +511,9 @@ ieee802_1x_kay_deinit_receive_sc(
6c9f0c
 
6c9f0c
 	wpa_printf(MSG_DEBUG, "KaY: Delete receive SC");
6c9f0c
 	dl_list_for_each_safe(psa, pre_sa, &psc->sa_list, struct receive_sa,
6c9f0c
-			      list)  {
6c9f0c
-		secy_disable_receive_sa(participant->kay, psa);
6c9f0c
-		ieee802_1x_kay_deinit_receive_sa(psa);
6c9f0c
-	}
6c9f0c
+			      list)
6c9f0c
+		ieee802_1x_delete_receive_sa(participant->kay, psa);
6c9f0c
+
6c9f0c
 	dl_list_del(&psc->list);
6c9f0c
 	os_free(psc);
6c9f0c
 }
6c9f0c
@@ -2270,6 +2278,16 @@ ieee802_1x_participant_send_mkpdu(
6c9f0c
 
6c9f0c
 
6c9f0c
 static void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa *psa);
6c9f0c
+
6c9f0c
+static void ieee802_1x_delete_transmit_sa(struct ieee802_1x_kay *kay,
6c9f0c
+					  struct transmit_sa *sa)
6c9f0c
+{
6c9f0c
+	secy_disable_transmit_sa(kay, sa);
6c9f0c
+	secy_delete_transmit_sa(kay, sa);
6c9f0c
+	ieee802_1x_kay_deinit_transmit_sa(sa);
6c9f0c
+}
6c9f0c
+
6c9f0c
+
6c9f0c
 /**
6c9f0c
  * ieee802_1x_participant_timer -
6c9f0c
  */
6c9f0c
@@ -2344,8 +2362,7 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx)
6c9f0c
 			dl_list_for_each_safe(txsa, pre_txsa,
6c9f0c
 					      &participant->txsc->sa_list,
6c9f0c
 					      struct transmit_sa, list) {
6c9f0c
-				secy_disable_transmit_sa(kay, txsa);
6c9f0c
-				ieee802_1x_kay_deinit_transmit_sa(txsa);
6c9f0c
+				ieee802_1x_delete_transmit_sa(kay, txsa);
6c9f0c
 			}
6c9f0c
 
6c9f0c
 			ieee802_1x_cp_connect_authenticated(kay->cp);
6c9f0c
@@ -2487,11 +2504,8 @@ ieee802_1x_kay_deinit_transmit_sc(
6c9f0c
 	struct transmit_sa *psa, *tmp;
6c9f0c
 
6c9f0c
 	wpa_printf(MSG_DEBUG, "KaY: Delete transmit SC");
6c9f0c
-	dl_list_for_each_safe(psa, tmp, &psc->sa_list, struct transmit_sa,
6c9f0c
-			      list) {
6c9f0c
-		secy_disable_transmit_sa(participant->kay, psa);
6c9f0c
-		ieee802_1x_kay_deinit_transmit_sa(psa);
6c9f0c
-	}
6c9f0c
+	dl_list_for_each_safe(psa, tmp, &psc->sa_list, struct transmit_sa, list)
6c9f0c
+		ieee802_1x_delete_transmit_sa(participant->kay, psa);
6c9f0c
 
6c9f0c
 	os_free(psc);
6c9f0c
 }
6c9f0c
@@ -2569,6 +2583,32 @@ int ieee802_1x_kay_set_old_sa_attr(struct ieee802_1x_kay *kay,
6c9f0c
 }
6c9f0c
 
6c9f0c
 
6c9f0c
+static struct transmit_sa * lookup_txsa_by_an(struct transmit_sc *txsc, u8 an)
6c9f0c
+{
6c9f0c
+	struct transmit_sa *txsa;
6c9f0c
+
6c9f0c
+	dl_list_for_each(txsa, &txsc->sa_list, struct transmit_sa, list) {
6c9f0c
+		if (txsa->an == an)
6c9f0c
+			return txsa;
6c9f0c
+	}
6c9f0c
+
6c9f0c
+	return NULL;
6c9f0c
+}
6c9f0c
+
6c9f0c
+
6c9f0c
+static struct receive_sa * lookup_rxsa_by_an(struct receive_sc *rxsc, u8 an)
6c9f0c
+{
6c9f0c
+	struct receive_sa *rxsa;
6c9f0c
+
6c9f0c
+	dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list) {
6c9f0c
+		if (rxsa->an == an)
6c9f0c
+			return rxsa;
6c9f0c
+	}
6c9f0c
+
6c9f0c
+	return NULL;
6c9f0c
+}
6c9f0c
+
6c9f0c
+
6c9f0c
 /**
6c9f0c
  * ieee802_1x_kay_create_sas -
6c9f0c
  */
6c9f0c
@@ -2603,6 +2643,9 @@ int ieee802_1x_kay_create_sas(struct ieee802_1x_kay *kay,
6c9f0c
 	}
6c9f0c
 
6c9f0c
 	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
6c9f0c
+		while ((rxsa = lookup_rxsa_by_an(rxsc, latest_sak->an)) != NULL)
6c9f0c
+			ieee802_1x_delete_receive_sa(kay, rxsa);
6c9f0c
+
6c9f0c
 		rxsa = ieee802_1x_kay_init_receive_sa(rxsc, latest_sak->an, 1,
6c9f0c
 						      latest_sak);
6c9f0c
 		if (!rxsa)
6c9f0c
@@ -2611,6 +2654,10 @@ int ieee802_1x_kay_create_sas(struct ieee802_1x_kay *kay,
6c9f0c
 		secy_create_receive_sa(kay, rxsa);
6c9f0c
 	}
6c9f0c
 
6c9f0c
+	while ((txsa = lookup_txsa_by_an(principal->txsc, latest_sak->an)) !=
6c9f0c
+	       NULL)
6c9f0c
+		ieee802_1x_delete_transmit_sa(kay, txsa);
6c9f0c
+
6c9f0c
 	txsa = ieee802_1x_kay_init_transmit_sa(principal->txsc, latest_sak->an,
6c9f0c
 					       1, latest_sak);
6c9f0c
 	if (!txsa)
6c9f0c
@@ -2644,20 +2691,16 @@ int ieee802_1x_kay_delete_sas(struct ieee802_1x_kay *kay,
6c9f0c
 	/* remove the transmit sa */
6c9f0c
 	dl_list_for_each_safe(txsa, pre_txsa, &principal->txsc->sa_list,
6c9f0c
 			      struct transmit_sa, list) {
6c9f0c
-		if (is_ki_equal(&txsa->pkey->key_identifier, ki)) {
6c9f0c
-			secy_disable_transmit_sa(kay, txsa);
6c9f0c
-			ieee802_1x_kay_deinit_transmit_sa(txsa);
6c9f0c
-		}
6c9f0c
+		if (is_ki_equal(&txsa->pkey->key_identifier, ki))
6c9f0c
+			ieee802_1x_delete_transmit_sa(kay, txsa);
6c9f0c
 	}
6c9f0c
 
6c9f0c
 	/* remove the receive sa */
6c9f0c
 	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
6c9f0c
 		dl_list_for_each_safe(rxsa, pre_rxsa, &rxsc->sa_list,
6c9f0c
 				      struct receive_sa, list) {
6c9f0c
-			if (is_ki_equal(&rxsa->pkey->key_identifier, ki)) {
6c9f0c
-				secy_disable_receive_sa(kay, rxsa);
6c9f0c
-				ieee802_1x_kay_deinit_receive_sa(rxsa);
6c9f0c
-			}
6c9f0c
+			if (is_ki_equal(&rxsa->pkey->key_identifier, ki))
6c9f0c
+				ieee802_1x_delete_receive_sa(kay, rxsa);
6c9f0c
 		}
6c9f0c
 	}
6c9f0c
 
6c9f0c
diff --git a/src/pae/ieee802_1x_kay.h b/src/pae/ieee802_1x_kay.h
6c9f0c
index e2ba180..5233cb2 100644
6c9f0c
--- a/src/pae/ieee802_1x_kay.h
6c9f0c
+++ b/src/pae/ieee802_1x_kay.h
6c9f0c
@@ -153,12 +153,14 @@ struct ieee802_1x_kay_ctx {
6c9f0c
 				 enum confidentiality_offset co);
6c9f0c
 	int (*delete_receive_sc)(void *ctx, struct receive_sc *sc);
6c9f0c
 	int (*create_receive_sa)(void *ctx, struct receive_sa *sa);
6c9f0c
+	int (*delete_receive_sa)(void *ctx, struct receive_sa *sa);
6c9f0c
 	int (*enable_receive_sa)(void *ctx, struct receive_sa *sa);
6c9f0c
 	int (*disable_receive_sa)(void *ctx, struct receive_sa *sa);
6c9f0c
 	int (*create_transmit_sc)(void *ctx, struct transmit_sc *sc,
6c9f0c
 				  enum confidentiality_offset co);
6c9f0c
 	int (*delete_transmit_sc)(void *ctx, struct transmit_sc *sc);
6c9f0c
 	int (*create_transmit_sa)(void *ctx, struct transmit_sa *sa);
6c9f0c
+	int (*delete_transmit_sa)(void *ctx, struct transmit_sa *sa);
6c9f0c
 	int (*enable_transmit_sa)(void *ctx, struct transmit_sa *sa);
6c9f0c
 	int (*disable_transmit_sa)(void *ctx, struct transmit_sa *sa);
6c9f0c
 };
6c9f0c
diff --git a/src/pae/ieee802_1x_secy_ops.c b/src/pae/ieee802_1x_secy_ops.c
6c9f0c
index b57c670..b1a9d22 100644
6c9f0c
--- a/src/pae/ieee802_1x_secy_ops.c
6c9f0c
+++ b/src/pae/ieee802_1x_secy_ops.c
6c9f0c
@@ -256,6 +256,26 @@ int secy_create_receive_sa(struct ieee802_1x_kay *kay, struct receive_sa *rxsa)
6c9f0c
 }
6c9f0c
 
6c9f0c
 
6c9f0c
+int secy_delete_receive_sa(struct ieee802_1x_kay *kay, struct receive_sa *rxsa)
6c9f0c
+{
6c9f0c
+	struct ieee802_1x_kay_ctx *ops;
6c9f0c
+
6c9f0c
+	if (!kay || !rxsa) {
6c9f0c
+		wpa_printf(MSG_ERROR, "KaY: %s params invalid", __func__);
6c9f0c
+		return -1;
6c9f0c
+	}
6c9f0c
+
6c9f0c
+	ops = kay->ctx;
6c9f0c
+	if (!ops || !ops->delete_receive_sa) {
6c9f0c
+		wpa_printf(MSG_ERROR,
6c9f0c
+			   "KaY: secy delete_receive_sa operation not supported");
6c9f0c
+		return -1;
6c9f0c
+	}
6c9f0c
+
6c9f0c
+	return ops->delete_receive_sa(ops->ctx, rxsa);
6c9f0c
+}
6c9f0c
+
6c9f0c
+
6c9f0c
 int secy_enable_receive_sa(struct ieee802_1x_kay *kay, struct receive_sa *rxsa)
6c9f0c
 {
6c9f0c
 	struct ieee802_1x_kay_ctx *ops;
6c9f0c
@@ -363,6 +383,27 @@ int secy_create_transmit_sa(struct ieee802_1x_kay *kay,
6c9f0c
 }
6c9f0c
 
6c9f0c
 
6c9f0c
+int secy_delete_transmit_sa(struct ieee802_1x_kay *kay,
6c9f0c
+			    struct transmit_sa *txsa)
6c9f0c
+{
6c9f0c
+	struct ieee802_1x_kay_ctx *ops;
6c9f0c
+
6c9f0c
+	if (!kay || !txsa) {
6c9f0c
+		wpa_printf(MSG_ERROR, "KaY: %s params invalid", __func__);
6c9f0c
+		return -1;
6c9f0c
+	}
6c9f0c
+
6c9f0c
+	ops = kay->ctx;
6c9f0c
+	if (!ops || !ops->delete_transmit_sa) {
6c9f0c
+		wpa_printf(MSG_ERROR,
6c9f0c
+			   "KaY: secy delete_transmit_sa operation not supported");
6c9f0c
+		return -1;
6c9f0c
+	}
6c9f0c
+
6c9f0c
+	return ops->delete_transmit_sa(ops->ctx, txsa);
6c9f0c
+}
6c9f0c
+
6c9f0c
+
6c9f0c
 int secy_enable_transmit_sa(struct ieee802_1x_kay *kay,
6c9f0c
 			    struct transmit_sa *txsa)
6c9f0c
 {
6c9f0c
diff --git a/src/pae/ieee802_1x_secy_ops.h b/src/pae/ieee802_1x_secy_ops.h
6c9f0c
index 59f0baa..477120b 100644
6c9f0c
--- a/src/pae/ieee802_1x_secy_ops.h
6c9f0c
+++ b/src/pae/ieee802_1x_secy_ops.h
6c9f0c
@@ -38,6 +38,7 @@ int secy_set_transmit_next_pn(struct ieee802_1x_kay *kay,
6c9f0c
 int secy_create_receive_sc(struct ieee802_1x_kay *kay, struct receive_sc *rxsc);
6c9f0c
 int secy_delete_receive_sc(struct ieee802_1x_kay *kay, struct receive_sc *rxsc);
6c9f0c
 int secy_create_receive_sa(struct ieee802_1x_kay *kay, struct receive_sa *rxsa);
6c9f0c
+int secy_delete_receive_sa(struct ieee802_1x_kay *kay, struct receive_sa *rxsa);
6c9f0c
 int secy_enable_receive_sa(struct ieee802_1x_kay *kay, struct receive_sa *rxsa);
6c9f0c
 int secy_disable_receive_sa(struct ieee802_1x_kay *kay,
6c9f0c
 			    struct receive_sa *rxsa);
6c9f0c
@@ -48,6 +49,8 @@ int secy_delete_transmit_sc(struct ieee802_1x_kay *kay,
6c9f0c
 			    struct transmit_sc *txsc);
6c9f0c
 int secy_create_transmit_sa(struct ieee802_1x_kay *kay,
6c9f0c
 			    struct transmit_sa *txsa);
6c9f0c
+int secy_delete_transmit_sa(struct ieee802_1x_kay *kay,
6c9f0c
+			    struct transmit_sa *txsa);
6c9f0c
 int secy_enable_transmit_sa(struct ieee802_1x_kay *kay,
6c9f0c
 			    struct transmit_sa *txsa);
6c9f0c
 int secy_disable_transmit_sa(struct ieee802_1x_kay *kay,
6c9f0c
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
6c9f0c
index 244e386..c9bb20d 100644
6c9f0c
--- a/wpa_supplicant/driver_i.h
6c9f0c
+++ b/wpa_supplicant/driver_i.h
6c9f0c
@@ -806,6 +806,14 @@ static inline int wpa_drv_create_receive_sa(struct wpa_supplicant *wpa_s,
6c9f0c
 	return wpa_s->driver->create_receive_sa(wpa_s->drv_priv, sa);
6c9f0c
 }
6c9f0c
 
6c9f0c
+static inline int wpa_drv_delete_receive_sa(struct wpa_supplicant *wpa_s,
6c9f0c
+					    struct receive_sa *sa)
6c9f0c
+{
6c9f0c
+	if (!wpa_s->driver->delete_receive_sa)
6c9f0c
+		return -1;
6c9f0c
+	return wpa_s->driver->delete_receive_sa(wpa_s->drv_priv, sa);
6c9f0c
+}
6c9f0c
+
6c9f0c
 static inline int wpa_drv_enable_receive_sa(struct wpa_supplicant *wpa_s,
6c9f0c
 					    struct receive_sa *sa)
6c9f0c
 {
6c9f0c
@@ -848,6 +856,14 @@ static inline int wpa_drv_create_transmit_sa(struct wpa_supplicant *wpa_s,
6c9f0c
 	return wpa_s->driver->create_transmit_sa(wpa_s->drv_priv, sa);
6c9f0c
 }
6c9f0c
 
6c9f0c
+static inline int wpa_drv_delete_transmit_sa(struct wpa_supplicant *wpa_s,
6c9f0c
+					     struct transmit_sa *sa)
6c9f0c
+{
6c9f0c
+	if (!wpa_s->driver->delete_transmit_sa)
6c9f0c
+		return -1;
6c9f0c
+	return wpa_s->driver->delete_transmit_sa(wpa_s->drv_priv, sa);
6c9f0c
+}
6c9f0c
+
6c9f0c
 static inline int wpa_drv_enable_transmit_sa(struct wpa_supplicant *wpa_s,
6c9f0c
 					     struct transmit_sa *sa)
6c9f0c
 {
6c9f0c
diff --git a/wpa_supplicant/wpas_kay.c b/wpa_supplicant/wpas_kay.c
6c9f0c
index 64364f7..e032330 100644
6c9f0c
--- a/wpa_supplicant/wpas_kay.c
6c9f0c
+++ b/wpa_supplicant/wpas_kay.c
6c9f0c
@@ -120,6 +120,12 @@ static int wpas_create_receive_sa(void *wpa_s, struct receive_sa *sa)
6c9f0c
 }
6c9f0c
 
6c9f0c
 
6c9f0c
+static int wpas_delete_receive_sa(void *wpa_s, struct receive_sa *sa)
6c9f0c
+{
6c9f0c
+	return wpa_drv_delete_receive_sa(wpa_s, sa);
6c9f0c
+}
6c9f0c
+
6c9f0c
+
6c9f0c
 static int wpas_enable_receive_sa(void *wpa_s, struct receive_sa *sa)
6c9f0c
 {
6c9f0c
 	return wpa_drv_enable_receive_sa(wpa_s, sa);
6c9f0c
@@ -152,6 +158,12 @@ static int wpas_create_transmit_sa(void *wpa_s, struct transmit_sa *sa)
6c9f0c
 }
6c9f0c
 
6c9f0c
 
6c9f0c
+static int wpas_delete_transmit_sa(void *wpa_s, struct transmit_sa *sa)
6c9f0c
+{
6c9f0c
+	return wpa_drv_delete_transmit_sa(wpa_s, sa);
6c9f0c
+}
6c9f0c
+
6c9f0c
+
6c9f0c
 static int wpas_enable_transmit_sa(void *wpa_s, struct transmit_sa *sa)
6c9f0c
 {
6c9f0c
 	return wpa_drv_enable_transmit_sa(wpa_s, sa);
6c9f0c
@@ -196,11 +208,13 @@ int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6c9f0c
 	kay_ctx->create_receive_sc = wpas_create_receive_sc;
6c9f0c
 	kay_ctx->delete_receive_sc = wpas_delete_receive_sc;
6c9f0c
 	kay_ctx->create_receive_sa = wpas_create_receive_sa;
6c9f0c
+	kay_ctx->delete_receive_sa = wpas_delete_receive_sa;
6c9f0c
 	kay_ctx->enable_receive_sa = wpas_enable_receive_sa;
6c9f0c
 	kay_ctx->disable_receive_sa = wpas_disable_receive_sa;
6c9f0c
 	kay_ctx->create_transmit_sc = wpas_create_transmit_sc;
6c9f0c
 	kay_ctx->delete_transmit_sc = wpas_delete_transmit_sc;
6c9f0c
 	kay_ctx->create_transmit_sa = wpas_create_transmit_sa;
6c9f0c
+	kay_ctx->delete_transmit_sa = wpas_delete_transmit_sa;
6c9f0c
 	kay_ctx->enable_transmit_sa = wpas_enable_transmit_sa;
6c9f0c
 	kay_ctx->disable_transmit_sa = wpas_disable_transmit_sa;
6c9f0c
 
6c9f0c
-- 
6c9f0c
2.7.4
6c9f0c