Home | History | Annotate | Line # | Download | only in rsn_supp
      1 /*
      2  * wpa_supplicant - WPA/RSN IE and KDE processing
      3  * Copyright (c) 2003-2018, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "includes.h"
     10 
     11 #include "common.h"
     12 #include "wpa.h"
     13 #include "pmksa_cache.h"
     14 #include "common/ieee802_11_defs.h"
     15 #include "wpa_i.h"
     16 #include "wpa_ie.h"
     17 
     18 
     19 /**
     20  * wpa_parse_wpa_ie - Parse WPA/RSN IE
     21  * @wpa_ie: Pointer to WPA or RSN IE
     22  * @wpa_ie_len: Length of the WPA/RSN IE
     23  * @data: Pointer to data area for parsing results
     24  * Returns: 0 on success, -1 on failure
     25  *
     26  * Parse the contents of WPA or RSN IE and write the parsed data into data.
     27  */
     28 int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
     29 		     struct wpa_ie_data *data)
     30 {
     31 	if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN)
     32 		return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
     33 	if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
     34 	    wpa_ie[1] >= 4 && WPA_GET_BE32(&wpa_ie[2]) == OSEN_IE_VENDOR_TYPE)
     35 		return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
     36 	else
     37 		return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
     38 }
     39 
     40 
     41 static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len,
     42 			      int pairwise_cipher, int group_cipher,
     43 			      int key_mgmt)
     44 {
     45 	u8 *pos;
     46 	struct wpa_ie_hdr *hdr;
     47 	u32 suite;
     48 
     49 	if (wpa_ie_len < sizeof(*hdr) + WPA_SELECTOR_LEN +
     50 	    2 + WPA_SELECTOR_LEN + 2 + WPA_SELECTOR_LEN)
     51 		return -1;
     52 
     53 	hdr = (struct wpa_ie_hdr *) wpa_ie;
     54 	hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC;
     55 	RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE);
     56 	WPA_PUT_LE16(hdr->version, WPA_VERSION);
     57 	pos = (u8 *) (hdr + 1);
     58 
     59 	suite = wpa_cipher_to_suite(WPA_PROTO_WPA, group_cipher);
     60 	if (suite == 0) {
     61 		wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
     62 			   group_cipher);
     63 		return -1;
     64 	}
     65 	RSN_SELECTOR_PUT(pos, suite);
     66 	pos += WPA_SELECTOR_LEN;
     67 
     68 	*pos++ = 1;
     69 	*pos++ = 0;
     70 	suite = wpa_cipher_to_suite(WPA_PROTO_WPA, pairwise_cipher);
     71 	if (suite == 0 ||
     72 	    (!wpa_cipher_valid_pairwise(pairwise_cipher) &&
     73 	     pairwise_cipher != WPA_CIPHER_NONE)) {
     74 		wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
     75 			   pairwise_cipher);
     76 		return -1;
     77 	}
     78 	RSN_SELECTOR_PUT(pos, suite);
     79 	pos += WPA_SELECTOR_LEN;
     80 
     81 	*pos++ = 1;
     82 	*pos++ = 0;
     83 	if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
     84 		RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
     85 	} else if (key_mgmt == WPA_KEY_MGMT_PSK) {
     86 		RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
     87 	} else if (key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
     88 		RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_NONE);
     89 	} else if (key_mgmt == WPA_KEY_MGMT_CCKM) {
     90 		RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_CCKM);
     91 	} else {
     92 		wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
     93 			   key_mgmt);
     94 		return -1;
     95 	}
     96 	pos += WPA_SELECTOR_LEN;
     97 
     98 	/* WPA Capabilities; use defaults, so no need to include it */
     99 
    100 	hdr->len = (pos - wpa_ie) - 2;
    101 
    102 	WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len);
    103 
    104 	return pos - wpa_ie;
    105 }
    106 
    107 
    108 u16 rsn_supp_capab(struct wpa_sm *sm)
    109 {
    110 	u16 capab = 0;
    111 
    112 	if (sm->wmm_enabled) {
    113 		/* Advertise 16 PTKSA replay counters when using WMM */
    114 		capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
    115 	}
    116 	if (sm->mfp)
    117 		capab |= WPA_CAPABILITY_MFPC;
    118 	if (sm->mfp == 2)
    119 		capab |= WPA_CAPABILITY_MFPR;
    120 	if (sm->ocv)
    121 		capab |= WPA_CAPABILITY_OCVC;
    122 	if (sm->ext_key_id)
    123 		capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST;
    124 
    125 	return capab;
    126 }
    127 
    128 
    129 static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
    130 			      int pairwise_cipher, int group_cipher,
    131 			      int key_mgmt, int mgmt_group_cipher,
    132 			      struct wpa_sm *sm)
    133 {
    134 	u8 *pos;
    135 	struct rsn_ie_hdr *hdr;
    136 	u32 suite;
    137 
    138 	if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN +
    139 	    2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 +
    140 	    (sm->cur_pmksa ? 2 + PMKID_LEN : 0)) {
    141 		wpa_printf(MSG_DEBUG, "RSN: Too short IE buffer (%lu bytes)",
    142 			   (unsigned long) rsn_ie_len);
    143 		return -1;
    144 	}
    145 
    146 	hdr = (struct rsn_ie_hdr *) rsn_ie;
    147 	hdr->elem_id = WLAN_EID_RSN;
    148 	WPA_PUT_LE16(hdr->version, RSN_VERSION);
    149 	pos = (u8 *) (hdr + 1);
    150 
    151 	suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group_cipher);
    152 	if (suite == 0) {
    153 		wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
    154 			   group_cipher);
    155 		return -1;
    156 	}
    157 	RSN_SELECTOR_PUT(pos, suite);
    158 	pos += RSN_SELECTOR_LEN;
    159 
    160 	*pos++ = 1;
    161 	*pos++ = 0;
    162 	suite = wpa_cipher_to_suite(WPA_PROTO_RSN, pairwise_cipher);
    163 	if (suite == 0 ||
    164 	    (!wpa_cipher_valid_pairwise(pairwise_cipher) &&
    165 	     pairwise_cipher != WPA_CIPHER_NONE)) {
    166 		wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
    167 			   pairwise_cipher);
    168 		return -1;
    169 	}
    170 	RSN_SELECTOR_PUT(pos, suite);
    171 	pos += RSN_SELECTOR_LEN;
    172 
    173 	*pos++ = 1;
    174 	*pos++ = 0;
    175 	if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
    176 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
    177 	} else if (key_mgmt == WPA_KEY_MGMT_PSK) {
    178 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
    179 	} else if (key_mgmt == WPA_KEY_MGMT_CCKM) {
    180 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_CCKM);
    181 #ifdef CONFIG_IEEE80211R
    182 	} else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) {
    183 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
    184 #ifdef CONFIG_SHA384
    185 	} else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
    186 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384);
    187 #endif /* CONFIG_SHA384 */
    188 	} else if (key_mgmt == WPA_KEY_MGMT_FT_PSK) {
    189 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
    190 #endif /* CONFIG_IEEE80211R */
    191 	} else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA256) {
    192 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
    193 	} else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) {
    194 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
    195 #ifdef CONFIG_SAE
    196 	} else if (key_mgmt == WPA_KEY_MGMT_SAE) {
    197 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
    198 	} else if (key_mgmt == WPA_KEY_MGMT_SAE_EXT_KEY) {
    199 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE_EXT_KEY);
    200 	} else if (key_mgmt == WPA_KEY_MGMT_FT_SAE) {
    201 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
    202 	} else if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
    203 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY);
    204 #endif /* CONFIG_SAE */
    205 	} else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
    206 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
    207 	} else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
    208 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B);
    209 #ifdef CONFIG_FILS
    210 	} else if (key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
    211 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA256);
    212 	} else if (key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
    213 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA384);
    214 #ifdef CONFIG_IEEE80211R
    215 	} else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
    216 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256);
    217 	} else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
    218 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384);
    219 #endif /* CONFIG_IEEE80211R */
    220 #endif /* CONFIG_FILS */
    221 #ifdef CONFIG_OWE
    222 	} else if (key_mgmt & WPA_KEY_MGMT_OWE) {
    223 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE);
    224 #endif /* CONFIG_OWE */
    225 #ifdef CONFIG_DPP
    226 	} else if (key_mgmt & WPA_KEY_MGMT_DPP) {
    227 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_DPP);
    228 #endif /* CONFIG_DPP */
    229 #ifdef CONFIG_HS20
    230 	} else if (key_mgmt & WPA_KEY_MGMT_OSEN) {
    231 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN);
    232 #endif /* CONFIG_HS20 */
    233 #ifdef CONFIG_SHA384
    234 	} else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA384) {
    235 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA384);
    236 #endif /* CONFIG_SHA384 */
    237 	} else {
    238 		wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
    239 			   key_mgmt);
    240 		return -1;
    241 	}
    242 	pos += RSN_SELECTOR_LEN;
    243 
    244 	/* RSN Capabilities */
    245 	WPA_PUT_LE16(pos, rsn_supp_capab(sm));
    246 	pos += 2;
    247 
    248 	if (sm->cur_pmksa) {
    249 		/* PMKID Count (2 octets, little endian) */
    250 		*pos++ = 1;
    251 		*pos++ = 0;
    252 		/* PMKID */
    253 		os_memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN);
    254 		pos += PMKID_LEN;
    255 	}
    256 
    257 	if (wpa_cipher_valid_mgmt_group(mgmt_group_cipher)) {
    258 		if (!sm->cur_pmksa) {
    259 			/* PMKID Count */
    260 			WPA_PUT_LE16(pos, 0);
    261 			pos += 2;
    262 		}
    263 
    264 		/* Management Group Cipher Suite */
    265 		RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
    266 							  mgmt_group_cipher));
    267 		pos += RSN_SELECTOR_LEN;
    268 	}
    269 
    270 	hdr->len = (pos - rsn_ie) - 2;
    271 
    272 	WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len);
    273 
    274 	return pos - rsn_ie;
    275 }
    276 
    277 
    278 #ifdef CONFIG_HS20
    279 static int wpa_gen_wpa_ie_osen(u8 *wpa_ie, size_t wpa_ie_len,
    280 			       int pairwise_cipher, int group_cipher,
    281 			       int key_mgmt)
    282 {
    283 	u8 *pos, *len;
    284 	u32 suite;
    285 
    286 	if (wpa_ie_len < 2 + 4 + RSN_SELECTOR_LEN +
    287 	    2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN)
    288 		return -1;
    289 
    290 	pos = wpa_ie;
    291 	*pos++ = WLAN_EID_VENDOR_SPECIFIC;
    292 	len = pos++; /* to be filled */
    293 	WPA_PUT_BE24(pos, OUI_WFA);
    294 	pos += 3;
    295 	*pos++ = HS20_OSEN_OUI_TYPE;
    296 
    297 	/* Group Data Cipher Suite */
    298 	suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group_cipher);
    299 	if (suite == 0) {
    300 		wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
    301 			   group_cipher);
    302 		return -1;
    303 	}
    304 	RSN_SELECTOR_PUT(pos, suite);
    305 	pos += RSN_SELECTOR_LEN;
    306 
    307 	/* Pairwise Cipher Suite Count and List */
    308 	WPA_PUT_LE16(pos, 1);
    309 	pos += 2;
    310 	suite = wpa_cipher_to_suite(WPA_PROTO_RSN, pairwise_cipher);
    311 	if (suite == 0 ||
    312 	    (!wpa_cipher_valid_pairwise(pairwise_cipher) &&
    313 	     pairwise_cipher != WPA_CIPHER_NONE)) {
    314 		wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
    315 			   pairwise_cipher);
    316 		return -1;
    317 	}
    318 	RSN_SELECTOR_PUT(pos, suite);
    319 	pos += RSN_SELECTOR_LEN;
    320 
    321 	/* AKM Suite Count and List */
    322 	WPA_PUT_LE16(pos, 1);
    323 	pos += 2;
    324 	RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN);
    325 	pos += RSN_SELECTOR_LEN;
    326 
    327 	*len = pos - len - 1;
    328 
    329 	WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len);
    330 
    331 	return pos - wpa_ie;
    332 }
    333 #endif /* CONFIG_HS20 */
    334 
    335 
    336 /**
    337  * wpa_gen_wpa_ie - Generate WPA/RSN IE based on current security policy
    338  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    339  * @wpa_ie: Pointer to memory area for the generated WPA/RSN IE
    340  * @wpa_ie_len: Maximum length of the generated WPA/RSN IE
    341  * Returns: Length of the generated WPA/RSN IE or -1 on failure
    342  */
    343 int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len)
    344 {
    345 	if (sm->proto == WPA_PROTO_RSN)
    346 		return wpa_gen_wpa_ie_rsn(wpa_ie, wpa_ie_len,
    347 					  sm->pairwise_cipher,
    348 					  sm->group_cipher,
    349 					  sm->key_mgmt, sm->mgmt_group_cipher,
    350 					  sm);
    351 #ifdef CONFIG_HS20
    352 	else if (sm->proto == WPA_PROTO_OSEN)
    353 		return wpa_gen_wpa_ie_osen(wpa_ie, wpa_ie_len,
    354 					   sm->pairwise_cipher,
    355 					   sm->group_cipher,
    356 					   sm->key_mgmt);
    357 #endif /* CONFIG_HS20 */
    358 	else
    359 		return wpa_gen_wpa_ie_wpa(wpa_ie, wpa_ie_len,
    360 					  sm->pairwise_cipher,
    361 					  sm->group_cipher,
    362 					  sm->key_mgmt);
    363 }
    364 
    365 
    366 int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len)
    367 {
    368 	u8 *pos = rsnxe;
    369 	u32 capab = 0, tmp;
    370 	size_t flen;
    371 
    372 	if (wpa_key_mgmt_sae(sm->key_mgmt) &&
    373 	    (sm->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
    374 	     sm->sae_pwe == SAE_PWE_BOTH || sm->sae_pk)) {
    375 		capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
    376 #ifdef CONFIG_SAE_PK
    377 		if (sm->sae_pk)
    378 			capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
    379 #endif /* CONFIG_SAE_PK */
    380 	}
    381 
    382 	if (sm->secure_ltf)
    383 		capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
    384 	if (sm->secure_rtt)
    385 		capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
    386 	if (sm->prot_range_neg)
    387 		capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
    388 	if (sm->ssid_protection)
    389 		capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
    390 
    391 	if (!capab)
    392 		return 0; /* no supported extended RSN capabilities */
    393 	tmp = capab;
    394 	flen = 0;
    395 	while (tmp) {
    396 		flen++;
    397 		tmp >>= 8;
    398 	}
    399 	if (rsnxe_len < 2 + flen)
    400 		return -1;
    401 	capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
    402 
    403 	*pos++ = WLAN_EID_RSNX;
    404 	*pos++ = flen;
    405 	while (capab) {
    406 		*pos++ = capab & 0xff;
    407 		capab >>= 8;
    408 	}
    409 
    410 	return pos - rsnxe;
    411 }
    412