Merge branch 'vendor/GCC47'
[dragonfly.git] / contrib / hostapd / src / rsn_supp / peerkey.c
1 /*
2  * WPA Supplicant - PeerKey for Direct Link Setup (DLS)
3  * Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #ifdef CONFIG_PEERKEY
18
19 #include "common.h"
20 #include "sha1.h"
21 #include "sha256.h"
22 #include "eloop.h"
23 #include "wpa.h"
24 #include "wpa_i.h"
25 #include "wpa_ie.h"
26 #include "ieee802_11_defs.h"
27 #include "peerkey.h"
28
29
30 static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len)
31 {
32         os_memcpy(pos, ie, ie_len);
33         return pos + ie_len;
34 }
35
36
37 static u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len)
38 {
39         *pos++ = WLAN_EID_VENDOR_SPECIFIC;
40         *pos++ = RSN_SELECTOR_LEN + data_len;
41         RSN_SELECTOR_PUT(pos, kde);
42         pos += RSN_SELECTOR_LEN;
43         os_memcpy(pos, data, data_len);
44         pos += data_len;
45         return pos;
46 }
47
48
49 static void wpa_supplicant_smk_timeout(void *eloop_ctx, void *timeout_ctx)
50 {
51 #if 0
52         struct wpa_sm *sm = eloop_ctx;
53         struct wpa_peerkey *peerkey = timeout_ctx;
54 #endif
55         /* TODO: time out SMK and any STK that was generated using this SMK */
56 }
57
58
59 static void wpa_supplicant_peerkey_free(struct wpa_sm *sm,
60                                         struct wpa_peerkey *peerkey)
61 {
62         eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey);
63         os_free(peerkey);
64 }
65
66
67 static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst,
68                                          const u8 *peer,
69                                          u16 mui, u16 error_type, int ver)
70 {
71         size_t rlen;
72         struct wpa_eapol_key *err;
73         struct rsn_error_kde error;
74         u8 *rbuf, *pos;
75         size_t kde_len;
76         u16 key_info;
77
78         kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error);
79         if (peer)
80                 kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN;
81
82         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
83                                   NULL, sizeof(*err) + kde_len, &rlen,
84                                   (void *) &err);
85         if (rbuf == NULL)
86                 return -1;
87
88         err->type = EAPOL_KEY_TYPE_RSN;
89         key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
90                 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR |
91                 WPA_KEY_INFO_REQUEST;
92         WPA_PUT_BE16(err->key_info, key_info);
93         WPA_PUT_BE16(err->key_length, 0);
94         os_memcpy(err->replay_counter, sm->request_counter,
95                   WPA_REPLAY_COUNTER_LEN);
96         inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
97
98         WPA_PUT_BE16(err->key_data_length, (u16) kde_len);
99         pos = (u8 *) (err + 1);
100
101         if (peer) {
102                 /* Peer MAC Address KDE */
103                 pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);
104         }
105
106         /* Error KDE */
107         error.mui = host_to_be16(mui);
108         error.error_type = host_to_be16(error_type);
109         wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error));
110
111         if (peer) {
112                 wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer "
113                            MACSTR " mui %d error_type %d)",
114                            MAC2STR(peer), mui, error_type);
115         } else {
116                 wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error "
117                            "(mui %d error_type %d)", mui, error_type);
118         }
119
120         wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL,
121                            rbuf, rlen, err->key_mic);
122
123         return 0;
124 }
125
126
127 static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm,
128                                       const unsigned char *src_addr,
129                                       const struct wpa_eapol_key *key,
130                                       int ver, struct wpa_peerkey *peerkey)
131 {
132         size_t rlen;
133         struct wpa_eapol_key *reply;
134         u8 *rbuf, *pos;
135         size_t kde_len;
136         u16 key_info;
137
138         /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */
139         kde_len = peerkey->rsnie_p_len +
140                 2 + RSN_SELECTOR_LEN + ETH_ALEN +
141                 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN;
142
143         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
144                                   NULL, sizeof(*reply) + kde_len, &rlen,
145                                   (void *) &reply);
146         if (rbuf == NULL)
147                 return -1;
148
149         reply->type = EAPOL_KEY_TYPE_RSN;
150         key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
151                 WPA_KEY_INFO_SECURE;
152         WPA_PUT_BE16(reply->key_info, key_info);
153         WPA_PUT_BE16(reply->key_length, 0);
154         os_memcpy(reply->replay_counter, key->replay_counter,
155                   WPA_REPLAY_COUNTER_LEN);
156
157         os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN);
158
159         WPA_PUT_BE16(reply->key_data_length, (u16) kde_len);
160         pos = (u8 *) (reply + 1);
161
162         /* Peer RSN IE */
163         pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len);
164
165         /* Initiator MAC Address KDE */
166         pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN);
167
168         /* Initiator Nonce */
169         wpa_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN);
170
171         wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3");
172         wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL,
173                            rbuf, rlen, reply->key_mic);
174
175         return 0;
176 }
177
178
179 static int wpa_supplicant_process_smk_m2(
180         struct wpa_sm *sm, const unsigned char *src_addr,
181         const struct wpa_eapol_key *key, size_t extra_len, int ver)
182 {
183         struct wpa_peerkey *peerkey;
184         struct wpa_eapol_ie_parse kde;
185         struct wpa_ie_data ie;
186         int cipher;
187         struct rsn_ie_hdr *hdr;
188         u8 *pos;
189
190         wpa_printf(MSG_DEBUG, "RSN: Received SMK M2");
191
192         if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
193                 wpa_printf(MSG_INFO, "RSN: SMK handshake not allowed for "
194                            "the current network");
195                 return -1;
196         }
197
198         if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
199             0) {
200                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M2");
201                 return -1;
202         }
203
204         if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
205             kde.mac_addr_len < ETH_ALEN) {
206                 wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
207                            "SMK M2");
208                 return -1;
209         }
210
211         wpa_printf(MSG_DEBUG, "RSN: SMK M2 - SMK initiator " MACSTR,
212                    MAC2STR(kde.mac_addr));
213
214         if (kde.rsn_ie_len > PEERKEY_MAX_IE_LEN) {
215                 wpa_printf(MSG_INFO, "RSN: Too long Initiator RSN IE in SMK "
216                            "M2");
217                 return -1;
218         }
219
220         if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
221                 wpa_printf(MSG_INFO, "RSN: Failed to parse RSN IE in SMK M2");
222                 return -1;
223         }
224
225         cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher;
226         if (cipher & WPA_CIPHER_CCMP) {
227                 wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey");
228                 cipher = WPA_CIPHER_CCMP;
229         } else if (cipher & WPA_CIPHER_TKIP) {
230                 wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey");
231                 cipher = WPA_CIPHER_TKIP;
232         } else {
233                 wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2");
234                 wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr,
235                                               STK_MUI_SMK, STK_ERR_CPHR_NS,
236                                               ver);
237                 return -1;
238         }
239
240         /* TODO: find existing entry and if found, use that instead of adding
241          * a new one; how to handle the case where both ends initiate at the
242          * same time? */
243         peerkey = os_zalloc(sizeof(*peerkey));
244         if (peerkey == NULL)
245                 return -1;
246         os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN);
247         os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN);
248         os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);
249         peerkey->rsnie_i_len = kde.rsn_ie_len;
250         peerkey->cipher = cipher;
251 #ifdef CONFIG_IEEE80211W
252         if (ie.key_mgmt & (WPA_KEY_MGMT_IEEE8021X_SHA256 |
253                            WPA_KEY_MGMT_PSK_SHA256))
254                 peerkey->use_sha256 = 1;
255 #endif /* CONFIG_IEEE80211W */
256
257         if (os_get_random(peerkey->pnonce, WPA_NONCE_LEN)) {
258                 wpa_msg(sm->ctx->ctx, MSG_WARNING,
259                         "WPA: Failed to get random data for PNonce");
260                 wpa_supplicant_peerkey_free(sm, peerkey);
261                 return -1;
262         }
263
264         hdr = (struct rsn_ie_hdr *) peerkey->rsnie_p;
265         hdr->elem_id = WLAN_EID_RSN;
266         WPA_PUT_LE16(hdr->version, RSN_VERSION);
267         pos = (u8 *) (hdr + 1);
268         /* Group Suite can be anything for SMK RSN IE; receiver will just
269          * ignore it. */
270         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
271         pos += RSN_SELECTOR_LEN;
272         /* Include only the selected cipher in pairwise cipher suite */
273         WPA_PUT_LE16(pos, 1);
274         pos += 2;
275         if (cipher == WPA_CIPHER_CCMP)
276                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
277         else if (cipher == WPA_CIPHER_TKIP)
278                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
279         pos += RSN_SELECTOR_LEN;
280
281         hdr->len = (pos - peerkey->rsnie_p) - 2;
282         peerkey->rsnie_p_len = pos - peerkey->rsnie_p;
283         wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",
284                     peerkey->rsnie_p, peerkey->rsnie_p_len);
285
286         wpa_supplicant_send_smk_m3(sm, src_addr, key, ver, peerkey);
287
288         peerkey->next = sm->peerkey;
289         sm->peerkey = peerkey;
290
291         return 0;
292 }
293
294
295 /**
296  * rsn_smkid - Derive SMK identifier
297  * @smk: Station master key (32 bytes)
298  * @pnonce: Peer Nonce
299  * @mac_p: Peer MAC address
300  * @inonce: Initiator Nonce
301  * @mac_i: Initiator MAC address
302  * @use_sha256: Whether to use SHA256-based KDF
303  *
304  * 8.5.1.4 Station to station (STK) key hierarchy
305  * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I)
306  */
307 static void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p,
308                       const u8 *inonce, const u8 *mac_i, u8 *smkid,
309                       int use_sha256)
310 {
311         char *title = "SMK Name";
312         const u8 *addr[5];
313         const size_t len[5] = { 8, WPA_NONCE_LEN, ETH_ALEN, WPA_NONCE_LEN,
314                                 ETH_ALEN };
315         unsigned char hash[SHA256_MAC_LEN];
316
317         addr[0] = (u8 *) title;
318         addr[1] = pnonce;
319         addr[2] = mac_p;
320         addr[3] = inonce;
321         addr[4] = mac_i;
322
323 #ifdef CONFIG_IEEE80211W
324         if (use_sha256)
325                 hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash);
326         else
327 #endif /* CONFIG_IEEE80211W */
328                 hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash);
329         os_memcpy(smkid, hash, PMKID_LEN);
330 }
331
332
333 static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm,
334                                            struct wpa_peerkey *peerkey)
335 {
336         size_t mlen;
337         struct wpa_eapol_key *msg;
338         u8 *mbuf;
339         size_t kde_len;
340         u16 key_info, ver;
341
342         kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
343
344         mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
345                                   sizeof(*msg) + kde_len, &mlen,
346                                   (void *) &msg);
347         if (mbuf == NULL)
348                 return;
349
350         msg->type = EAPOL_KEY_TYPE_RSN;
351
352         if (peerkey->cipher == WPA_CIPHER_CCMP)
353                 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
354         else
355                 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
356
357         key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK;
358         WPA_PUT_BE16(msg->key_info, key_info);
359
360         if (peerkey->cipher == WPA_CIPHER_CCMP)
361                 WPA_PUT_BE16(msg->key_length, 16);
362         else
363                 WPA_PUT_BE16(msg->key_length, 32);
364
365         os_memcpy(msg->replay_counter, peerkey->replay_counter,
366                   WPA_REPLAY_COUNTER_LEN);
367         inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN);
368
369         WPA_PUT_BE16(msg->key_data_length, kde_len);
370         wpa_add_kde((u8 *) (msg + 1), RSN_KEY_DATA_PMKID,
371                     peerkey->smkid, PMKID_LEN);
372
373         if (os_get_random(peerkey->inonce, WPA_NONCE_LEN)) {
374                 wpa_msg(sm->ctx->ctx, MSG_WARNING,
375                         "RSN: Failed to get random data for INonce (STK)");
376                 os_free(mbuf);
377                 return;
378         }
379         wpa_hexdump(MSG_DEBUG, "RSN: INonce for STK 4-Way Handshake",
380                     peerkey->inonce, WPA_NONCE_LEN);
381         os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
382
383         wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR,
384                    MAC2STR(peerkey->addr));
385         wpa_eapol_key_send(sm, NULL, ver, peerkey->addr, ETH_P_EAPOL,
386                            mbuf, mlen, NULL);
387 }
388
389
390 static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm,
391                                            struct wpa_peerkey *peerkey)
392 {
393         size_t mlen;
394         struct wpa_eapol_key *msg;
395         u8 *mbuf, *pos;
396         size_t kde_len;
397         u16 key_info, ver;
398         be32 lifetime;
399
400         kde_len = peerkey->rsnie_i_len +
401                 2 + RSN_SELECTOR_LEN + sizeof(lifetime);
402
403         mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
404                                   sizeof(*msg) + kde_len, &mlen,
405                                   (void *) &msg);
406         if (mbuf == NULL)
407                 return;
408
409         msg->type = EAPOL_KEY_TYPE_RSN;
410
411         if (peerkey->cipher == WPA_CIPHER_CCMP)
412                 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
413         else
414                 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
415
416         key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK |
417                 WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
418         WPA_PUT_BE16(msg->key_info, key_info);
419
420         if (peerkey->cipher == WPA_CIPHER_CCMP)
421                 WPA_PUT_BE16(msg->key_length, 16);
422         else
423                 WPA_PUT_BE16(msg->key_length, 32);
424
425         os_memcpy(msg->replay_counter, peerkey->replay_counter,
426                   WPA_REPLAY_COUNTER_LEN);
427         inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN);
428
429         WPA_PUT_BE16(msg->key_data_length, kde_len);
430         pos = (u8 *) (msg + 1);
431         pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);
432         lifetime = host_to_be32(peerkey->lifetime);
433         wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
434                     (u8 *) &lifetime, sizeof(lifetime));
435
436         os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
437
438         wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR,
439                    MAC2STR(peerkey->addr));
440         wpa_eapol_key_send(sm, peerkey->stk.kck, ver, peerkey->addr,
441                            ETH_P_EAPOL, mbuf, mlen, msg->key_mic);
442 }
443
444
445 static int wpa_supplicant_process_smk_m4(struct wpa_peerkey *peerkey,
446                                          struct wpa_eapol_ie_parse *kde)
447 {
448         wpa_printf(MSG_DEBUG, "RSN: Received SMK M4 (Initiator " MACSTR ")",
449                    MAC2STR(kde->mac_addr));
450
451         if (os_memcmp(kde->smk + PMK_LEN, peerkey->pnonce, WPA_NONCE_LEN) != 0)
452         {
453                 wpa_printf(MSG_INFO, "RSN: PNonce in SMK KDE does not "
454                            "match with the one used in SMK M3");
455                 return -1;
456         }
457
458         if (os_memcmp(kde->nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) {
459                 wpa_printf(MSG_INFO, "RSN: INonce in SMK M4 did not "
460                            "match with the one received in SMK M2");
461                 return -1;
462         }
463
464         return 0;
465 }
466
467
468 static int wpa_supplicant_process_smk_m5(struct wpa_sm *sm,
469                                          const unsigned char *src_addr,
470                                          const struct wpa_eapol_key *key,
471                                          int ver,
472                                          struct wpa_peerkey *peerkey,
473                                          struct wpa_eapol_ie_parse *kde)
474 {
475         int cipher;
476         struct wpa_ie_data ie;
477
478         wpa_printf(MSG_DEBUG, "RSN: Received SMK M5 (Peer " MACSTR ")",
479                    MAC2STR(kde->mac_addr));
480         if (kde->rsn_ie == NULL || kde->rsn_ie_len > PEERKEY_MAX_IE_LEN ||
481             wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0) {
482                 wpa_printf(MSG_INFO, "RSN: No RSN IE in SMK M5");
483                 /* TODO: abort negotiation */
484                 return -1;
485         }
486
487         if (os_memcmp(key->key_nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) {
488                 wpa_printf(MSG_INFO, "RSN: Key Nonce in SMK M5 does "
489                            "not match with INonce used in SMK M1");
490                 return -1;
491         }
492
493         if (os_memcmp(kde->smk + PMK_LEN, peerkey->inonce, WPA_NONCE_LEN) != 0)
494         {
495                 wpa_printf(MSG_INFO, "RSN: INonce in SMK KDE does not "
496                            "match with the one used in SMK M1");
497                 return -1;
498         }
499
500         os_memcpy(peerkey->rsnie_p, kde->rsn_ie, kde->rsn_ie_len);
501         peerkey->rsnie_p_len = kde->rsn_ie_len;
502         os_memcpy(peerkey->pnonce, kde->nonce, WPA_NONCE_LEN);
503
504         cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher;
505         if (cipher & WPA_CIPHER_CCMP) {
506                 wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey");
507                 peerkey->cipher = WPA_CIPHER_CCMP;
508         } else if (cipher & WPA_CIPHER_TKIP) {
509                 wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey");
510                 peerkey->cipher = WPA_CIPHER_TKIP;
511         } else {
512                 wpa_printf(MSG_INFO, "RSN: SMK Peer STA " MACSTR " selected "
513                            "unacceptable cipher", MAC2STR(kde->mac_addr));
514                 wpa_supplicant_send_smk_error(sm, src_addr, kde->mac_addr,
515                                               STK_MUI_SMK, STK_ERR_CPHR_NS,
516                                               ver);
517                 /* TODO: abort negotiation */
518                 return -1;
519         }
520
521         return 0;
522 }
523
524
525 static int wpa_supplicant_process_smk_m45(
526         struct wpa_sm *sm, const unsigned char *src_addr,
527         const struct wpa_eapol_key *key, size_t extra_len, int ver)
528 {
529         struct wpa_peerkey *peerkey;
530         struct wpa_eapol_ie_parse kde;
531         u32 lifetime;
532         struct os_time now;
533
534         if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
535                 wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
536                            "the current network");
537                 return -1;
538         }
539
540         if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
541             0) {
542                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5");
543                 return -1;
544         }
545
546         if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
547             kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN ||
548             kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN ||
549             kde.lifetime == NULL || kde.lifetime_len < 4) {
550                 wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or "
551                            "Lifetime KDE in SMK M4/M5");
552                 return -1;
553         }
554
555         for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
556                 if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 &&
557                     os_memcmp(peerkey->initiator ? peerkey->inonce :
558                            peerkey->pnonce,
559                            key->key_nonce, WPA_NONCE_LEN) == 0)
560                         break;
561         }
562         if (peerkey == NULL) {
563                 wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found "
564                            "for SMK M4/M5: peer " MACSTR,
565                            MAC2STR(kde.mac_addr));
566                 return -1;
567         }
568
569         if (peerkey->initiator) {
570                 if (wpa_supplicant_process_smk_m5(sm, src_addr, key, ver,
571                                                   peerkey, &kde) < 0)
572                         return -1;
573         } else {
574                 if (wpa_supplicant_process_smk_m4(peerkey, &kde) < 0)
575                         return -1;
576         }
577
578         os_memcpy(peerkey->smk, kde.smk, PMK_LEN);
579         peerkey->smk_complete = 1;
580         wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN);
581         lifetime = WPA_GET_BE32(kde.lifetime);
582         wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime);
583         if (lifetime > 1000000000)
584                 lifetime = 1000000000; /* avoid overflowing expiration time */
585         peerkey->lifetime = lifetime;
586         os_get_time(&now);
587         peerkey->expiration = now.sec + lifetime;
588         eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout,
589                                sm, peerkey);
590
591         if (peerkey->initiator) {
592                 rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr,
593                           peerkey->inonce, sm->own_addr, peerkey->smkid,
594                           peerkey->use_sha256);
595                 wpa_supplicant_send_stk_1_of_4(sm, peerkey);
596         } else {
597                 rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr,
598                           peerkey->inonce, peerkey->addr, peerkey->smkid,
599                           peerkey->use_sha256);
600         }
601         wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN);
602
603         return 0;
604 }
605
606
607 static int wpa_supplicant_process_smk_error(
608         struct wpa_sm *sm, const unsigned char *src_addr,
609         const struct wpa_eapol_key *key, size_t extra_len)
610 {
611         struct wpa_eapol_ie_parse kde;
612         struct rsn_error_kde error;
613         u8 peer[ETH_ALEN];
614         u16 error_type;
615
616         wpa_printf(MSG_DEBUG, "RSN: Received SMK Error");
617
618         if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
619                 wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
620                            "the current network");
621                 return -1;
622         }
623
624         if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
625             0) {
626                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
627                 return -1;
628         }
629
630         if (kde.error == NULL || kde.error_len < sizeof(error)) {
631                 wpa_printf(MSG_INFO, "RSN: No Error KDE in SMK Error");
632                 return -1;
633         }
634
635         if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN)
636                 os_memcpy(peer, kde.mac_addr, ETH_ALEN);
637         os_memcpy(&error, kde.error, sizeof(error));
638         error_type = be_to_host16(error.error_type);
639         wpa_msg(sm->ctx->ctx, MSG_INFO,
640                 "RSN: SMK Error KDE received: MUI %d error_type %d peer "
641                 MACSTR,
642                 be_to_host16(error.mui), error_type,
643                 MAC2STR(peer));
644
645         if (kde.mac_addr &&
646             (error_type == STK_ERR_STA_NR || error_type == STK_ERR_STA_NRSN ||
647              error_type == STK_ERR_CPHR_NS)) {
648                 struct wpa_peerkey *peerkey;
649
650                 for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
651                         if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) ==
652                             0)
653                                 break;
654                 }
655                 if (peerkey == NULL) {
656                         wpa_printf(MSG_DEBUG, "RSN: No matching SMK handshake "
657                                    "found for SMK Error");
658                         return -1;
659                 }
660                 /* TODO: abort SMK/STK handshake and remove all related keys */
661         }
662
663         return 0;
664 }
665
666
667 static void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm,
668                                               struct wpa_peerkey *peerkey,
669                                               const struct wpa_eapol_key *key,
670                                               u16 ver)
671 {
672         struct wpa_eapol_ie_parse ie;
673         const u8 *kde;
674         size_t len, kde_buf_len;
675         struct wpa_ptk *stk;
676         u8 buf[8], *kde_buf, *pos;
677         be32 lifetime;
678
679         wpa_printf(MSG_DEBUG, "RSN: RX message 1 of STK 4-Way Handshake from "
680                    MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
681
682         os_memset(&ie, 0, sizeof(ie));
683
684         /* RSN: msg 1/4 should contain SMKID for the selected SMK */
685         kde = (const u8 *) (key + 1);
686         len = WPA_GET_BE16(key->key_data_length);
687         wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", kde, len);
688         if (wpa_supplicant_parse_ies(kde, len, &ie) < 0 || ie.pmkid == NULL) {
689                 wpa_printf(MSG_DEBUG, "RSN: No SMKID in STK 1/4");
690                 return;
691         }
692         if (os_memcmp(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) {
693                 wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 1/4",
694                             ie.pmkid, PMKID_LEN);
695                 return;
696         }
697
698         if (os_get_random(peerkey->pnonce, WPA_NONCE_LEN)) {
699                 wpa_msg(sm->ctx->ctx, MSG_WARNING,
700                         "RSN: Failed to get random data for PNonce");
701                 return;
702         }
703         wpa_hexdump(MSG_DEBUG, "WPA: Renewed PNonce",
704                     peerkey->pnonce, WPA_NONCE_LEN);
705
706         /* Calculate STK which will be stored as a temporary STK until it has
707          * been verified when processing message 3/4. */
708         stk = &peerkey->tstk;
709         wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion",
710                        sm->own_addr, peerkey->addr,
711                        peerkey->pnonce, key->key_nonce,
712                        (u8 *) stk, sizeof(*stk),
713                        peerkey->use_sha256);
714         /* Supplicant: swap tx/rx Mic keys */
715         os_memcpy(buf, stk->u.auth.tx_mic_key, 8);
716         os_memcpy(stk->u.auth.tx_mic_key, stk->u.auth.rx_mic_key, 8);
717         os_memcpy(stk->u.auth.rx_mic_key, buf, 8);
718         peerkey->tstk_set = 1;
719
720         kde_buf_len = peerkey->rsnie_p_len +
721                 2 + RSN_SELECTOR_LEN + sizeof(lifetime) +
722                 2 + RSN_SELECTOR_LEN + PMKID_LEN;
723         kde_buf = os_malloc(kde_buf_len);
724         if (kde_buf == NULL)
725                 return;
726         pos = kde_buf;
727         pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len);
728         lifetime = host_to_be32(peerkey->lifetime);
729         pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
730                           (u8 *) &lifetime, sizeof(lifetime));
731         wpa_add_kde(pos, RSN_KEY_DATA_PMKID, peerkey->smkid, PMKID_LEN);
732
733         if (wpa_supplicant_send_2_of_4(sm, peerkey->addr, key, ver,
734                                        peerkey->pnonce, kde_buf, kde_buf_len,
735                                        stk)) {
736                 os_free(kde_buf);
737                 return;
738         }
739         os_free(kde_buf);
740
741         os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN);
742 }
743
744
745 static void wpa_supplicant_update_smk_lifetime(struct wpa_sm *sm,
746                                                struct wpa_peerkey *peerkey,
747                                                struct wpa_eapol_ie_parse *kde)
748 {
749         u32 lifetime;
750         struct os_time now;
751
752         if (kde->lifetime == NULL || kde->lifetime_len < sizeof(lifetime))
753                 return;
754
755         lifetime = WPA_GET_BE32(kde->lifetime);
756
757         if (lifetime >= peerkey->lifetime) {
758                 wpa_printf(MSG_DEBUG, "RSN: Peer used SMK lifetime %u seconds "
759                            "which is larger than or equal to own value %u "
760                            "seconds - ignored", lifetime, peerkey->lifetime);
761                 return;
762         }
763
764         wpa_printf(MSG_DEBUG, "RSN: Peer used shorter SMK lifetime %u seconds "
765                    "(own was %u seconds) - updated",
766                    lifetime, peerkey->lifetime);
767         peerkey->lifetime = lifetime;
768
769         os_get_time(&now);
770         peerkey->expiration = now.sec + lifetime;
771         eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey);
772         eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout,
773                                sm, peerkey);
774 }
775
776
777 static void wpa_supplicant_process_stk_2_of_4(struct wpa_sm *sm,
778                                               struct wpa_peerkey *peerkey,
779                                               const struct wpa_eapol_key *key,
780                                               u16 ver)
781 {
782         struct wpa_eapol_ie_parse kde;
783         const u8 *keydata;
784         size_t len;
785
786         wpa_printf(MSG_DEBUG, "RSN: RX message 2 of STK 4-Way Handshake from "
787                    MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
788
789         os_memset(&kde, 0, sizeof(kde));
790
791         /* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE
792          * from the peer. It may also include Lifetime KDE. */
793         keydata = (const u8 *) (key + 1);
794         len = WPA_GET_BE16(key->key_data_length);
795         wpa_hexdump(MSG_DEBUG, "RSN: msg 2/4 key data", keydata, len);
796         if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0 ||
797             kde.pmkid == NULL || kde.rsn_ie == NULL) {
798                 wpa_printf(MSG_DEBUG, "RSN: No SMKID or RSN IE in STK 2/4");
799                 return;
800         }
801
802         if (os_memcmp(kde.pmkid, peerkey->smkid, PMKID_LEN) != 0) {
803                 wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 2/4",
804                             kde.pmkid, PMKID_LEN);
805                 return;
806         }
807
808         if (kde.rsn_ie_len != peerkey->rsnie_p_len ||
809             os_memcmp(kde.rsn_ie, peerkey->rsnie_p, kde.rsn_ie_len) != 0) {
810                 wpa_printf(MSG_INFO, "RSN: Peer RSN IE in SMK and STK "
811                            "handshakes did not match");
812                 wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in SMK handshake",
813                             peerkey->rsnie_p, peerkey->rsnie_p_len);
814                 wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in STK handshake",
815                             kde.rsn_ie, kde.rsn_ie_len);
816                 return;
817         }
818
819         wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde);
820
821         wpa_supplicant_send_stk_3_of_4(sm, peerkey);
822         os_memcpy(peerkey->pnonce, key->key_nonce, WPA_NONCE_LEN);
823 }
824
825
826 static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm,
827                                               struct wpa_peerkey *peerkey,
828                                               const struct wpa_eapol_key *key,
829                                               u16 ver)
830 {
831         struct wpa_eapol_ie_parse kde;
832         const u8 *keydata;
833         size_t len, key_len;
834         const u8 *_key;
835         u8 key_buf[32], rsc[6];
836
837         wpa_printf(MSG_DEBUG, "RSN: RX message 3 of STK 4-Way Handshake from "
838                    MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
839
840         os_memset(&kde, 0, sizeof(kde));
841
842         /* RSN: msg 3/4 should contain Initiator RSN IE. It may also include
843          * Lifetime KDE. */
844         keydata = (const u8 *) (key + 1);
845         len = WPA_GET_BE16(key->key_data_length);
846         wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", keydata, len);
847         if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0) {
848                 wpa_printf(MSG_DEBUG, "RSN: Failed to parse key data in "
849                            "STK 3/4");
850                 return;
851         }
852
853         if (kde.rsn_ie_len != peerkey->rsnie_i_len ||
854             os_memcmp(kde.rsn_ie, peerkey->rsnie_i, kde.rsn_ie_len) != 0) {
855                 wpa_printf(MSG_INFO, "RSN: Initiator RSN IE in SMK and STK "
856                            "handshakes did not match");
857                 wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in SMK "
858                             "handshake",
859                             peerkey->rsnie_i, peerkey->rsnie_i_len);
860                 wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in STK "
861                             "handshake",
862                             kde.rsn_ie, kde.rsn_ie_len);
863                 return;
864         }
865
866         if (os_memcmp(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
867                 wpa_printf(MSG_WARNING, "RSN: INonce from message 1 of STK "
868                            "4-Way Handshake differs from 3 of STK 4-Way "
869                            "Handshake - drop packet (src=" MACSTR ")",
870                            MAC2STR(peerkey->addr));
871                 return;
872         }
873
874         wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde);
875
876         if (wpa_supplicant_send_4_of_4(sm, peerkey->addr, key, ver,
877                                        WPA_GET_BE16(key->key_info),
878                                        NULL, 0, &peerkey->stk))
879                 return;
880
881         _key = (u8 *) peerkey->stk.tk1;
882         if (peerkey->cipher == WPA_CIPHER_TKIP) {
883                 /* Swap Tx/Rx keys for Michael MIC */
884                 os_memcpy(key_buf, _key, 16);
885                 os_memcpy(key_buf + 16, peerkey->stk.u.auth.rx_mic_key, 8);
886                 os_memcpy(key_buf + 24, peerkey->stk.u.auth.tx_mic_key, 8);
887                 _key = key_buf;
888                 key_len = 32;
889         } else
890                 key_len = 16;
891
892         os_memset(rsc, 0, 6);
893         if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1,
894                            rsc, sizeof(rsc), _key, key_len) < 0) {
895                 wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the "
896                            "driver.");
897                 return;
898         }
899 }
900
901
902 static void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm,
903                                               struct wpa_peerkey *peerkey,
904                                               const struct wpa_eapol_key *key,
905                                               u16 ver)
906 {
907         u8 rsc[6];
908
909         wpa_printf(MSG_DEBUG, "RSN: RX message 4 of STK 4-Way Handshake from "
910                    MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
911
912         os_memset(rsc, 0, 6);
913         if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1,
914                            rsc, sizeof(rsc), (u8 *) peerkey->stk.tk1,
915                            peerkey->cipher == WPA_CIPHER_TKIP ? 32 : 16) < 0) {
916                 wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the "
917                            "driver.");
918                 return;
919         }
920 }
921
922
923 /**
924  * peerkey_verify_eapol_key_mic - Verify PeerKey MIC
925  * @sm: Pointer to WPA state machine data from wpa_sm_init()
926  * @peerkey: Pointer to the PeerKey data for the peer
927  * @key: Pointer to the EAPOL-Key frame header
928  * @ver: Version bits from EAPOL-Key Key Info
929  * @buf: Pointer to the beginning of EAPOL-Key frame
930  * @len: Length of the EAPOL-Key frame
931  * Returns: 0 on success, -1 on failure
932  */
933 int peerkey_verify_eapol_key_mic(struct wpa_sm *sm,
934                                  struct wpa_peerkey *peerkey,
935                                  struct wpa_eapol_key *key, u16 ver,
936                                  const u8 *buf, size_t len)
937 {
938         u8 mic[16];
939         int ok = 0;
940
941         if (peerkey->initiator && !peerkey->stk_set) {
942                 wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion",
943                                sm->own_addr, peerkey->addr,
944                                peerkey->inonce, key->key_nonce,
945                                (u8 *) &peerkey->stk, sizeof(peerkey->stk),
946                                peerkey->use_sha256);
947                 peerkey->stk_set = 1;
948         }
949
950         os_memcpy(mic, key->key_mic, 16);
951         if (peerkey->tstk_set) {
952                 os_memset(key->key_mic, 0, 16);
953                 wpa_eapol_key_mic(peerkey->tstk.kck, ver, buf, len,
954                                   key->key_mic);
955                 if (os_memcmp(mic, key->key_mic, 16) != 0) {
956                         wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
957                                    "when using TSTK - ignoring TSTK");
958                 } else {
959                         ok = 1;
960                         peerkey->tstk_set = 0;
961                         peerkey->stk_set = 1;
962                         os_memcpy(&peerkey->stk, &peerkey->tstk,
963                                   sizeof(peerkey->stk));
964                 }
965         }
966
967         if (!ok && peerkey->stk_set) {
968                 os_memset(key->key_mic, 0, 16);
969                 wpa_eapol_key_mic(peerkey->stk.kck, ver, buf, len,
970                                   key->key_mic);
971                 if (os_memcmp(mic, key->key_mic, 16) != 0) {
972                         wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
973                                    "- dropping packet");
974                         return -1;
975                 }
976                 ok = 1;
977         }
978
979         if (!ok) {
980                 wpa_printf(MSG_WARNING, "RSN: Could not verify EAPOL-Key MIC "
981                            "- dropping packet");
982                 return -1;
983         }
984
985         os_memcpy(peerkey->replay_counter, key->replay_counter,
986                   WPA_REPLAY_COUNTER_LEN);
987         peerkey->replay_counter_set = 1;
988         return 0;
989 }
990
991
992 /**
993  * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1)
994  * @sm: Pointer to WPA state machine data from wpa_sm_init()
995  * @peer: MAC address of the peer STA
996  * Returns: 0 on success, or -1 on failure
997  *
998  * Send an EAPOL-Key Request to the current authenticator to start STK
999  * handshake with the peer.
1000  */
1001 int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer)
1002 {
1003         size_t rlen, kde_len;
1004         struct wpa_eapol_key *req;
1005         int key_info, ver;
1006         u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos;
1007         u16 count;
1008         struct rsn_ie_hdr *hdr;
1009         struct wpa_peerkey *peerkey;
1010         struct wpa_ie_data ie;
1011
1012         if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set || !sm->peerkey_enabled)
1013                 return -1;
1014
1015         if (sm->ap_rsn_ie &&
1016             wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 &&
1017             !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) {
1018                 wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK");
1019                 return -1;
1020         }
1021
1022         if (sm->pairwise_cipher == WPA_CIPHER_CCMP)
1023                 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
1024         else
1025                 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
1026
1027         if (wpa_sm_get_bssid(sm, bssid) < 0) {
1028                 wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key "
1029                            "SMK M1");
1030                 return -1;
1031         }
1032
1033         /* TODO: find existing entry and if found, use that instead of adding
1034          * a new one */
1035         peerkey = os_zalloc(sizeof(*peerkey));
1036         if (peerkey == NULL)
1037                 return -1;
1038         peerkey->initiator = 1;
1039         os_memcpy(peerkey->addr, peer, ETH_ALEN);
1040 #ifdef CONFIG_IEEE80211W
1041         if (wpa_key_mgmt_sha256(sm->key_mgmt))
1042                 peerkey->use_sha256 = 1;
1043 #endif /* CONFIG_IEEE80211W */
1044
1045         /* SMK M1:
1046          * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
1047          *           MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE))
1048          */
1049
1050         hdr = (struct rsn_ie_hdr *) peerkey->rsnie_i;
1051         hdr->elem_id = WLAN_EID_RSN;
1052         WPA_PUT_LE16(hdr->version, RSN_VERSION);
1053         pos = (u8 *) (hdr + 1);
1054         /* Group Suite can be anything for SMK RSN IE; receiver will just
1055          * ignore it. */
1056         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1057         pos += RSN_SELECTOR_LEN;
1058         count_pos = pos;
1059         pos += 2;
1060
1061         count = 0;
1062         if (sm->allowed_pairwise_cipher & WPA_CIPHER_CCMP) {
1063                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1064                 pos += RSN_SELECTOR_LEN;
1065                 count++;
1066         }
1067         if (sm->allowed_pairwise_cipher & WPA_CIPHER_TKIP) {
1068                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
1069                 pos += RSN_SELECTOR_LEN;
1070                 count++;
1071         }
1072         WPA_PUT_LE16(count_pos, count);
1073
1074         hdr->len = (pos - peerkey->rsnie_i) - 2;
1075         peerkey->rsnie_i_len = pos - peerkey->rsnie_i;
1076         wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",
1077                     peerkey->rsnie_i, peerkey->rsnie_i_len);
1078
1079         kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
1080
1081         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
1082                                   sizeof(*req) + kde_len, &rlen,
1083                                   (void *) &req);
1084         if (rbuf == NULL) {
1085                 wpa_supplicant_peerkey_free(sm, peerkey);
1086                 return -1;
1087         }
1088
1089         req->type = EAPOL_KEY_TYPE_RSN;
1090         key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
1091                 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver;
1092         WPA_PUT_BE16(req->key_info, key_info);
1093         WPA_PUT_BE16(req->key_length, 0);
1094         os_memcpy(req->replay_counter, sm->request_counter,
1095                   WPA_REPLAY_COUNTER_LEN);
1096         inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
1097
1098         if (os_get_random(peerkey->inonce, WPA_NONCE_LEN)) {
1099                 wpa_msg(sm->ctx->ctx, MSG_WARNING,
1100                         "WPA: Failed to get random data for INonce");
1101                 os_free(rbuf);
1102                 wpa_supplicant_peerkey_free(sm, peerkey);
1103                 return -1;
1104         }
1105         os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
1106         wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake",
1107                     req->key_nonce, WPA_NONCE_LEN);
1108
1109         WPA_PUT_BE16(req->key_data_length, (u16) kde_len);
1110         pos = (u8 *) (req + 1);
1111
1112         /* Initiator RSN IE */
1113         pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);
1114         /* Peer MAC address KDE */
1115         wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);
1116
1117         wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer "
1118                    MACSTR ")", MAC2STR(peer));
1119         wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL,
1120                            rbuf, rlen, req->key_mic);
1121
1122         peerkey->next = sm->peerkey;
1123         sm->peerkey = peerkey;
1124
1125         return 0;
1126 }
1127
1128
1129 /**
1130  * peerkey_deinit - Free PeerKey values
1131  * @sm: Pointer to WPA state machine data from wpa_sm_init()
1132  */
1133 void peerkey_deinit(struct wpa_sm *sm)
1134 {
1135         struct wpa_peerkey *prev, *peerkey = sm->peerkey;
1136         while (peerkey) {
1137                 prev = peerkey;
1138                 peerkey = peerkey->next;
1139                 os_free(prev);
1140         }
1141 }
1142
1143
1144 void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey,
1145                            struct wpa_eapol_key *key, u16 key_info, u16 ver)
1146 {
1147         if ((key_info & (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) ==
1148             (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) {
1149                 /* 3/4 STK 4-Way Handshake */
1150                 wpa_supplicant_process_stk_3_of_4(sm, peerkey, key, ver);
1151         } else if (key_info & WPA_KEY_INFO_ACK) {
1152                 /* 1/4 STK 4-Way Handshake */
1153                 wpa_supplicant_process_stk_1_of_4(sm, peerkey, key, ver);
1154         } else if (key_info & WPA_KEY_INFO_SECURE) {
1155                 /* 4/4 STK 4-Way Handshake */
1156                 wpa_supplicant_process_stk_4_of_4(sm, peerkey, key, ver);
1157         } else {
1158                 /* 2/4 STK 4-Way Handshake */
1159                 wpa_supplicant_process_stk_2_of_4(sm, peerkey, key, ver);
1160         }
1161 }
1162
1163
1164 void peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr,
1165                           struct wpa_eapol_key *key, size_t extra_len,
1166                           u16 key_info, u16 ver)
1167 {
1168         if (key_info & WPA_KEY_INFO_ERROR) {
1169                 /* SMK Error */
1170                 wpa_supplicant_process_smk_error(sm, src_addr, key, extra_len);
1171         } else if (key_info & WPA_KEY_INFO_ACK) {
1172                 /* SMK M2 */
1173                 wpa_supplicant_process_smk_m2(sm, src_addr, key, extra_len,
1174                                               ver);
1175         } else {
1176                 /* SMK M4 or M5 */
1177                 wpa_supplicant_process_smk_m45(sm, src_addr, key, extra_len,
1178                                                ver);
1179         }
1180 }
1181
1182 #endif /* CONFIG_PEERKEY */