~ubuntu-branches/ubuntu/hardy/wpasupplicant/hardy

« back to all changes in this revision

Viewing changes to src/common/wpa_common.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * WPA/RSN - Shared functions for supplicant and authenticator
3
 
 * Copyright (c) 2002-2007, 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
 
#include "common.h"
18
 
#include "md5.h"
19
 
#include "sha1.h"
20
 
#include "sha256.h"
21
 
#include "aes_wrap.h"
22
 
#include "crypto.h"
23
 
#include "ieee802_11_defs.h"
24
 
#include "defs.h"
25
 
#include "wpa_common.h"
26
 
 
27
 
 
28
 
/**
29
 
 * wpa_eapol_key_mic - Calculate EAPOL-Key MIC
30
 
 * @key: EAPOL-Key Key Confirmation Key (KCK)
31
 
 * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*)
32
 
 * @buf: Pointer to the beginning of the EAPOL header (version field)
33
 
 * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame)
34
 
 * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written
35
 
 * Returns: 0 on success, -1 on failure
36
 
 *
37
 
 * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has
38
 
 * to be cleared (all zeroes) when calling this function.
39
 
 *
40
 
 * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the
41
 
 * description of the Key MIC calculation. It includes packet data from the
42
 
 * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change
43
 
 * happened during final editing of the standard and the correct behavior is
44
 
 * defined in the last draft (IEEE 802.11i/D10).
45
 
 */
46
 
int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
47
 
                      u8 *mic)
48
 
{
49
 
        u8 hash[SHA1_MAC_LEN];
50
 
 
51
 
        switch (ver) {
52
 
        case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
53
 
                hmac_md5(key, 16, buf, len, mic);
54
 
                break;
55
 
        case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
56
 
                hmac_sha1(key, 16, buf, len, hash);
57
 
                os_memcpy(mic, hash, MD5_MAC_LEN);
58
 
                break;
59
 
#ifdef CONFIG_IEEE80211R
60
 
        case WPA_KEY_INFO_TYPE_AES_128_CMAC:
61
 
                omac1_aes_128(key, buf, len, mic);
62
 
                break;
63
 
#endif /* CONFIG_IEEE80211R */
64
 
        default:
65
 
                return -1;
66
 
        }
67
 
 
68
 
        return 0;
69
 
}
70
 
 
71
 
 
72
 
/**
73
 
 * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces
74
 
 * @pmk: Pairwise master key
75
 
 * @pmk_len: Length of PMK
76
 
 * @label: Label to use in derivation
77
 
 * @addr1: AA or SA
78
 
 * @addr2: SA or AA
79
 
 * @nonce1: ANonce or SNonce
80
 
 * @nonce2: SNonce or ANonce
81
 
 * @ptk: Buffer for pairwise transient key
82
 
 * @ptk_len: Length of PTK
83
 
 *
84
 
 * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
85
 
 * PTK = PRF-X(PMK, "Pairwise key expansion",
86
 
 *             Min(AA, SA) || Max(AA, SA) ||
87
 
 *             Min(ANonce, SNonce) || Max(ANonce, SNonce))
88
 
 *
89
 
 * STK = PRF-X(SMK, "Peer key expansion",
90
 
 *             Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) ||
91
 
 *             Min(INonce, PNonce) || Max(INonce, PNonce))
92
 
 */
93
 
void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
94
 
                    const u8 *addr1, const u8 *addr2,
95
 
                    const u8 *nonce1, const u8 *nonce2,
96
 
                    u8 *ptk, size_t ptk_len)
97
 
{
98
 
        u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];
99
 
 
100
 
        if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {
101
 
                os_memcpy(data, addr1, ETH_ALEN);
102
 
                os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN);
103
 
        } else {
104
 
                os_memcpy(data, addr2, ETH_ALEN);
105
 
                os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN);
106
 
        }
107
 
 
108
 
        if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) {
109
 
                os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN);
110
 
                os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2,
111
 
                          WPA_NONCE_LEN);
112
 
        } else {
113
 
                os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN);
114
 
                os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1,
115
 
                          WPA_NONCE_LEN);
116
 
        }
117
 
 
118
 
        sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, ptk_len);
119
 
 
120
 
        wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
121
 
                   MAC2STR(addr1), MAC2STR(addr2));
122
 
        wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
123
 
        wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len);
124
 
}
125
 
 
126
 
 
127
 
#ifdef CONFIG_IEEE80211R
128
 
