Cumulative patch from commit 3f56a2b7460a57a2b68b48b936be134bf04aa36d (DO NOT MERGE)

3f56a2b Ignore pmf=1 default if driver does not support PMF
fa38860 nl80211: Fix build with libnl 1.1
937403b Update copyright notices for the new year 2015
399e613 Add Suite B AKMs to key_mgmt capability list
5e3b519 Add Suite B 192-bit AKM
97ae35a Add HMAC-SHA384
98cd3d1 Preparations for variable length KCK and KEK
30bff1d Extend AES-CMAC routines to support 256-bit keys
86f9b1c nl80211: Fix default group key management index configuration
b5f045d Show supported group_mgmt capabilities
893e152 Interworking: More debug messages
f45bae5 Interworking: Add logging to track nai_realm_find_eap failures
5a5aab7 Interworking: Remove unnecessary NULL check
400de9b hostapd: Debug messages for dodgy RADIUS servers
ad905e4 wpa_gui: Sort frequency and signal numerically in the scan results dialog
c35e35e Add passive_scan configuration parameter
bff162a P2P: Fix NULL pointer dereference with SD query cancellation
630b323 nl80211: Increase netlink receive buffer size

Change-Id: I32d4bd934ad76e24c646e9925bb839b1ba2a148e
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index a573e11..de81d53 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -1,6 +1,6 @@
 /*
  * WPA/RSN - Shared functions for supplicant and authenticator
- * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -12,6 +12,7 @@
 #include "crypto/md5.h"
 #include "crypto/sha1.h"
 #include "crypto/sha256.h"
+#include "crypto/sha384.h"
 #include "crypto/aes_wrap.h"
 #include "crypto/crypto.h"
 #include "ieee802_11_defs.h"
@@ -19,9 +20,34 @@
 #include "wpa_common.h"
 
 
+static unsigned int wpa_kck_len(int akmp)
+{
+	if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
+		return 24;
+	return 16;
+}
+
+
+static unsigned int wpa_kek_len(int akmp)
+{
+	if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
+		return 32;
+	return 16;
+}
+
+
+unsigned int wpa_mic_len(int akmp)
+{
+	if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
+		return 24;
+	return 16;
+}
+
+
 /**
  * wpa_eapol_key_mic - Calculate EAPOL-Key MIC
  * @key: EAPOL-Key Key Confirmation Key (KCK)
+ * @key_len: KCK length in octets
  * @akmp: WPA_KEY_MGMT_* used in key derivation
  * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*)
  * @buf: Pointer to the beginning of the EAPOL header (version field)
@@ -38,18 +64,18 @@
  * happened during final editing of the standard and the correct behavior is
  * defined in the last draft (IEEE 802.11i/D10).
  */
-int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf,
-		      size_t len, u8 *mic)
+int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
+		      const u8 *buf, size_t len, u8 *mic)
 {
-	u8 hash[SHA256_MAC_LEN];
+	u8 hash[SHA384_MAC_LEN];
 
 	switch (ver) {
 #ifndef CONFIG_FIPS
 	case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
-		return hmac_md5(key, 16, buf, len, mic);
+		return hmac_md5(key, key_len, buf, len, mic);
 #endif /* CONFIG_FIPS */
 	case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
-		if (hmac_sha1(key, 16, buf, len, hash))
+		if (hmac_sha1(key, key_len, buf, len, hash))
 			return -1;
 		os_memcpy(mic, hash, MD5_MAC_LEN);
 		break;
@@ -65,11 +91,18 @@
 #endif /* CONFIG_HS20 */
 #ifdef CONFIG_SUITEB
 		case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
-			if (hmac_sha256(key, 16, buf, len, hash))
+			if (hmac_sha256(key, key_len, buf, len, hash))
 				return -1;
 			os_memcpy(mic, hash, MD5_MAC_LEN);
 			break;
 #endif /* CONFIG_SUITEB */
+#ifdef CONFIG_SUITEB192
+		case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
+			if (hmac_sha384(key, key_len, buf, len, hash))
+				return -1;
+			os_memcpy(mic, hash, 24);
+			break;
+#endif /* CONFIG_SUITEB192 */
 		default:
 			return -1;
 		}
@@ -92,8 +125,9 @@
  * @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
+ * @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",
@@ -104,12 +138,14 @@
  *             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)
