1 /*
2 * hostapd - PeerKey for Direct Link Setup (DLS)
3 * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "utils/includes.h"
10
11 #include "utils/common.h"
12 #include "utils/eloop.h"
13 #include "crypto/sha1.h"
14 #include "crypto/sha256.h"
15 #include "crypto/random.h"
16 #include "wpa_auth.h"
17 #include "wpa_auth_i.h"
18 #include "wpa_auth_ie.h"
19
20 #ifdef CONFIG_PEERKEY
21
22 struct wpa_stsl_search {
23 const u8 *addr;
24 struct wpa_state_machine *sm;
25 };
26
27
wpa_stsl_select_sta(struct wpa_state_machine * sm,void * ctx)28 static int wpa_stsl_select_sta(struct wpa_state_machine *sm, void *ctx)
29 {
30 struct wpa_stsl_search *search = ctx;
31 if (os_memcmp(search->addr, sm->addr, ETH_ALEN) == 0) {
32 search->sm = sm;
33 return 1;
34 }
35 return 0;
36 }
37
38
wpa_smk_send_error(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,const u8 * peer,u16 mui,u16 error_type)39 static void wpa_smk_send_error(struct wpa_authenticator *wpa_auth,
40 struct wpa_state_machine *sm, const u8 *peer,
41 u16 mui, u16 error_type)
42 {
43 u8 kde[2 + RSN_SELECTOR_LEN + ETH_ALEN +
44 2 + RSN_SELECTOR_LEN + sizeof(struct rsn_error_kde)];
45 u8 *pos;
46 struct rsn_error_kde error;
47
48 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
49 "Sending SMK Error");
50
51 pos = kde;
52
53 if (peer) {
54 pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN,
55 NULL, 0);
56 }
57
58 error.mui = host_to_be16(mui);
59 error.error_type = host_to_be16(error_type);
60 pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR,
61 (u8 *) &error, sizeof(error), NULL, 0);
62
63 __wpa_send_eapol(wpa_auth, sm,
64 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
65 WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_ERROR,
66 NULL, NULL, kde, pos - kde, 0, 0, 0);
67 }
68
69
wpa_smk_m1(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key,const u8 * key_data,size_t key_data_len)70 void wpa_smk_m1(struct wpa_authenticator *wpa_auth,
71 struct wpa_state_machine *sm, struct wpa_eapol_key *key,
72 const u8 *key_data, size_t key_data_len)
73 {
74 struct wpa_eapol_ie_parse kde;
75 struct wpa_stsl_search search;
76 u8 *buf, *pos;
77 size_t buf_len;
78
79 if (wpa_parse_kde_ies(key_data, key_data_len, &kde) < 0) {
80 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M1");
81 return;
82 }
83
84 if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
85 kde.mac_addr_len < ETH_ALEN) {
86 wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
87 "SMK M1");
88 return;
89 }
90
91 /* Initiator = sm->addr; Peer = kde.mac_addr */
92
93 search.addr = kde.mac_addr;
94 search.sm = NULL;
95 if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
96 0 || search.sm == NULL) {
97 wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
98 " aborted - STA not associated anymore",
99 MAC2STR(kde.mac_addr));
100 wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
101 STK_ERR_STA_NR);
102 return;
103 }
104
105 buf_len = kde.rsn_ie_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
106 buf = os_malloc(buf_len);
107 if (buf == NULL)
108 return;
109 /* Initiator RSN IE */
110 os_memcpy(buf, kde.rsn_ie, kde.rsn_ie_len);
111 pos = buf + kde.rsn_ie_len;
112 /* Initiator MAC Address */
113 pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->addr, ETH_ALEN,
114 NULL, 0);
115
116 /* SMK M2:
117 * EAPOL-Key(S=1, M=1, A=1, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
118 * MIC=MIC, DataKDs=(RSNIE_I, MAC_I KDE)
119 */
120
121 wpa_auth_logger(wpa_auth, search.sm->addr, LOGGER_DEBUG,
122 "Sending SMK M2");
123
124 __wpa_send_eapol(wpa_auth, search.sm,
125 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
126 WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE,
127 NULL, key->key_nonce, buf, pos - buf, 0, 0, 0);
128
129 os_free(buf);
130 }
131
132
wpa_send_smk_m4(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key,struct wpa_eapol_ie_parse * kde,const u8 * smk)133 static void wpa_send_smk_m4(struct wpa_authenticator *wpa_auth,
134 struct wpa_state_machine *sm,
135 struct wpa_eapol_key *key,
136 struct wpa_eapol_ie_parse *kde,
137 const u8 *smk)
138 {
139 u8 *buf, *pos;
140 size_t buf_len;
141 u32 lifetime;
142
143 /* SMK M4:
144 * EAPOL-Key(S=1, M=1, A=0, I=1, K=0, SM=1, KeyRSC=0, Nonce=PNonce,
145 * MIC=MIC, DataKDs=(MAC_I KDE, INonce KDE, SMK KDE,
146 * Lifetime KDE)
147 */
148
149 buf_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN +
150 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
151 2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
152 2 + RSN_SELECTOR_LEN + sizeof(lifetime);
153 pos = buf = os_malloc(buf_len);
154 if (buf == NULL)
155 return;
156
157 /* Initiator MAC Address */
158 pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, kde->mac_addr, ETH_ALEN,
159 NULL, 0);
160
161 /* Initiator Nonce */
162 pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, kde->nonce, WPA_NONCE_LEN,
163 NULL, 0);
164
165 /* SMK with PNonce */
166 pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
167 key->key_nonce, WPA_NONCE_LEN);
168
169 /* Lifetime */
170 lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
171 pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
172 (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
173
174 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
175 "Sending SMK M4");
176
177 __wpa_send_eapol(wpa_auth, sm,
178 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
179 WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_SMK_MESSAGE,
180 NULL, key->key_nonce, buf, pos - buf, 0, 1, 0);
181
182 os_free(buf);
183 }
184
185
wpa_send_smk_m5(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key,struct wpa_eapol_ie_parse * kde,const u8 * smk,const u8 * peer)186 static void wpa_send_smk_m5(struct wpa_authenticator *wpa_auth,
187 struct wpa_state_machine *sm,
188 struct wpa_eapol_key *key,
189 struct wpa_eapol_ie_parse *kde,
190 const u8 *smk, const u8 *peer)
191 {
192 u8 *buf, *pos;
193 size_t buf_len;
194 u32 lifetime;
195
196 /* SMK M5:
197 * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
198 * MIC=MIC, DataKDs=(RSNIE_P, MAC_P KDE, PNonce, SMK KDE,
199 * Lifetime KDE))
200 */
201
202 buf_len = kde->rsn_ie_len +
203 2 + RSN_SELECTOR_LEN + ETH_ALEN +
204 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
205 2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
206 2 + RSN_SELECTOR_LEN + sizeof(lifetime);
207 pos = buf = os_malloc(buf_len);
208 if (buf == NULL)
209 return;
210
211 /* Peer RSN IE */
212 os_memcpy(pos, kde->rsn_ie, kde->rsn_ie_len);
213 pos += kde->rsn_ie_len;
214
215 /* Peer MAC Address */
216 pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, NULL, 0);
217
218 /* PNonce */
219 pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, key->key_nonce,
220 WPA_NONCE_LEN, NULL, 0);
221
222 /* SMK and INonce */
223 pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
224 kde->nonce, WPA_NONCE_LEN);
225
226 /* Lifetime */
227 lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
228 pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
229 (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
230
231 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
232 "Sending SMK M5");
233
234 __wpa_send_eapol(wpa_auth, sm,
235 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
236 WPA_KEY_INFO_SMK_MESSAGE,
237 NULL, kde->nonce, buf, pos - buf, 0, 1, 0);
238
239 os_free(buf);
240 }
241
242
wpa_smk_m3(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key,const u8 * key_data,size_t key_data_len)243 void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
244 struct wpa_state_machine *sm, struct wpa_eapol_key *key,
245 const u8 *key_data, size_t key_data_len)
246 {
247 struct wpa_eapol_ie_parse kde;
248 struct wpa_stsl_search search;
249 u8 smk[32], buf[ETH_ALEN + 8 + 2 * WPA_NONCE_LEN], *pos;
250
251 if (wpa_parse_kde_ies(key_data, key_data_len, &kde) < 0) {
252 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M3");
253 return;
254 }
255
256 if (kde.rsn_ie == NULL ||
257 kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
258 kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN) {
259 wpa_printf(MSG_INFO, "RSN: No RSN IE, MAC address KDE, or "
260 "Nonce KDE in SMK M3");
261 return;
262 }
263
264 /* Peer = sm->addr; Initiator = kde.mac_addr;
265 * Peer Nonce = key->key_nonce; Initiator Nonce = kde.nonce */
266
267 search.addr = kde.mac_addr;
268 search.sm = NULL;
269 if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
270 0 || search.sm == NULL) {
271 wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
272 " aborted - STA not associated anymore",
273 MAC2STR(kde.mac_addr));
274 wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
275 STK_ERR_STA_NR);
276 return;
277 }
278
279 if (random_get_bytes(smk, PMK_LEN)) {
280 wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK");
281 return;
282 }
283
284 /* SMK = PRF-256(Random number, "SMK Derivation",
285 * AA || Time || INonce || PNonce)
286 */
287 os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
288 pos = buf + ETH_ALEN;
289 wpa_get_ntp_timestamp(pos);
290 pos += 8;
291 os_memcpy(pos, kde.nonce, WPA_NONCE_LEN);
292 pos += WPA_NONCE_LEN;
293 os_memcpy(pos, key->key_nonce, WPA_NONCE_LEN);
294 #ifdef CONFIG_IEEE80211W
295 sha256_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
296 smk, PMK_LEN);
297 #else /* CONFIG_IEEE80211W */
298 sha1_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
299 smk, PMK_LEN);
300 #endif /* CONFIG_IEEE80211W */
301
302 wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", smk, PMK_LEN);
303
304 wpa_send_smk_m4(wpa_auth, sm, key, &kde, smk);
305 wpa_send_smk_m5(wpa_auth, search.sm, key, &kde, smk, sm->addr);
306
307 /* Authenticator does not need SMK anymore and it is required to forget
308 * it. */
309 os_memset(smk, 0, sizeof(*smk));
310 }
311
312
wpa_smk_error(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,const u8 * key_data,size_t key_data_len)313 void wpa_smk_error(struct wpa_authenticator *wpa_auth,
314 struct wpa_state_machine *sm,
315 const u8 *key_data, size_t key_data_len)
316 {
317 struct wpa_eapol_ie_parse kde;
318 struct wpa_stsl_search search;
319 struct rsn_error_kde error;
320 u16 mui, error_type;
321
322 if (wpa_parse_kde_ies(key_data, key_data_len, &kde) < 0) {
323 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
324 return;
325 }
326
327 if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
328 kde.error == NULL || kde.error_len < sizeof(error)) {
329 wpa_printf(MSG_INFO, "RSN: No MAC address or Error KDE in "
330 "SMK Error");
331 return;
332 }
333
334 search.addr = kde.mac_addr;
335 search.sm = NULL;
336 if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
337 0 || search.sm == NULL) {
338 wpa_printf(MSG_DEBUG, "RSN: Peer STA " MACSTR " not "
339 "associated for SMK Error message from " MACSTR,
340 MAC2STR(kde.mac_addr), MAC2STR(sm->addr));
341 return;
342 }
343
344 os_memcpy(&error, kde.error, sizeof(error));
345 mui = be_to_host16(error.mui);
346 error_type = be_to_host16(error.error_type);
347 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
348 "STA reported SMK Error: Peer " MACSTR
349 " MUI %d Error Type %d",
350 MAC2STR(kde.mac_addr), mui, error_type);
351
352 wpa_smk_send_error(wpa_auth, search.sm, sm->addr, mui, error_type);
353 }
354
355 #endif /* CONFIG_PEERKEY */
356