1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * WPA/RSN - Shared functions for supplicant and authenticator 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi> 4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify 6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation. 8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license. 11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details. 13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 18b349ef9e9f3f5399bf96b3c1c663cb9e547f50a1Dmitry Shmidt#include "crypto/md5.h" 19b349ef9e9f3f5399bf96b3c1c663cb9e547f50a1Dmitry Shmidt#include "crypto/sha1.h" 20b349ef9e9f3f5399bf96b3c1c663cb9e547f50a1Dmitry Shmidt#include "crypto/sha256.h" 21b349ef9e9f3f5399bf96b3c1c663cb9e547f50a1Dmitry Shmidt#include "crypto/aes_wrap.h" 22b349ef9e9f3f5399bf96b3c1c663cb9e547f50a1Dmitry Shmidt#include "crypto/crypto.h" 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "ieee802_11_defs.h" 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "defs.h" 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wpa_common.h" 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * wpa_eapol_key_mic - Calculate EAPOL-Key MIC 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @key: EAPOL-Key Key Confirmation Key (KCK) 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*) 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @buf: Pointer to the beginning of the EAPOL header (version field) 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame) 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: 0 on success, -1 on failure 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * to be cleared (all zeroes) when calling this function. 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * description of the Key MIC calculation. It includes packet data from the 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * happened during final editing of the standard and the correct behavior is 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * defined in the last draft (IEEE 802.11i/D10). 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *mic) 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 hash[SHA1_MAC_LEN]; 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (ver) { 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hmac_md5(key, 16, buf, len, mic); 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hmac_sha1(key, 16, buf, len, hash); 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(mic, hash, MD5_MAC_LEN); 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WPA_KEY_INFO_TYPE_AES_128_CMAC: 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return omac1_aes_128(key, buf, len, mic); 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @pmk: Pairwise master key 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @pmk_len: Length of PMK 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @label: Label to use in derivation 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @addr1: AA or SA 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @addr2: SA or AA 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @nonce1: ANonce or SNonce 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @nonce2: SNonce or ANonce 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @ptk: Buffer for pairwise transient key 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @ptk_len: Length of PTK 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @use_sha256: Whether to use SHA256-based KDF 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * PTK = PRF-X(PMK, "Pairwise key expansion", 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Min(AA, SA) || Max(AA, SA) || 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Min(ANonce, SNonce) || Max(ANonce, SNonce)) 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * STK = PRF-X(SMK, "Peer key expansion", 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) || 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Min(INonce, PNonce) || Max(INonce, PNonce)) 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *addr1, const u8 *addr2, 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *nonce1, const u8 *nonce2, 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *ptk, size_t ptk_len, int use_sha256) 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) { 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data, addr1, ETH_ALEN); 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN); 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data, addr2, ETH_ALEN); 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN); 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) { 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN); 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2, 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_NONCE_LEN); 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN); 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1, 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_NONCE_LEN); 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211W 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (use_sha256) 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sha256_prf(pmk, pmk_len, label, data, sizeof(data), 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ptk, ptk_len); 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ptk_len); 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR, 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MAC2STR(addr1), MAC2STR(addr2)); 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len); 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211R 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr, 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 transaction_seqnum, const u8 *mdie, size_t mdie_len, 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *ftie, size_t ftie_len, 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *rsnie, size_t rsnie_len, 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *ric, size_t ric_len, u8 *mic) 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *buf, *pos; 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t buf_len; 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len; 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = os_malloc(buf_len); 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (buf == NULL) 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = buf; 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, sta_addr, ETH_ALEN); 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += ETH_ALEN; 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, ap_addr, ETH_ALEN); 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += ETH_ALEN; 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = transaction_seqnum; 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (rsnie) { 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, rsnie, rsnie_len); 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += rsnie_len; 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (mdie) { 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, mdie, mdie_len); 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += mdie_len; 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ftie) { 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct rsn_ftie *_ftie; 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, ftie, ftie_len); 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ftie_len < 2 + sizeof(*_ftie)) { 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt _ftie = (struct rsn_ftie *) (pos + 2); 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(_ftie->mic, 0, sizeof(_ftie->mic)); 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += ftie_len; 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ric) { 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, ric, ric_len); 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += ric_len; 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf); 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (omac1_aes_128(kck, buf, pos - buf, mic)) { 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211R */ 190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef CONFIG_NO_WPA2 193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int rsn_selector_to_bitfield(const u8 *s) 194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE) 196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return WPA_CIPHER_NONE; 197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40) 198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return WPA_CIPHER_WEP40; 199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP) 200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return WPA_CIPHER_TKIP; 201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP) 202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return WPA_CIPHER_CCMP; 203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104) 204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return WPA_CIPHER_WEP104; 205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211W 206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC) 207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return WPA_CIPHER_AES_128_CMAC; 208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int rsn_key_mgmt_to_bitfield(const u8 *s) 214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X) 216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return WPA_KEY_MGMT_IEEE8021X; 217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X) 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return WPA_KEY_MGMT_PSK; 219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211R 220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X) 221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return WPA_KEY_MGMT_FT_IEEE8021X; 222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK) 223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return WPA_KEY_MGMT_FT_PSK; 224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211R */ 225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211W 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256) 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return WPA_KEY_MGMT_IEEE8021X_SHA256; 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256) 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return WPA_KEY_MGMT_PSK_SHA256; 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_NO_WPA2 */ 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * wpa_parse_wpa_ie_rsn - Parse RSN IE 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @rsn_ie: Buffer containing RSN IE 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @rsn_ie_len: RSN IE buffer length (including IE number and length octets) 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @data: Pointer to structure that will be filled in with parsed data 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: 0 on success, <0 on failure 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ie_data *data) 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef CONFIG_NO_WPA2 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct rsn_ie_hdr *hdr; 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos; 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int left; 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int i, count; 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(data, 0, sizeof(*data)); 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->proto = WPA_PROTO_RSN; 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->pairwise_cipher = WPA_CIPHER_CCMP; 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->group_cipher = WPA_CIPHER_CCMP; 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->capabilities = 0; 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->pmkid = NULL; 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->num_pmkid = 0; 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211W 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* CONFIG_IEEE80211W */ 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->mgmt_group_cipher = 0; 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (rsn_ie_len == 0) { 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* No RSN IE - fail silently */ 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) { 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt __func__, (unsigned long) rsn_ie_len); 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr = (const struct rsn_ie_hdr *) rsn_ie; 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (hdr->elem_id != WLAN_EID_RSN || 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr->len != rsn_ie_len - 2 || 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_GET_LE16(hdr->version) != RSN_VERSION) { 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt __func__); 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -2; 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = (const u8 *) (hdr + 1); 288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left = rsn_ie_len - sizeof(*hdr); 289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (left >= RSN_SELECTOR_LEN) { 291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->group_cipher = rsn_selector_to_bitfield(pos); 292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211W 293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) { 294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group " 295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "cipher", __func__); 296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += RSN_SELECTOR_LEN; 300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left -= RSN_SELECTOR_LEN; 301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (left > 0) { 302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", 303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt __func__, left); 304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -3; 305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (left >= 2) { 308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->pairwise_cipher = 0; 309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt count = WPA_GET_LE16(pos); 310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left -= 2; 312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (count == 0 || left < count * RSN_SELECTOR_LEN) { 313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " 314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "count %u left %u", __func__, count, left); 315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -4; 316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < count; i++) { 318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->pairwise_cipher |= rsn_selector_to_bitfield(pos); 319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += RSN_SELECTOR_LEN; 320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left -= RSN_SELECTOR_LEN; 321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211W 323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) { 324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as " 325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "pairwise cipher", __func__); 326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (left == 1) { 330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", 331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt __func__); 332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -5; 333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (left >= 2) { 336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->key_mgmt = 0; 337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt count = WPA_GET_LE16(pos); 338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left -= 2; 340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (count == 0 || left < count * RSN_SELECTOR_LEN) { 341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " 342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "count %u left %u", __func__, count, left); 343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -6; 344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < count; i++) { 346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos); 347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += RSN_SELECTOR_LEN; 348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left -= RSN_SELECTOR_LEN; 349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (left == 1) { 351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", 352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt __func__); 353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -7; 354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (left >= 2) { 357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->capabilities = WPA_GET_LE16(pos); 358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left -= 2; 360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (left >= 2) { 363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->num_pmkid = WPA_GET_LE16(pos); 364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left -= 2; 366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (left < (int) data->num_pmkid * PMKID_LEN) { 367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: PMKID underflow " 368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(num_pmkid=%lu left=%d)", 369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt __func__, (unsigned long) data->num_pmkid, 370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left); 371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->num_pmkid = 0; 372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -9; 373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->pmkid = pos; 375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += data->num_pmkid * PMKID_LEN; 376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left -= data->num_pmkid * PMKID_LEN; 377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211W 381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (left >= 4) { 382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->mgmt_group_cipher = rsn_selector_to_bitfield(pos); 383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) { 384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Unsupported management " 385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "group cipher 0x%x", __func__, 386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->mgmt_group_cipher); 387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -10; 388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += RSN_SELECTOR_LEN; 390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left -= RSN_SELECTOR_LEN; 391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (left > 0) { 395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", 396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt __func__, left); 397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* CONFIG_NO_WPA2 */ 401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_NO_WPA2 */ 403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211R 407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name 410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * IEEE Std 802.11r-2008 - 8.5.1.5.3 412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, 414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *ssid, size_t ssid_len, 415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, 416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name) 417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 + 419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt FT_R0KH_ID_MAX_LEN + ETH_ALEN]; 420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *pos, r0_key_data[48], hash[32]; 421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *addr[2]; 422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len[2]; 423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * R0-Key-Data = KDF-384(XXKey, "FT-R0", 426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * SSIDlength || SSID || MDID || R0KHlength || 427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * R0KH-ID || S0KH-ID) 428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * XXKey is either the second 256 bits of MSK or PSK. 429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * PMK-R0 = L(R0-Key-Data, 0, 256) 430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128) 431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN) 433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = buf; 435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = ssid_len; 436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, ssid, ssid_len); 437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += ssid_len; 438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN); 439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += MOBILITY_DOMAIN_ID_LEN; 440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = r0kh_id_len; 441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, r0kh_id, r0kh_id_len); 442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += r0kh_id_len; 443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, s0kh_id, ETH_ALEN); 444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += ETH_ALEN; 445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf, 447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt r0_key_data, sizeof(r0_key_data)); 448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pmk_r0, r0_key_data, PMK_LEN); 449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt) 452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[0] = (const u8 *) "FT-R0N"; 454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[0] = 6; 455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[1] = r0_key_data + PMK_LEN; 456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[1] = 16; 457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sha256_vector(2, addr, len, hash); 459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN); 460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * wpa_derive_pmk_r1_name - Derive PMKR1Name 465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * IEEE Std 802.11r-2008 - 8.5.1.5.4 467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, 469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *s1kh_id, u8 *pmk_r1_name) 470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 hash[32]; 472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *addr[4]; 473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len[4]; 474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name || 477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * R1KH-ID || S1KH-ID)) 478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[0] = (const u8 *) "FT-R1N"; 480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[0] = 6; 481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[1] = pmk_r0_name; 482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[1] = WPA_PMK_NAME_LEN; 483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[2] = r1kh_id; 484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[2] = FT_R1KH_ID_LEN; 485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[3] = s1kh_id; 486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[3] = ETH_ALEN; 487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sha256_vector(4, addr, len, hash); 489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN); 490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0 495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * IEEE Std 802.11r-2008 - 8.5.1.5.4 497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, 499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *r1kh_id, const u8 *s1kh_id, 500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *pmk_r1, u8 *pmk_r1_name) 501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 buf[FT_R1KH_ID_LEN + ETH_ALEN]; 503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *pos; 504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */ 506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = buf; 507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN); 508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += FT_R1KH_ID_LEN; 509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, s1kh_id, ETH_ALEN); 510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += ETH_ALEN; 511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN); 513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name); 515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1 520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * IEEE Std 802.11r-2008 - 8.5.1.5.5 522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, 524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *sta_addr, const u8 *bssid, 525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pmk_r1_name, 526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *ptk, size_t ptk_len, u8 *ptk_name) 527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN]; 529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *pos, hash[32]; 530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *addr[6]; 531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len[6]; 532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce || 535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * BSSID || STA-ADDR) 536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = buf; 538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, snonce, WPA_NONCE_LEN); 539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += WPA_NONCE_LEN; 540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, anonce, WPA_NONCE_LEN); 541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += WPA_NONCE_LEN; 542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, bssid, ETH_ALEN); 543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += ETH_ALEN; 544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, sta_addr, ETH_ALEN); 545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += ETH_ALEN; 546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len); 548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce || 551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * ANonce || BSSID || STA-ADDR)) 552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[0] = pmk_r1_name; 554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[0] = WPA_PMK_NAME_LEN; 555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[1] = (const u8 *) "FT-PTKN"; 556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[1] = 7; 557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[2] = snonce; 558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[2] = WPA_NONCE_LEN; 559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[3] = anonce; 560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[3] = WPA_NONCE_LEN; 561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[4] = bssid; 562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[4] = ETH_ALEN; 563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[5] = sta_addr; 564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[5] = ETH_ALEN; 565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sha256_vector(6, addr, len, hash); 567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN); 568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211R */ 571