int wpa_ft_mic(const u8 *kck, int use_aes_cmac,
129
 
               const u8 *sta_addr, const u8 *ap_addr,
130
 
               u8 transaction_seqnum, const u8 *mdie, size_t mdie_len,
131
 
               const u8 *ftie, size_t ftie_len,
132
 
               const u8 *rsnie, size_t rsnie_len,
133
 
               const u8 *ric, size_t ric_len, u8 *mic)
134
 
{
135
 
        u8 *buf, *pos;
136
 
        size_t buf_len;
137
 
 
138
 
        buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len;
139
 
        buf = os_malloc(buf_len);
140
 
        if (buf == NULL)
141
 
                return -1;
142
 
 
143
 
        pos = buf;
144
 
        os_memcpy(pos, sta_addr, ETH_ALEN);
145
 
        pos += ETH_ALEN;
146
 
        os_memcpy(pos, ap_addr, ETH_ALEN);
147
 
        pos += ETH_ALEN;
148
 
        *pos++ = transaction_seqnum;
149
 
        if (rsnie) {
150
 
                os_memcpy(pos, rsnie, rsnie_len);
151
 
                pos += rsnie_len;
152
 
        }
153
 
        if (mdie) {
154
 
                os_memcpy(pos, mdie, mdie_len);
155
 
                pos += mdie_len;
156
 
        }
157
 
        if (ftie) {
158
 
                struct rsn_ftie *_ftie;
159
 
                os_memcpy(pos, ftie, ftie_len);
160
 
                if (ftie_len < 2 + sizeof(*_ftie)) {
161
 
                        os_free(buf);
162
 
                        return -1;
163
 
                }
164
 
                _ftie = (struct rsn_ftie *) (pos + 2);
165
 
                os_memset(_ftie->mic, 0, sizeof(_ftie->mic));
166
 
                pos += ftie_len;
167
 
        }
168
 
        if (ric) {
169
 
                os_memcpy(pos, ric, ric_len);
170
 
                pos += ric_len;
171
 
        }
172
 
 
173
 
        wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf);
174
 
        if (use_aes_cmac)
175
 
                omac1_aes_128(kck, buf, pos - buf, mic);
176
 
        else
177
 
                hmac_md5(kck, 16, buf, pos - buf, mic);
178
 
 
179
 
        os_free(buf);
180
 
 
181
 
        return 0;
182
 
}
183
 
#endif /* CONFIG_IEEE80211R */
184
 
 
185
 
 
186
 
#ifndef CONFIG_NO_WPA2
187
 
static int rsn_selector_to_bitfield(const u8 *s)
188
 
{
189
 
        if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
190
 
                return WPA_CIPHER_NONE;
191
 
        if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40)
192
 
                return WPA_CIPHER_WEP40;
193
 
        if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP)
194
 
                return WPA_CIPHER_TKIP;
195
 
        if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP)
196
 
                return WPA_CIPHER_CCMP;
197
 
        if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104)
198
 
                return WPA_CIPHER_WEP104;
199
 
#ifdef CONFIG_IEEE80211W
200
 
        if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
201
 
                return WPA_CIPHER_AES_128_CMAC;
202
 
#endif /* CONFIG_IEEE80211W */
203
 
        return 0;
204
 
}
205
 
 
206
 
 
207
 
static int rsn_key_mgmt_to_bitfield(const u8 *s)
208
 
{
209
 
        if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X)
210
 
                return WPA_KEY_MGMT_IEEE8021X;
211
 
        if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X)
212
 
                return WPA_KEY_MGMT_PSK;
213
 
#ifdef CONFIG_IEEE80211R
214
 
        if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X)
215
 
                return WPA_KEY_MGMT_FT_IEEE8021X;
216
 
        if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
217
 
                return WPA_KEY_MGMT_FT_PSK;
218
 
#endif /* CONFIG_IEEE80211R */
219
 
        return 0;
220
 
}
221
 
#endif /* CONFIG_NO_WPA2 */
222
 
 
223
 
 
224
 
/**
225
 
 * wpa_parse_wpa_ie_rsn - Parse RSN IE
226
 
 * @rsn_ie: Buffer containing RSN IE
227
 
 * @rsn_ie_len: RSN IE buffer length (including IE number and length octets)
228
 
 * @data: Pointer to structure that will be filled in with parsed data
229
 
 * Returns: 0 on success, <0 on failure
230
 
 */
231
 
int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
232
 
                         struct wpa_ie_data *data)
233
 
