static int tdls_derive_tpk(struct wlantest_tdls *tdls, const u8 *bssid, const u8 *ftie, u8 ftie_len) { const struct rsn_ftie *f; u8 key_input[SHA256_MAC_LEN]; const u8 *nonce[2]; size_t len[2]; u8 data[3 * ETH_ALEN]; if (ftie == NULL || ftie_len < sizeof(struct rsn_ftie)) return 0; f = (const struct rsn_ftie *) ftie; wpa_hexdump(MSG_DEBUG, "TDLS ANonce", f->anonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "TDLS SNonce", f->snonce, WPA_NONCE_LEN); /* * IEEE Std 802.11z-2010 8.5.9.1: * TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce)) */ len[0] = WPA_NONCE_LEN; len[1] = WPA_NONCE_LEN; if (os_memcmp(f->anonce, f->snonce, WPA_NONCE_LEN) < 0) { nonce[0] = f->anonce; nonce[1] = f->snonce; } else { nonce[0] = f->snonce; nonce[1] = f->anonce; } sha256_vector(2, nonce, len, key_input); wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-Key-Input", key_input, SHA256_MAC_LEN); /* * TPK-Key-Data = KDF-N_KEY(TPK-Key-Input, "TDLS PMK", * min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID || N_KEY) * TODO: is N_KEY really included in KDF Context and if so, in which * presentation format (little endian 16-bit?) is it used? It gets * added by the KDF anyway.. */ if (os_memcmp(tdls->init->addr, tdls->resp->addr, ETH_ALEN) < 0) { os_memcpy(data, tdls->init->addr, ETH_ALEN); os_memcpy(data + ETH_ALEN, tdls->resp->addr, ETH_ALEN); } else { os_memcpy(data, tdls->resp->addr, ETH_ALEN); os_memcpy(data + ETH_ALEN, tdls->init->addr, ETH_ALEN); } os_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN); wpa_hexdump(MSG_DEBUG, "TDLS: KDF Context", data, sizeof(data)); sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data), (u8 *) &tdls->tpk, sizeof(tdls->tpk)); wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-KCK", tdls->tpk.kck, sizeof(tdls->tpk.kck)); wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-TK", tdls->tpk.tk, sizeof(tdls->tpk.tk)); return 1; }
/** * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces * @pmk: Pairwise master key * @pmk_len: Length of PMK * @label: Label to use in derivation * @addr1: AA or SA * @addr2: SA or AA * @nonce1: ANonce or SNonce * @nonce2: SNonce or ANonce * @ptk: Buffer for pairwise transient key * @akmp: Negotiated AKM * @cipher: Negotiated pairwise cipher * Returns: 0 on success, -1 on failure * * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * PTK = PRF-X(PMK, "Pairwise key expansion", * Min(AA, SA) || Max(AA, SA) || * Min(ANonce, SNonce) || Max(ANonce, SNonce)) * * STK = PRF-X(SMK, "Peer key expansion", * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) || * Min(INonce, PNonce) || Max(INonce, PNonce)) */ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, const u8 *addr1, const u8 *addr2, const u8 *nonce1, const u8 *nonce2, struct wpa_ptk *ptk, int akmp, int cipher) { u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; size_t ptk_len; if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) { os_memcpy(data, addr1, ETH_ALEN); os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN); } else { os_memcpy(data, addr2, ETH_ALEN); os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN); } if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) { os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN); os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2, WPA_NONCE_LEN); } else { os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN); os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1, WPA_NONCE_LEN); } ptk->kck_len = wpa_kck_len(akmp); ptk->kek_len = wpa_kek_len(akmp); ptk->tk_len = wpa_cipher_key_len(cipher); ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len; #ifdef CONFIG_IEEE80211W if (wpa_key_mgmt_sha256(akmp)) sha256_prf(pmk, pmk_len, label, data, sizeof(data), tmp, ptk_len); else #endif /* CONFIG_IEEE80211W */ sha1_prf(pmk, pmk_len, label, data, sizeof(data), tmp, ptk_len); wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2)); wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN); wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", tmp, ptk_len); os_memcpy(ptk->kck, tmp, ptk->kck_len); wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", ptk->kck, ptk->kck_len); os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len); wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", ptk->kek, ptk->kek_len); os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len); wpa_hexdump_key(MSG_DEBUG, "WPA: TK", ptk->tk, ptk->tk_len); os_memset(tmp, 0, sizeof(tmp)); return 0; }
/* derive mesh temporal key from pmk */ int mesh_rsn_derive_mtk(struct wpa_supplicant *wpa_s, struct sta_info *sta) { u8 *ptr; u8 *min, *max; u16 min_lid, max_lid; size_t nonce_len = sizeof(sta->my_nonce); size_t lid_len = sizeof(sta->my_lid); u8 *myaddr = wpa_s->own_addr; u8 *peer = sta->addr; /* 2 nonces, 2 linkids, akm suite, 2 mac addrs */ u8 context[64 + 4 + 4 + 12]; ptr = context; if (os_memcmp(sta->my_nonce, sta->peer_nonce, nonce_len) < 0) { min = sta->my_nonce; max = sta->peer_nonce; } else { min = sta->peer_nonce; max = sta->my_nonce; } os_memcpy(ptr, min, nonce_len); os_memcpy(ptr + nonce_len, max, nonce_len); ptr += 2 * nonce_len; if (sta->my_lid < sta->peer_lid) { min_lid = host_to_le16(sta->my_lid); max_lid = host_to_le16(sta->peer_lid); } else { min_lid = host_to_le16(sta->peer_lid); max_lid = host_to_le16(sta->my_lid); } os_memcpy(ptr, &min_lid, lid_len); os_memcpy(ptr + lid_len, &max_lid, lid_len); ptr += 2 * lid_len; /* SAE */ RSN_SELECTOR_PUT(ptr, wpa_cipher_to_suite(0, WPA_CIPHER_GCMP)); ptr += 4; if (os_memcmp(myaddr, peer, ETH_ALEN) < 0) { min = myaddr; max = peer; } else { min = peer; max = myaddr; } os_memcpy(ptr, min, ETH_ALEN); os_memcpy(ptr + ETH_ALEN, max, ETH_ALEN); sha256_prf(sta->sae->pmk, sizeof(sta->sae->pmk), "Temporal Key Derivation", context, sizeof(context), sta->mtk, sizeof(sta->mtk)); return 0; }
/** * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name * * IEEE Std 802.11r-2008 - 8.5.1.5.3 */ void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, const u8 *ssid, size_t ssid_len, const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name) { u8 buf[1 + SSID_MAX_LEN + MOBILITY_DOMAIN_ID_LEN + 1 + FT_R0KH_ID_MAX_LEN + ETH_ALEN]; u8 *pos, r0_key_data[48], hash[32]; const u8 *addr[2]; size_t len[2]; /* * R0-Key-Data = KDF-384(XXKey, "FT-R0", * SSIDlength || SSID || MDID || R0KHlength || * R0KH-ID || S0KH-ID) * XXKey is either the second 256 bits of MSK or PSK. * PMK-R0 = L(R0-Key-Data, 0, 256) * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128) */ if (ssid_len > SSID_MAX_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN) return; pos = buf; *pos++ = ssid_len; os_memcpy(pos, ssid, ssid_len); pos += ssid_len; os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN); pos += MOBILITY_DOMAIN_ID_LEN; *pos++ = r0kh_id_len; os_memcpy(pos, r0kh_id, r0kh_id_len); pos += r0kh_id_len; os_memcpy(pos, s0kh_id, ETH_ALEN); pos += ETH_ALEN; sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf, r0_key_data, sizeof(r0_key_data)); os_memcpy(pmk_r0, r0_key_data, PMK_LEN); /* * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt) */ addr[0] = (const u8 *) "FT-R0N"; len[0] = 6; addr[1] = r0_key_data + PMK_LEN; len[1] = 16; sha256_vector(2, addr, len, hash); os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN); }
/** * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1 * * IEEE Std 802.11r-2008 - 8.5.1.5.5 */ void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, const u8 *sta_addr, const u8 *bssid, const u8 *pmk_r1_name, u8 *ptk, size_t ptk_len, u8 *ptk_name) { u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN]; u8 *pos, hash[32]; const u8 *addr[6]; size_t len[6]; /* * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce || * BSSID || STA-ADDR) */ pos = buf; os_memcpy(pos, snonce, WPA_NONCE_LEN); pos += WPA_NONCE_LEN; os_memcpy(pos, anonce, WPA_NONCE_LEN); pos += WPA_NONCE_LEN; os_memcpy(pos, bssid, ETH_ALEN); pos += ETH_ALEN; os_memcpy(pos, sta_addr, ETH_ALEN); pos += ETH_ALEN; sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len); /* * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce || * ANonce || BSSID || STA-ADDR)) */ addr[0] = pmk_r1_name; len[0] = WPA_PMK_NAME_LEN; addr[1] = (const u8 *) "FT-PTKN"; len[1] = 7; addr[2] = snonce; len[2] = WPA_NONCE_LEN; addr[3] = anonce; len[3] = WPA_NONCE_LEN; addr[4] = bssid; len[4] = ETH_ALEN; addr[5] = sta_addr; len[5] = ETH_ALEN; sha256_vector(6, addr, len, hash); os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN); }
/** * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0 * * IEEE Std 802.11r-2008 - 8.5.1.5.4 */ void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, const u8 *r1kh_id, const u8 *s1kh_id, u8 *pmk_r1, u8 *pmk_r1_name) { u8 buf[FT_R1KH_ID_LEN + ETH_ALEN]; u8 *pos; /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */ pos = buf; os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN); pos += FT_R1KH_ID_LEN; os_memcpy(pos, s1kh_id, ETH_ALEN); pos += ETH_ALEN; sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN); wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name); }
/** * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces * @pmk: Pairwise master key * @pmk_len: Length of PMK * @label: Label to use in derivation * @addr1: AA or SA * @addr2: SA or AA * @nonce1: ANonce or SNonce * @nonce2: SNonce or ANonce * @ptk: Buffer for pairwise transient key * @ptk_len: Length of PTK * @use_sha256: Whether to use SHA256-based KDF * * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * PTK = PRF-X(PMK, "Pairwise key expansion", * Min(AA, SA) || Max(AA, SA) || * Min(ANonce, SNonce) || Max(ANonce, SNonce)) * * STK = PRF-X(SMK, "Peer key expansion", * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) || * Min(INonce, PNonce) || Max(INonce, PNonce)) */ void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, const u8 *addr1, const u8 *addr2, const u8 *nonce1, const u8 *nonce2, u8 *ptk, size_t ptk_len, int use_sha256) { u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) { os_memcpy(data, addr1, ETH_ALEN); os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN); } else { os_memcpy(data, addr2, ETH_ALEN); os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN); } if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) { os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN); os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2, WPA_NONCE_LEN); } else { os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN); os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1, WPA_NONCE_LEN); } #ifdef CONFIG_IEEE80211W if (use_sha256) sha256_prf(pmk, pmk_len, label, data, sizeof(data), ptk, ptk_len); else #endif /* CONFIG_IEEE80211W */ sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, ptk_len); wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2)); wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN); wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len); }
static void mesh_rsn_derive_aek(struct mesh_rsn *rsn, struct sta_info *sta) { u8 *myaddr = rsn->wpa_s->own_addr; u8 *peer = sta->addr; u8 *addr1 = peer, *addr2 = myaddr; u8 context[AES_BLOCK_SIZE]; /* SAE */ RSN_SELECTOR_PUT(context, wpa_cipher_to_suite(0, WPA_CIPHER_GCMP)); if (os_memcmp(myaddr, peer, ETH_ALEN) < 0) { addr1 = myaddr; addr2 = peer; } os_memcpy(context + 4, addr1, ETH_ALEN); os_memcpy(context + 10, addr2, ETH_ALEN); sha256_prf(sta->sae->pmk, sizeof(sta->sae->pmk), "AEK Derivation", context, sizeof(context), sta->aek, sizeof(sta->aek)); }
/** * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1 * * IEEE Std 802.11r-2008 - 8.5.1.5.5 */ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, const u8 *sta_addr, const u8 *bssid, const u8 *pmk_r1_name, struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher) { u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN]; u8 *pos, hash[32]; const u8 *addr[6]; size_t len[6]; u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; size_t ptk_len; /* * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce || * BSSID || STA-ADDR) */ pos = buf; os_memcpy(pos, snonce, WPA_NONCE_LEN); pos += WPA_NONCE_LEN; os_memcpy(pos, anonce, WPA_NONCE_LEN); pos += WPA_NONCE_LEN; os_memcpy(pos, bssid, ETH_ALEN); pos += ETH_ALEN; os_memcpy(pos, sta_addr, ETH_ALEN); pos += ETH_ALEN; ptk->kck_len = wpa_kck_len(akmp); ptk->kek_len = wpa_kek_len(akmp); ptk->tk_len = wpa_cipher_key_len(cipher); ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len; sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, tmp, ptk_len); /* * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce || * ANonce || BSSID || STA-ADDR)) */ addr[0] = pmk_r1_name; len[0] = WPA_PMK_NAME_LEN; addr[1] = (const u8 *) "FT-PTKN"; len[1] = 7; addr[2] = snonce; len[2] = WPA_NONCE_LEN; addr[3] = anonce; len[3] = WPA_NONCE_LEN; addr[4] = bssid; len[4] = ETH_ALEN; addr[5] = sta_addr; len[5] = ETH_ALEN; sha256_vector(6, addr, len, hash); os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN); os_memcpy(ptk->kck, tmp, ptk->kck_len); os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len); os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len); wpa_hexdump_key(MSG_DEBUG, "FT: KCK", ptk->kck, ptk->kck_len); wpa_hexdump_key(MSG_DEBUG, "FT: KEK", ptk->kek, ptk->kek_len); wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len); wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); os_memset(tmp, 0, sizeof(tmp)); return 0; }
int main(int argc, char *argv[]) { unsigned int i; u8 hash[32]; const u8 *addr[2]; size_t len[2]; int errors = 0; for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { printf("SHA256 test case %d:", i + 1); addr[0] = (u8 *) tests[i].data; len[0] = strlen(tests[i].data); sha256_vector(1, addr, len, hash); if (memcmp(hash, tests[i].hash, 32) != 0) { printf(" FAIL"); errors++; } else printf(" OK"); if (len[0]) { addr[0] = (u8 *) tests[i].data; len[0] = 1; addr[1] = (u8 *) tests[i].data + 1; len[1] = strlen(tests[i].data) - 1; sha256_vector(2, addr, len, hash); if (memcmp(hash, tests[i].hash, 32) != 0) { printf(" FAIL"); errors++; } else printf(" OK"); } printf("\n"); } for (i = 0; i < sizeof(hmac_tests) / sizeof(hmac_tests[0]); i++) { struct hmac_test *t = &hmac_tests[i]; printf("HMAC-SHA256 test case %d:", i + 1); hmac_sha256(t->key, t->key_len, t->data, t->data_len, hash); if (memcmp(hash, t->hash, 32) != 0) { printf(" FAIL"); errors++; } else printf(" OK"); addr[0] = t->data; len[0] = t->data_len; hmac_sha256_vector(t->key, t->key_len, 1, addr, len, hash); if (memcmp(hash, t->hash, 32) != 0) { printf(" FAIL"); errors++; } else printf(" OK"); if (len[0]) { addr[0] = t->data; len[0] = 1; addr[1] = t->data + 1; len[1] = t->data_len - 1; hmac_sha256_vector(t->key, t->key_len, 2, addr, len, hash); if (memcmp(hash, t->hash, 32) != 0) { printf(" FAIL"); errors++; } else printf(" OK"); } printf("\n"); } printf("Test IEEE 802.11r KDF\n"); sha256_prf("abc", 3, "KDF test", "data", 4, hash, sizeof(hash)); /* TODO: add proper test case for this */ return errors; }
void wpa_smk_m3(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, struct wpa_eapol_key *key) { struct wpa_eapol_ie_parse kde; struct wpa_stsl_search search; u8 smk[32], buf[ETH_ALEN + 8 + 2 * WPA_NONCE_LEN], *pos; if (wpa_parse_kde_ies((const u8 *) (key + 1), WPA_GET_BE16(key->key_data_length), &kde) < 0) { wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M3"); return; } if (kde.rsn_ie == NULL || kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN) { wpa_printf(MSG_INFO, "RSN: No RSN IE, MAC address KDE, or " "Nonce KDE in SMK M3"); return; } /* Peer = sm->addr; Initiator = kde.mac_addr; * Peer Nonce = key->key_nonce; Initiator Nonce = kde.nonce */ search.addr = kde.mac_addr; search.sm = NULL; if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) == 0 || search.sm == NULL) { wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR " aborted - STA not associated anymore", MAC2STR(kde.mac_addr)); wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK, STK_ERR_STA_NR); /* FIX: wpa_stsl_remove(wpa_auth, neg); */ return; } if (os_get_random(smk, PMK_LEN)) { wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK"); return; } /* SMK = PRF-256(Random number, "SMK Derivation", * AA || Time || INonce || PNonce) */ os_memcpy(buf, wpa_auth->addr, ETH_ALEN); pos = buf + ETH_ALEN; wpa_get_ntp_timestamp(pos); pos += 8; os_memcpy(pos, kde.nonce, WPA_NONCE_LEN); pos += WPA_NONCE_LEN; os_memcpy(pos, key->key_nonce, WPA_NONCE_LEN); #ifdef CONFIG_IEEE80211W sha256_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf), smk, PMK_LEN); #else /* CONFIG_IEEE80211W */ sha1_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf), smk, PMK_LEN); #endif /* CONFIG_IEEE80211W */ wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", smk, PMK_LEN); wpa_send_smk_m4(wpa_auth, sm, key, &kde, smk); wpa_send_smk_m5(wpa_auth, search.sm, key, &kde, smk, sm->addr); /* Authenticator does not need SMK anymore and it is required to forget * it. */ os_memset(smk, 0, sizeof(*smk)); }