]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/wpa/src/rsn_supp/peerkey.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / wpa / 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 software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "includes.h"
10
11 #ifdef CONFIG_PEERKEY
12
13 #include "common.h"
14 #include "eloop.h"
15 #include "crypto/sha1.h"
16 #include "crypto/sha256.h"
17 #include "crypto/random.h"
18 #include "common/ieee802_11_defs.h"
19 #include "wpa.h"
20 #include "wpa_i.h"
21 #include "wpa_ie.h"
22 #include "peerkey.h"
23
24
25 static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len)
26 {
27         os_memcpy(pos, ie, ie_len);
28         return pos + ie_len;
29 }
30
31
32 static u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len)
33 {
34         *pos++ = WLAN_EID_VENDOR_SPECIFIC;
35         *pos++ = RSN_SELECTOR_LEN + data_len;
36         RSN_SELECTOR_PUT(pos, kde);
37         pos += RSN_SELECTOR_LEN;
38         os_memcpy(pos, data, data_len);
39         pos += data_len;
40         return pos;
41 }
42
43
44 static void wpa_supplicant_smk_timeout(void *eloop_ctx, void *timeout_ctx)
45 {
46 #if 0
47         struct wpa_sm *sm = eloop_ctx;
48         struct wpa_peerkey *peerkey = timeout_ctx;
49 #endif
50         /* TODO: time out SMK and any STK that was generated using this SMK */
51 }
52
53
54 static void wpa_supplicant_peerkey_free(struct wpa_sm *sm,
55                                         struct wpa_peerkey *peerkey)
56 {
57         eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey);
58         os_free(peerkey);
59 }
60
61
62 static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst,
63                                          const u8 *peer,
64                                          u16 mui, u16 error_type, int ver)
65 {
66         size_t rlen;
67         struct wpa_eapol_key *err;
68         struct rsn_error_kde error;
69         u8 *rbuf, *pos;
70         size_t kde_len;
71         u16 key_info;
72
73         kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error);
74         if (peer)
75                 kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN;
76
77         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
78                                   NULL, sizeof(*err) + kde_len, &rlen,
79                                   (void *) &err);
80         if (rbuf == NULL)
81                 return -1;
82
83         err->type = EAPOL_KEY_TYPE_RSN;
84         key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
85                 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR |
86                 WPA_KEY_INFO_REQUEST;
87         WPA_PUT_BE16(err->key_info, key_info);
88         WPA_PUT_BE16(err->key_length, 0);
89         os_memcpy(err->replay_counter, sm->request_counter,
90                   WPA_REPLAY_COUNTER_LEN);
91         inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
92
93         WPA_PUT_BE16(err->key_data_length, (u16) kde_len);
94         pos = (u8 *) (err + 1);
95
96         if (peer) {
97                 /* Peer MAC Address KDE */
98                 pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);
99         }
100
101         /* Error KDE */
102         error.mui = host_to_be16(mui);
103         error.error_type = host_to_be16(error_type);
104         wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error));
105
106         if (peer) {
107                 wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer "
108                            MACSTR " mui %d error_type %d)",
109                            MAC2STR(peer), mui, error_type);
110         } else {
111                 wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error "
112                            "(mui %d error_type %d)", mui, error_type);
113         }
114
115         wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL,
116                            rbuf, rlen, err->key_mic);
117
118         return 0;
119 }
120
121
122 static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm,
123                                       const unsigned char *src_addr,
124                                       const struct wpa_eapol_key *key,
125                                       int ver, struct wpa_peerkey *peerkey)
126 {
127         size_t rlen;
128         struct wpa_eapol_key *reply;
129         u8 *rbuf, *pos;
130         size_t kde_len;
131         u16 key_info;
132
133         /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */
134         kde_len = peerkey->rsnie_p_len +
135                 2 + RSN_SELECTOR_LEN + ETH_ALEN +
136                 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN;
137
138         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
139                                   NULL, sizeof(*reply) + kde_len, &rlen,
140                                   (void *) &reply);
141         if (rbuf == NULL)
142                 return -1;
143
144         reply->type = EAPOL_KEY_TYPE_RSN;
145         key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
146                 WPA_KEY_INFO_SECURE;
147         WPA_PUT_BE16(reply->key_info, key_info);
148         WPA_PUT_BE16(reply->key_length, 0);
149         os_memcpy(reply->replay_counter, key->replay_counter,
150                   WPA_REPLAY_COUNTER_LEN);
151
152         os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN);
153
154         WPA_PUT_BE16(reply->key_data_length, (u16) kde_len);
155         pos = (u8 *) (reply + 1);
156
157         /* Peer RSN IE */
158         pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len);
159
160         /* Initiator MAC Address KDE */
161         pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN);
162
163         /* Initiator Nonce */
164         wpa_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN);
165
166         wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3");
167         wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL,
168                            rbuf, rlen, reply->key_mic);
169
170         return 0;
171 }
172
173
174 static int wpa_supplicant_process_smk_m2(
175         struct wpa_sm *sm, const unsigned char *src_addr,
176         const struct wpa_eapol_key *key, size_t extra_len, int ver)
177 {
178         struct wpa_peerkey *peerkey;
179         struct wpa_eapol_ie_parse kde;
180         struct wpa_ie_data ie;
181         int cipher;
182         struct rsn_ie_hdr *hdr;
183         u8 *pos;
184
185         wpa_printf(MSG_DEBUG, "RSN: Received SMK M2");
186
187         if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
188                 wpa_printf(MSG_INFO, "RSN: SMK handshake not allowed for "
189                            "the current network");
190                 return -1;
191         }
192
193         if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
194             0) {
195                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M2");
196                 return -1;
197         }
198
199         if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
200             kde.mac_addr_len < ETH_ALEN) {
201                 wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
202                            "SMK M2");
203                 return -1;
204         }
205
206         wpa_printf(MSG_DEBUG, "RSN: SMK M2 - SMK initiator " MACSTR,
207                    MAC2STR(kde.mac_addr));
208
209         if (kde.rsn_ie_len > PEERKEY_MAX_IE_LEN) {
210                 wpa_printf(MSG_INFO, "RSN: Too long Initiator RSN IE in SMK "
211                            "M2");
212                 return -1;
213         }
214
215         if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
216                 wpa_printf(MSG_INFO, "RSN: Failed to parse RSN IE in SMK M2");
217                 return -1;
218         }
219
220         cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher;
221         if (cipher & WPA_CIPHER_CCMP) {
222                 wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey");
223                 cipher = WPA_CIPHER_CCMP;
224         } else if (cipher & WPA_CIPHER_GCMP) {
225                 wpa_printf(MSG_DEBUG, "RSN: Using GCMP for PeerKey");
226                 cipher = WPA_CIPHER_GCMP;
227         } else if (cipher & WPA_CIPHER_TKIP) {
228                 wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey");
229                 cipher = WPA_CIPHER_TKIP;
230         } else {
231                 wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2");
232                 wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr,
233                                               STK_MUI_SMK, STK_ERR_CPHR_NS,
234                                               ver);
235                 return -1;
236         }
237
238         /* TODO: find existing entry and if found, use that instead of adding
239          * a new one; how to handle the case where both ends initiate at the
240          * same time? */
241         peerkey = os_zalloc(sizeof(*peerkey));
242         if (peerkey == NULL)
243                 return -1;
244         os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN);
245         os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN);
246         os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);
247         peerkey->rsnie_i_len = kde.rsn_ie_len;
248         peerkey->cipher = cipher;
249 #ifdef CONFIG_IEEE80211W
250         if (ie.key_mgmt & (WPA_KEY_MGMT_IEEE8021X_SHA256 |
251                            WPA_KEY_MGMT_PSK_SHA256))
252                 peerkey->use_sha256 = 1;
253 #endif /* CONFIG_IEEE80211W */
254
255         if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) {
256                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
257                         "WPA: Failed to get random data for PNonce");
258                 wpa_supplicant_peerkey_free(sm, peerkey);
259                 return -1;
260         }
261
262         hdr = (struct rsn_ie_hdr *) peerkey->rsnie_p;
263         hdr->elem_id = WLAN_EID_RSN;
264         WPA_PUT_LE16(hdr->version, RSN_VERSION);
265         pos = (u8 *) (hdr + 1);
266         /* Group Suite can be anything for SMK RSN IE; receiver will just
267          * ignore it. */
268         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
269         pos += RSN_SELECTOR_LEN;
270         /* Include only the selected cipher in pairwise cipher suite */
271         WPA_PUT_LE16(pos, 1);
272         pos += 2;
273         RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN, cipher));
274         pos += RSN_SELECTOR_LEN;
275
276         hdr->len = (pos - peerkey->rsnie_p) - 2;
277         peerkey->rsnie_p_len = pos - peerkey->rsnie_p;
278         wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",
279                     peerkey->rsnie_p, peerkey->rsnie_p_len);
280
281         wpa_supplicant_send_smk_m3(sm, src_addr, key, ver, peerkey);
282
283         peerkey->next = sm->peerkey;
284         sm->peerkey = peerkey;
285
286         return 0;
287 }
288
289
290 /**
291  * rsn_smkid - Derive SMK identifier
292  * @smk: Station master key (32 bytes)
293  * @pnonce: Peer Nonce
294  * @mac_p: Peer MAC address
295  * @inonce: Initiator Nonce
296  * @mac_i: Initiator MAC address
297  * @use_sha256: Whether to use SHA256-based KDF
298  *
299  * 8.5.1.4 Station to station (STK) key hierarchy
300  * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I)
301  */
302 static void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p,
303                       const u8 *inonce, const u8 *mac_i, u8 *smkid,
304                       int use_sha256)
305 {
306         char *title = "SMK Name";
307         const u8 *addr[5];
308         const size_t len[5] = { 8, WPA_NONCE_LEN, ETH_ALEN, WPA_NONCE_LEN,
309                                 ETH_ALEN };
310         unsigned char hash[SHA256_MAC_LEN];
311
312         addr[0] = (u8 *) title;
313         addr[1] = pnonce;
314         addr[2] = mac_p;
315         addr[3] = inonce;
316         addr[4] = mac_i;
317
318 #ifdef CONFIG_IEEE80211W
319         if (use_sha256)
320                 hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash);
321         else
322 #endif /* CONFIG_IEEE80211W */
323                 hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash);
324         os_memcpy(smkid, hash, PMKID_LEN);
325 }
326
327
328 static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm,
329                                            struct wpa_peerkey *peerkey)
330 {
331         size_t mlen;
332         struct wpa_eapol_key *msg;
333         u8 *mbuf;
334         size_t kde_len;
335         u16 key_info, ver;
336
337         kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
338
339         mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
340                                   sizeof(*msg) + kde_len, &mlen,
341                                   (void *) &msg);
342         if (mbuf == NULL)
343                 return;
344
345         msg->type = EAPOL_KEY_TYPE_RSN;
346
347         if (peerkey->cipher != WPA_CIPHER_TKIP)
348                 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
349         else
350                 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
351
352         key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK;
353         WPA_PUT_BE16(msg->key_info, key_info);
354
355         if (peerkey->cipher != WPA_CIPHER_TKIP)
356                 WPA_PUT_BE16(msg->key_length, 16);
357         else
358                 WPA_PUT_BE16(msg->key_length, 32);
359
360         os_memcpy(msg->replay_counter, peerkey->replay_counter,
361                   WPA_REPLAY_COUNTER_LEN);
362         inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN);
363
364         WPA_PUT_BE16(msg->key_data_length, kde_len);
365         wpa_add_kde((u8 *) (msg + 1), RSN_KEY_DATA_PMKID,
366                     peerkey->smkid, PMKID_LEN);
367
368         if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) {
369                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
370                         "RSN: Failed to get random data for INonce (STK)");
371                 os_free(mbuf);
372                 return;
373         }
374         wpa_hexdump(MSG_DEBUG, "RSN: INonce for STK 4-Way Handshake",
375                     peerkey->inonce, WPA_NONCE_LEN);
376         os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
377
378         wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR,
379                    MAC2STR(peerkey->addr));
380         wpa_eapol_key_send(sm, NULL, ver, peerkey->addr, ETH_P_EAPOL,
381                            mbuf, mlen, NULL);
382 }
383
384
385 static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm,
386                                            struct wpa_peerkey *peerkey)
387 {
388         size_t mlen;
389         struct wpa_eapol_key *msg;
390         u8 *mbuf, *pos;
391         size_t kde_len;
392         u16 key_info, ver;
393         be32 lifetime;
394
395         kde_len = peerkey->rsnie_i_len +
396                 2 + RSN_SELECTOR_LEN + sizeof(lifetime);
397
398         mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
399                                   sizeof(*msg) + kde_len, &mlen,
400                                   (void *) &msg);
401         if (mbuf == NULL)
402                 return;
403
404         msg->type = EAPOL_KEY_TYPE_RSN;
405
406         if (peerkey->cipher != WPA_CIPHER_TKIP)
407                 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
408         else
409                 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
410
411         key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK |
412                 WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
413         WPA_PUT_BE16(msg->key_info, key_info);
414
415         if (peerkey->cipher != WPA_CIPHER_TKIP)
416                 WPA_PUT_BE16(msg->key_length, 16);
417         else
418                 WPA_PUT_BE16(msg->key_length, 32);
419
420         os_memcpy(msg->replay_counter, peerkey->replay_counter,
421                   WPA_REPLAY_COUNTER_LEN);
422         inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN);
423
424         WPA_PUT_BE16(msg->key_data_length, kde_len);
425         pos = (u8 *) (msg + 1);
426         pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);
427         lifetime = host_to_be32(peerkey->lifetime);
428         wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
429                     (u8 *) &lifetime, sizeof(lifetime));
430
431         os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
432
433         wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR,
434                    MAC2STR(peerkey->addr));
435         wpa_eapol_key_send(sm, peerkey->stk.kck, ver, peerkey->addr,
436                            ETH_P_EAPOL, mbuf, mlen, msg->key_mic);
437 }
438
439
440 static int wpa_supplicant_process_smk_m4(struct wpa_peerkey *peerkey,
441                                          struct wpa_eapol_ie_parse *kde)
442 {
443         wpa_printf(MSG_DEBUG, "RSN: Received SMK M4 (Initiator " MACSTR ")",
444                    MAC2STR(kde->mac_addr));
445
446         if (os_memcmp(kde->smk + PMK_LEN, peerkey->pnonce, WPA_NONCE_LEN) != 0)
447         {
448                 wpa_printf(MSG_INFO, "RSN: PNonce in SMK KDE does not "
449                            "match with the one used in SMK M3");
450                 return -1;
451         }
452
453         if (os_memcmp(kde->nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) {
454                 wpa_printf(MSG_INFO, "RSN: INonce in SMK M4 did not "
455                            "match with the one received in SMK M2");
456                 return -1;
457         }
458
459         return 0;
460 }
461
462
463 static int wpa_supplicant_process_smk_m5(struct wpa_sm *sm,
464                                          const unsigned char *src_addr,
465                                          const struct wpa_eapol_key *key,
466                                          int ver,
467                                          struct wpa_peerkey *peerkey,
468                                          struct wpa_eapol_ie_parse *kde)
469 {
470         int cipher;
471         struct wpa_ie_data ie;
472
473         wpa_printf(MSG_DEBUG, "RSN: Received SMK M5 (Peer " MACSTR ")",
474                    MAC2STR(kde->mac_addr));
475         if (kde->rsn_ie == NULL || kde->rsn_ie_len > PEERKEY_MAX_IE_LEN ||
476             wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0) {
477                 wpa_printf(MSG_INFO, "RSN: No RSN IE in SMK M5");
478                 /* TODO: abort negotiation */
479                 return -1;
480         }
481
482         if (os_memcmp(key->key_nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) {
483                 wpa_printf(MSG_INFO, "RSN: Key Nonce in SMK M5 does "
484                            "not match with INonce used in SMK M1");
485                 return -1;
486         }
487
488         if (os_memcmp(kde->smk + PMK_LEN, peerkey->inonce, WPA_NONCE_LEN) != 0)
489         {
490                 wpa_printf(MSG_INFO, "RSN: INonce in SMK KDE does not "
491                            "match with the one used in SMK M1");
492                 return -1;
493         }
494
495         os_memcpy(peerkey->rsnie_p, kde->rsn_ie, kde->rsn_ie_len);
496         peerkey->rsnie_p_len = kde->rsn_ie_len;
497         os_memcpy(peerkey->pnonce, kde->nonce, WPA_NONCE_LEN);
498
499         cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher;
500         if (cipher & WPA_CIPHER_CCMP) {
501                 wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey");
502                 peerkey->cipher = WPA_CIPHER_CCMP;
503         } else if (cipher & WPA_CIPHER_GCMP) {
504                 wpa_printf(MSG_DEBUG, "RSN: Using GCMP for PeerKey");
505                 peerkey->cipher = WPA_CIPHER_GCMP;
506         } else if (cipher & WPA_CIPHER_TKIP) {
507                 wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey");
508                 peerkey->cipher = WPA_CIPHER_TKIP;
509         } else {
510                 wpa_printf(MSG_INFO, "RSN: SMK Peer STA " MACSTR " selected "
511                            "unacceptable cipher", MAC2STR(kde->mac_addr));
512                 wpa_supplicant_send_smk_error(sm, src_addr, kde->mac_addr,
513                                               STK_MUI_SMK, STK_ERR_CPHR_NS,
514                                               ver);
515                 /* TODO: abort negotiation */
516                 return -1;
517         }
518
519         return 0;
520 }
521
522
523 static int wpa_supplicant_process_smk_m45(
524         struct wpa_sm *sm, const unsigned char *src_addr,
525         const struct wpa_eapol_key *key, size_t extra_len, int ver)
526 {
527         struct wpa_peerkey *peerkey;
528         struct wpa_eapol_ie_parse kde;
529         u32 lifetime;
530         struct os_time now;
531
532         if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
533                 wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
534                            "the current network");
535                 return -1;
536         }
537
538         if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
539             0) {
540                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5");
541                 return -1;
542         }
543
544         if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
545             kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN ||
546             kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN ||
547             kde.lifetime == NULL || kde.lifetime_len < 4) {
548                 wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or "
549                            "Lifetime KDE in SMK M4/M5");
550                 return -1;
551         }
552
553         for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
554                 if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 &&
555                     os_memcmp(peerkey->initiator ? peerkey->inonce :
556                            peerkey->pnonce,
557                            key->key_nonce, WPA_NONCE_LEN) == 0)
558                         break;
559         }
560         if (peerkey == NULL) {
561                 wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found "
562                            "for SMK M4/M5: peer " MACSTR,
563                            MAC2STR(kde.mac_addr));
564                 return -1;
565         }
566
567         if (peerkey->initiator) {
568                 if (wpa_supplicant_process_smk_m5(sm, src_addr, key, ver,
569                                                   peerkey, &kde) < 0)
570                         return -1;
571         } else {
572                 if (wpa_supplicant_process_smk_m4(peerkey, &kde) < 0)
573                         return -1;
574         }
575
576         os_memcpy(peerkey->smk, kde.smk, PMK_LEN);
577         peerkey->smk_complete = 1;
578         wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN);
579         lifetime = WPA_GET_BE32(kde.lifetime);
580         wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime);
581         if (lifetime > 1000000000)
582                 lifetime = 1000000000; /* avoid overflowing expiration time */
583         peerkey->lifetime = lifetime;
584         os_get_time(&now);
585         peerkey->expiration = now.sec + lifetime;
586         eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout,
587                                sm, peerkey);
588
589         if (peerkey->initiator) {
590                 rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr,
591                           peerkey->inonce, sm->own_addr, peerkey->smkid,
592                           peerkey->use_sha256);
593                 wpa_supplicant_send_stk_1_of_4(sm, peerkey);
594         } else {
595                 rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr,
596                           peerkey->inonce, peerkey->addr, peerkey->smkid,
597                           peerkey->use_sha256);
598         }
599         wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN);
600
601         return 0;
602 }
603
604
605 static int wpa_supplicant_process_smk_error(
606         struct wpa_sm *sm, const unsigned char *src_addr,
607         const struct wpa_eapol_key *key, size_t extra_len)
608 {
609         struct wpa_eapol_ie_parse kde;
610         struct rsn_error_kde error;
611         u8 peer[ETH_ALEN];
612         u16 error_type;
613
614         wpa_printf(MSG_DEBUG, "RSN: Received SMK Error");
615
616         if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
617                 wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
618                            "the current network");
619                 return -1;
620         }
621
622         if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
623             0) {
624                 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
625                 return -1;
626         }
627
628         if (kde.error == NULL || kde.error_len < sizeof(error)) {
629                 wpa_printf(MSG_INFO, "RSN: No Error KDE in SMK Error");
630                 return -1;
631         }
632
633         if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN)
634                 os_memcpy(peer, kde.mac_addr, ETH_ALEN);
635         else
636                 os_memset(peer, 0, ETH_ALEN);
637         os_memcpy(&error, kde.error, sizeof(error));
638         error_type = be_to_host16(error.error_type);
639         wpa_msg(sm->ctx->msg_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 (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) {
699                 wpa_msg(sm->ctx->msg_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_TKIP)
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 = rsn_cipher_put_suites(pos, sm->allowed_pairwise_cipher);
1062         pos += count * RSN_SELECTOR_LEN;
1063         WPA_PUT_LE16(count_pos, count);
1064
1065         hdr->len = (pos - peerkey->rsnie_i) - 2;
1066         peerkey->rsnie_i_len = pos - peerkey->rsnie_i;
1067         wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",
1068                     peerkey->rsnie_i, peerkey->rsnie_i_len);
1069
1070         kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
1071
1072         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
1073                                   sizeof(*req) + kde_len, &rlen,
1074                                   (void *) &req);
1075         if (rbuf == NULL) {
1076                 wpa_supplicant_peerkey_free(sm, peerkey);
1077                 return -1;
1078         }
1079
1080         req->type = EAPOL_KEY_TYPE_RSN;
1081         key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
1082                 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver;
1083         WPA_PUT_BE16(req->key_info, key_info);
1084         WPA_PUT_BE16(req->key_length, 0);
1085         os_memcpy(req->replay_counter, sm->request_counter,
1086                   WPA_REPLAY_COUNTER_LEN);
1087         inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
1088
1089         if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) {
1090                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1091                         "WPA: Failed to get random data for INonce");
1092                 os_free(rbuf);
1093                 wpa_supplicant_peerkey_free(sm, peerkey);
1094                 return -1;
1095         }
1096         os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
1097         wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake",
1098                     req->key_nonce, WPA_NONCE_LEN);
1099
1100         WPA_PUT_BE16(req->key_data_length, (u16) kde_len);
1101         pos = (u8 *) (req + 1);
1102
1103         /* Initiator RSN IE */
1104         pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);
1105         /* Peer MAC address KDE */
1106         wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);
1107
1108         wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer "
1109                    MACSTR ")", MAC2STR(peer));
1110         wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL,
1111                            rbuf, rlen, req->key_mic);
1112
1113         peerkey->next = sm->peerkey;
1114         sm->peerkey = peerkey;
1115
1116         return 0;
1117 }
1118
1119
1120 /**
1121  * peerkey_deinit - Free PeerKey values
1122  * @sm: Pointer to WPA state machine data from wpa_sm_init()
1123  */
1124 void peerkey_deinit(struct wpa_sm *sm)
1125 {
1126         struct wpa_peerkey *prev, *peerkey = sm->peerkey;
1127         while (peerkey) {
1128                 prev = peerkey;
1129                 peerkey = peerkey->next;
1130                 os_free(prev);
1131         }
1132         sm->peerkey = NULL;
1133 }
1134
1135
1136 void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey,
1137                            struct wpa_eapol_key *key, u16 key_info, u16 ver)
1138 {
1139         if ((key_info & (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) ==
1140             (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) {
1141                 /* 3/4 STK 4-Way Handshake */
1142                 wpa_supplicant_process_stk_3_of_4(sm, peerkey, key, ver);
1143         } else if (key_info & WPA_KEY_INFO_ACK) {
1144                 /* 1/4 STK 4-Way Handshake */
1145                 wpa_supplicant_process_stk_1_of_4(sm, peerkey, key, ver);
1146         } else if (key_info & WPA_KEY_INFO_SECURE) {
1147                 /* 4/4 STK 4-Way Handshake */
1148                 wpa_supplicant_process_stk_4_of_4(sm, peerkey, key, ver);
1149         } else {
1150                 /* 2/4 STK 4-Way Handshake */
1151                 wpa_supplicant_process_stk_2_of_4(sm, peerkey, key, ver);
1152         }
1153 }
1154
1155
1156 void peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr,
1157                           struct wpa_eapol_key *key, size_t extra_len,
1158                           u16 key_info, u16 ver)
1159 {
1160         if (key_info & WPA_KEY_INFO_ERROR) {
1161                 /* SMK Error */
1162                 wpa_supplicant_process_smk_error(sm, src_addr, key, extra_len);
1163         } else if (key_info & WPA_KEY_INFO_ACK) {
1164                 /* SMK M2 */
1165                 wpa_supplicant_process_smk_m2(sm, src_addr, key, extra_len,
1166                                               ver);
1167         } else {
1168                 /* SMK M4 or M5 */
1169                 wpa_supplicant_process_smk_m45(sm, src_addr, key, extra_len,
1170                                                ver);
1171         }
1172 }
1173
1174 #endif /* CONFIG_PEERKEY */