summaryrefslogtreecommitdiff
path: root/package/network/services/hostapd/patches/007-Extend-protection-of-GTK-IGTK-reinstallation-of-WNM-.patch
blob: 650bf43e9144842fb8f082f404247f9ad1250194 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
From: Jouni Malinen <j@w1.fi>
Date: Sun, 1 Oct 2017 12:12:24 +0300
Subject: [PATCH] Extend protection of GTK/IGTK reinstallation of WNM-Sleep
 Mode cases

This extends the protection to track last configured GTK/IGTK value
separately from EAPOL-Key frames and WNM-Sleep Mode frames to cover a
corner case where these two different mechanisms may get used when the
GTK/IGTK has changed and tracking a single value is not sufficient to
detect a possible key reconfiguration.

Signed-off-by: Jouni Malinen <j@w1.fi>
---

--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -780,14 +780,17 @@ struct wpa_gtk_data {
 
 static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
 				      const struct wpa_gtk_data *gd,
-				      const u8 *key_rsc)
+				      const u8 *key_rsc, int wnm_sleep)
 {
 	const u8 *_gtk = gd->gtk;
 	u8 gtk_buf[32];
 
 	/* Detect possible key reinstallation */
-	if (sm->gtk.gtk_len == (size_t) gd->gtk_len &&
-	    os_memcmp(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len) == 0) {
+	if ((sm->gtk.gtk_len == (size_t) gd->gtk_len &&
+	     os_memcmp(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len) == 0) ||
+	    (sm->gtk_wnm_sleep.gtk_len == (size_t) gd->gtk_len &&
+	     os_memcmp(sm->gtk_wnm_sleep.gtk, gd->gtk,
+		       sm->gtk_wnm_sleep.gtk_len) == 0)) {
 		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
 			"WPA: Not reinstalling already in-use GTK to the driver (keyidx=%d tx=%d len=%d)",
 			gd->keyidx, gd->tx, gd->gtk_len);
@@ -828,8 +831,14 @@ static int wpa_supplicant_install_gtk(st
 	}
 	os_memset(gtk_buf, 0, sizeof(gtk_buf));
 
-	sm->gtk.gtk_len = gd->gtk_len;
-	os_memcpy(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len);
+	if (wnm_sleep) {
+		sm->gtk_wnm_sleep.gtk_len = gd->gtk_len;
+		os_memcpy(sm->gtk_wnm_sleep.gtk, gd->gtk,
+			  sm->gtk_wnm_sleep.gtk_len);
+	} else {
+		sm->gtk.gtk_len = gd->gtk_len;
+		os_memcpy(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len);
+	}
 
 	return 0;
 }
@@ -923,7 +932,7 @@ static int wpa_supplicant_pairwise_gtk(s
 	    (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
 					       gtk_len, gtk_len,
 					       &gd.key_rsc_len, &gd.alg) ||
-	     wpa_supplicant_install_gtk(sm, &gd, key_rsc))) {
+	     wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0))) {
 		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
 			"RSN: Failed to install GTK");
 		os_memset(&gd, 0, sizeof(gd));
@@ -939,14 +948,18 @@ static int wpa_supplicant_pairwise_gtk(s
 
 #ifdef CONFIG_IEEE80211W
 static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
-				       const struct wpa_igtk_kde *igtk)
+				       const struct wpa_igtk_kde *igtk,
+				       int wnm_sleep)
 {
 	size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher);
 	u16 keyidx = WPA_GET_LE16(igtk->keyid);
 
 	/* Detect possible key reinstallation */