{
234
 
#ifndef CONFIG_NO_WPA2
235
 
        const struct rsn_ie_hdr *hdr;
236
 
        const u8 *pos;
237
 
        int left;
238
 
        int i, count;
239
 
 
240
 
        os_memset(data, 0, sizeof(*data));
241
 
        data->proto = WPA_PROTO_RSN;
242
 
        data->pairwise_cipher = WPA_CIPHER_CCMP;
243
 
        data->group_cipher = WPA_CIPHER_CCMP;
244
 
        data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
245
 
        data->capabilities = 0;
246
 
        data->pmkid = NULL;
247
 
        data->num_pmkid = 0;
248
 
#ifdef CONFIG_IEEE80211W
249
 
        data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
250
 
#else /* CONFIG_IEEE80211W */
251
 
        data->mgmt_group_cipher = 0;
252
 
#endif /* CONFIG_IEEE80211W */
253
 
 
254
 
        if (rsn_ie_len == 0) {
255
 
                /* No RSN IE - fail silently */
256
 
                return -1;
257
 
        }
258
 
 
259
 
        if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
260
 
                wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
261
 
                           __func__, (unsigned long) rsn_ie_len);
262
 
                return -1;
263
 
        }
264
 
 
265
 
        hdr = (const struct rsn_ie_hdr *) rsn_ie;
266
 
 
267
 
        if (hdr->elem_id != WLAN_EID_RSN ||
268
 
            hdr->len != rsn_ie_len - 2 ||
269
 
            WPA_GET_LE16(hdr->version) != RSN_VERSION) {
270
 
                wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
271
 
                           __func__);
272
 
                return -2;
273
 
        }
274
 
 
275
 
        pos = (const u8 *) (hdr + 1);
276
 
        left = rsn_ie_len - sizeof(*hdr);
277
 
 
278
 
        if (left >= RSN_SELECTOR_LEN) {
279
 
                data->group_cipher = rsn_selector_to_bitfield(pos);
280
 
#ifdef CONFIG_IEEE80211W
281
 
                if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) {
282
 
                        wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group "
283
 
                                   "cipher", __func__);
284
 
                        return -1;
285
 
                }
286
 
#endif /* CONFIG_IEEE80211W */
287
 
                pos += RSN_SELECTOR_LEN;
288
 
                left -= RSN_SELECTOR_LEN;
289
 
        } else if (left > 0) {
290
 
                wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
291
 
                           __func__, left);
292
 
                return -3;
293
 
        }
294
 
 
295
 
        if (left >= 2) {
296
 
                data->pairwise_cipher = 0;
297
 
                count = WPA_GET_LE16(pos);
298
 
                pos += 2;
299
 
                left -= 2;
300
 
                if (count == 0 || left < count * RSN_SELECTOR_LEN) {
301
 
                        wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
302
 
                                   "count %u left %u", __func__, count, left);
303
 
                        return -4;
304
 
                }
305
 
                for (i = 0; i < count; i++) {
306
 
                        data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
307
 
                        pos += RSN_SELECTOR_LEN;
308
 
                        left -= RSN_SELECTOR_LEN;
309
 
                }
310
 
#ifdef CONFIG_IEEE80211W
311
 
                if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {
312
 
                        wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "
313
 
                                   "pairwise cipher", __func__);
314
 
                        return -1;
315
 
                }
316
 
#endif /* CONFIG_IEEE80211W */
317
 
        } else if (left == 1) {
318
 
                wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
319
 
                           __func__);
320
 
                return -5;
321
 
        }
322
 
 
323
 
        if (left >= 2) {
324
 
                data->key_mgmt = 0;
325
 
                count = WPA_GET_LE16(pos);
326
 
                pos += 2;
327
 
                left -= 2;
328
 
                if (count == 0 || left < count * RSN_SELECTOR_LEN) {
329
 
                        wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
330
 
                                   "count %u left %u", __func__, count, left);
331
 
                        return -6;
332
 
                }
333
 
                for (i = 0; i < count; i++) {
334
 
                        data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
335
 
                        pos += RSN_SELECTOR_LEN;
336
 
                        left -= RSN_SELECTOR_LEN;
337
 
                }
338
 
        } else if (left == 1) {
339
 
                wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
340
 
                           __func__);
341
 
                return -7;
342
 
        }
343
 
 
344
 
        if (left >= 2) {
345
 
                data->capabilities = WPA_GET_LE16(pos);
346
 
                pos += 2;
347
 
                left -= 2;
348
 
        }