+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);
@@ -129,27 +165,44 @@
 			  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 (use_sha256)
+	if (wpa_key_mgmt_sha256(akmp))
 		sha256_prf(pmk, pmk_len, label, data, sizeof(data),
-			   ptk, ptk_len);
+			   tmp, ptk_len);
 	else
 #endif /* CONFIG_IEEE80211W */
-		sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk,
-			 ptk_len);
+		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", ptk, ptk_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;
 }
 
 
 #ifdef CONFIG_IEEE80211R
-int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr,
-	       u8 transaction_seqnum, const u8 *mdie, size_t mdie_len,
+int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
+	       const u8 *ap_addr, u8 transaction_seqnum,
+	       const u8 *mdie, size_t mdie_len,
 	       const u8 *ftie, size_t ftie_len,
 	       const u8 *rsnie, size_t rsnie_len,
 	       const u8 *ric, size_t ric_len, u8 *mic)
@@ -157,6 +210,12 @@
 	u8 *buf, *pos;
 	size_t buf_len;
 
+	if (kck_len != 16) {
+		wpa_printf(MSG_WARNING, "FT: Unsupported KCK length %u",
+			   (unsigned int) kck_len);
+		return -1;
+	}
+
 	buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len;
 	buf = os_malloc(buf_len);
 	if (buf == NULL)
@@ -413,6 +472,8 @@
 #endif /* CONFIG_SAE */
 	if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B)
 		return WPA_KEY_MGMT_IEEE8021X_SUITE_B;
+	if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192)
+		return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
 	return 0;
 }
 
@@ -858,15 +919,17 @@
  *
  * 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)
+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 ||
@@ -882,7 +945,12 @@
 	os_memcpy(pos, sta_addr, ETH_ALEN);
 	pos += ETH_ALEN;
 
-	sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_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;
+
+	sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, tmp, ptk_len);
 
 	/*
 	 * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
@@ -903,6 +971,19 @@
 
 	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;
 }
 
 #endif /* CONFIG_IEEE80211R */
@@ -975,6 +1056,39 @@
 #endif /* CONFIG_SUITEB */
 
 
+#ifdef CONFIG_SUITEB192
+/**
+ * rsn_pmkid_suite_b_192 - Calculate PMK identifier for Suite B AKM
+ * @kck: Key confirmation key
+ * @kck_len: Length of kck in bytes
+ * @aa: Authenticator address
+ * @spa: Supplicant address
+ * @pmkid: Buffer for PMKID
+ * Returns: 0 on success, -1 on failure
+ *
+ * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
+ * PMKID = Truncate(HMAC-SHA-384(KCK, "PMK Name" || AA || SPA))
+ */
+int rsn_pmkid_suite_b_192(const u8 *kck, size_t kck_len, const u8 *aa,
+			  const u8 *spa, u8 *pmkid)
+{
+	char *title = "PMK Name";
+	const u8 *addr[3];
+	const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
+	unsigned char hash[SHA384_MAC_LEN];
+
+	addr[0] = (u8 *) title;
+	addr[1] = aa;
+	addr[2] = spa;
+
+	if (hmac_sha384_vector(kck, kck_len, 3, addr, len, hash) < 0)
+		return -1;
+	os_memcpy(pmkid, hash, PMKID_LEN);
+	return 0;
+}
+#endif /* CONFIG_SUITEB192 */
+
+
 /**
  * wpa_cipher_txt - Convert cipher suite to a text string
  * @cipher: Cipher suite (WPA_CIPHER_* enum)
@@ -1054,6 +1168,8 @@
 		return "OSEN";
 	case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
 		return "WPA2-EAP-SUITE-B";
+	case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
+		return "WPA2-EAP-SUITE-B-192";
 	default:
 		return "UNKNOWN";
 	}
@@ -1082,6 +1198,8 @@
 		return WLAN_AKM_SUITE_OSEN;
 	if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
 		return WLAN_AKM_SUITE_8021X_SUITE_B;
+	if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
+		return WLAN_AKM_SUITE_8021X_SUITE_B_192;
 	return 0;
 }