-	if (sm->igtk.igtk_len == len &&
-	    os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) {
+	if ((sm->igtk.igtk_len == len &&
+	     os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) ||
+	    (sm->igtk_wnm_sleep.igtk_len == len &&
+	     os_memcmp(sm->igtk_wnm_sleep.igtk, igtk->igtk,
+		       sm->igtk_wnm_sleep.igtk_len) == 0)) {
 		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
 			"WPA: Not reinstalling already in-use IGTK to the driver (keyidx=%d)",
 			keyidx);
@@ -971,8 +984,14 @@ static int wpa_supplicant_install_igtk(s
 		return -1;
 	}
 
-	sm->igtk.igtk_len = len;
-	os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len);
+	if (wnm_sleep) {
+		sm->igtk_wnm_sleep.igtk_len = len;
+		os_memcpy(sm->igtk_wnm_sleep.igtk, igtk->igtk,
+			  sm->igtk_wnm_sleep.igtk_len);
+	} else {
+		sm->igtk.igtk_len = len;
+		os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len);
+	}
 
 	return 0;
 }
@@ -995,7 +1014,7 @@ static int ieee80211w_set_keys(struct wp
 			return -1;
 
 		igtk = (const struct wpa_igtk_kde *) ie->igtk;
-		if (wpa_supplicant_install_igtk(sm, igtk) < 0)
+		if (wpa_supplicant_install_igtk(sm, igtk, 0) < 0)
 			return -1;
 	}
 
@@ -1641,7 +1660,7 @@ static void wpa_supplicant_process_1_of_
 	if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
 		key_rsc = null_rsc;
 
-	if (wpa_supplicant_install_gtk(sm, &gd, key_rsc) ||
+	if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0) ||
 	    wpa_supplicant_send_2_of_2(sm, key, ver, key_info) < 0)
 		goto failed;
 	os_memset(&gd, 0, sizeof(gd));
@@ -2540,8 +2559,10 @@ void wpa_sm_notify_assoc(struct wpa_sm *
 		sm->tptk_set = 0;
 		os_memset(&sm->tptk, 0, sizeof(sm->tptk));
 		os_memset(&sm->gtk, 0, sizeof(sm->gtk));
+		os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep));
 #ifdef CONFIG_IEEE80211W
 		os_memset(&sm->igtk, 0, sizeof(sm->igtk));
+		os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep));
 #endif /* CONFIG_IEEE80211W */
 	}
 
@@ -3095,8 +3116,10 @@ void wpa_sm_drop_sa(struct wpa_sm *sm)
 	os_memset(&sm->ptk, 0, sizeof(sm->ptk));
 	os_memset(&sm->tptk, 0, sizeof(sm->tptk));
 	os_memset(&sm->gtk, 0, sizeof(sm->gtk));
+	os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep));
 #ifdef CONFIG_IEEE80211W
 	os_memset(&sm->igtk, 0, sizeof(sm->igtk));
+	os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep));
 #endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_IEEE80211R
 	os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
@@ -3161,7 +3184,7 @@ int wpa_wnmsleep_install_key(struct wpa_
 
 		wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)",
 				gd.gtk, gd.gtk_len);
-		if (wpa_supplicant_install_gtk(sm, &gd, key_rsc)) {
+		if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 1)) {
 			os_memset(&gd, 0, sizeof(gd));
 			wpa_printf(MSG_DEBUG, "Failed to install the GTK in "
 				   "WNM mode");
@@ -3173,7 +3196,7 @@ int wpa_wnmsleep_install_key(struct wpa_
 		const struct wpa_igtk_kde *igtk;
 
 		igtk = (const struct wpa_igtk_kde *) (buf + 2);
-		if (wpa_supplicant_install_igtk(sm, igtk) < 0)
+		if (wpa_supplicant_install_igtk(sm, igtk, 1) < 0)
 			return -1;
 #endif /* CONFIG_IEEE80211W */
 	} else {
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -32,8 +32,10 @@ struct wpa_sm {
 	int rx_replay_counter_set;
 	u8 request_counter[WPA_REPLAY_COUNTER_LEN];
 	struct wpa_gtk gtk;
+	struct wpa_gtk gtk_wnm_sleep;
 #ifdef CONFIG_IEEE80211W
 	struct wpa_igtk igtk;
+	struct wpa_igtk igtk_wnm_sleep;
 #endif /* CONFIG_IEEE80211W */
 
 	struct eapol_sm *eapol; /* EAPOL state machine from upper level code */