349
 
 
350
 
        if (left >= 2) {
351
 
                data->num_pmkid = WPA_GET_LE16(pos);
352
 
                pos += 2;
353
 
                left -= 2;
354
 
                if (left < (int) data->num_pmkid * PMKID_LEN) {
355
 
                        wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
356
 
                                   "(num_pmkid=%lu left=%d)",
357
 
                                   __func__, (unsigned long) data->num_pmkid,
358
 
                                   left);
359
 
                        data->num_pmkid = 0;
360
 
                        return -9;
361
 
                } else {
362
 
                        data->pmkid = pos;
363
 
                        pos += data->num_pmkid * PMKID_LEN;
364
 
                        left -= data->num_pmkid * PMKID_LEN;
365
 
                }
366
 
        }
367
 
 
368
 
#ifdef CONFIG_IEEE80211W
369
 
        if (left >= 4) {
370
 
                data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
371
 
                if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
372
 
                        wpa_printf(MSG_DEBUG, "%s: Unsupported management "
373
 
                                   "group cipher 0x%x", __func__,
374
 
                                   data->mgmt_group_cipher);
375
 
                        return -10;
376
 
                }
377
 
                pos += RSN_SELECTOR_LEN;
378
 
                left -= RSN_SELECTOR_LEN;
379
 
        }
380
 
#endif /* CONFIG_IEEE80211W */
381
 
 
382
 
        if (left > 0) {
383
 
                wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",
384
 
                           __func__, left);
385
 
        }
386
 
 
387
 
        return 0;
388
 
#else /* CONFIG_NO_WPA2 */
389
 
        return -1;
390
 
#endif /* CONFIG_NO_WPA2 */
391
 
}
392
 
 
393
 
 
394
 
#ifdef CONFIG_IEEE80211R
395
 
 
396
 
/**
397
 
 * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name
398
 
 *
399
 
 * IEEE 802.11r/D5.0 - 8.5.1.5.3
400
 
 */
401
 
void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
402
 
                       const u8 *ssid, size_t ssid_len,
403
 
                       const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
404
 
                       const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
405
 
{
406
 
        u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
407
 
               FT_R0KH_ID_MAX_LEN + ETH_ALEN];
408
 
        u8 *pos, r0_key_data[48], hash[32];
409
 
        const u8 *addr[2];
410
 
        size_t len[2];
411
 
 
412
 
        /*
413
 
         * R0-Key-Data = KDF-384(XXKey, "R0 Key Derivation",
414
 
         *                       SSIDlength || SSID || MDID || R0KHlength ||
415
 
         *                       R0KH-ID || S0KH-ID)
416
 
         * XXKey is either the second 256 bits of MSK or PSK.
417
 
         * PMK-R0 = L(R0-Key-Data, 0, 256)
418
 
         * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
419
 
         */
420
 
        if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
421
 
                return;
422
 
        pos = buf;
423
 
        *pos++ = ssid_len;
424
 
        os_memcpy(pos, ssid, ssid_len);
425
 
        pos += ssid_len;
426
 
        os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
427
 
        pos += MOBILITY_DOMAIN_ID_LEN;
428
 
        *pos++ = r0kh_id_len;
429
 
        os_memcpy(pos, r0kh_id, r0kh_id_len);
430
 
        pos += r0kh_id_len;
431
 
        os_memcpy(pos, s0kh_id, ETH_ALEN);
432
 
        pos += ETH_ALEN;
433
 
 
434
 
        sha256_prf(xxkey, xxkey_len, "R0 Key Derivation", buf, pos - buf,
435
 
                   r0_key_data, sizeof(r0_key_data));
436
 
        os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
437
 
 
438
 
        /*
439
 
         * PMKR0Name = Truncate-128(SHA-256("R0 Key Name" || PMK-R0Name-Salt)
440
 
         */
441
 
        addr[0] = (const u8 *) "R0 Key Name";
442
 
        len[0] = 11;
443
 
        addr[1] = r0_key_data + PMK_LEN;
444
 
        len[1] = 16;
445
 
 
446
 
        sha256_vector(2, addr, len, hash);
447
 
        os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
448
 
}
449
 
 
450
 
 
451
 
/**
452
 
 * wpa_derive_pmk_r1_name - Derive PMKR1Name
453
 
 *
454
 
 * IEEE 802.11r/D5.0 - 8.5.1.5.4
455
 
 */
456
 
void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
457
 
                            const u8 *s1kh_id, u8 *pmk_r1_name)
458
 
{
459
 
        u8 hash[32];
460
 
        const u8 *addr[4];
461
 
        size_t len[4];
462
 
 
463
 
        /*
464
 
         * PMKR1Name = Truncate-128(SHA-256("R1 Key Name" || PMKR0Name ||
465
 
         *                                  R1KH-ID || S1KH-ID))
466
 
         */
467
 
        addr[0] = (const u8 *) "R1 Key Name";
468
 
        len[0] = 11;
469
 
        addr[1] = pmk_r0_name;
470
 
        len[1] = WPA_PMK_NAME_LEN;
471
 
        addr[2] = r1kh_id;
472
 
        len[2] = FT_R1KH_ID_LEN;
473
 
        addr[3] = s1kh_id;
474
 
        len[3] = ETH_ALEN;
475
 
 
476
 
        sha256_vector(4, addr, len, hash);
477
 
        os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
478
 
}
479
 
 
480
 
 
481
 
/**
482
 
 * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0
483
 
 *
484
 
 * IEEE 802.11r/D5.0 - 8.5.1.5.4
485
 
 */
486
 
void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
487
 
                       const u8 *r1kh_id, const u8 *s1kh_id,
488
 
                       u8 *pmk_r1, u8 *pmk_r1_name)
489
 
{
490
 
        u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
491
 
        u8 *pos;
492
 
 
493
 
        /* PMK-R1 = KDF-256(PMK-R0, "R1 Key Derivation", R1KH-ID || S1KH-ID) */
494
 
        pos = buf;
495
 
        os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
496
 
        pos += FT_R1KH_ID_LEN;
497
 
        os_memcpy(pos, s1kh_id, ETH_ALEN);
498
 
        pos += ETH_ALEN;
499
 
 
500
 
        sha256_prf(pmk_r0, PMK_LEN, "R1 Key Derivation", buf, pos - buf,
501
 
                   pmk_r1, PMK_LEN);
502
 
 
503
 
        wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name);
504
 
}
505
 
 
506
 
 
507
 
/**
508
 
 * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1
509
 
 *
510
 
 * IEEE 802.11r/D5.0 - 8.5.1.5.5
511
 
 */
512
 
void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
513
 
                       const u8 *sta_addr, const u8 *bssid,
514
 
                       const u8 *pmk_r1_name,
515
 
                       u8 *ptk, size_t ptk_len, u8 *ptk_name)
516
 
{
517
 
        u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
518
 
        u8 *pos, hash[32];
519
 
        const u8 *addr[6];
520
 
        size_t len[6];
521
 
 
522
 
        /*
523
 
         * PTK = KDF-PTKLen(PMK-R1, "PTK Key derivation", SNonce || ANonce ||
524
 
         *                  BSSID || STA-ADDR)
525
 
         */
526
 
        pos = buf;
527
 
        os_memcpy(pos, snonce, WPA_NONCE_LEN);
528
 
        pos += WPA_NONCE_LEN;
529
 
        os_memcpy(pos, anonce, WPA_NONCE_LEN);
530
 
        pos += WPA_NONCE_LEN;
531
 
        os_memcpy(pos, bssid, ETH_ALEN);
532
 
        pos += ETH_ALEN;
533
 
        os_memcpy(pos, sta_addr, ETH_ALEN);
534
 
        pos += ETH_ALEN;
535
 
 
536
 
        sha256_prf(pmk_r1, PMK_LEN, "PTK Key derivation", buf, pos - buf,
537
 
                   ptk, ptk_len);
538
 
 
539
 
        /*
540
 
         * PTKName = Truncate-128(SHA-256(PMKR1Name || "PTK Name" || SNonce ||
541
 
         *                                ANonce || BSSID || STA-ADDR))
542
 
         */
543
 
        addr[0] = pmk_r1_name;
544
 
        len[0] = WPA_PMK_NAME_LEN;
545
 
        addr[1] = (const u8 *) "PTK Name";
546
 
        len[1] = 8;
547
 
        addr[2] = snonce;
548
 
        len[2] = WPA_NONCE_LEN;
549
 
        addr[3] = anonce;
550
 
        len[3] = WPA_NONCE_LEN;
551
 
        addr[4] = bssid;
552
 
        len[4] = ETH_ALEN;
553
 
        addr[5] = sta_addr;
554
 
        len[5] = ETH_ALEN;
555
 
 
556
 
        sha256_vector(6, addr, len, hash);
557
 
        os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
558
 
}
559
 
 
560
 
#endif /* CONFIG_IEEE80211R */