WNM: Fix GTK/IGTK encoding in WNM-Sleep Mode Exit frame
These subelements do not use AES key wrap (MFP is used instead). Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
		
							parent
							
								
									5d247692f6
								
							
						
					
					
						commit
						835822d404
					
				
					 1 changed files with 33 additions and 79 deletions
				
			
		|  | @ -2444,108 +2444,62 @@ void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag) | |||
| 
 | ||||
| int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos) | ||||
| { | ||||
| 	u8 *subelem; | ||||
| 	struct wpa_group *gsm = sm->group; | ||||
| 	size_t subelem_len, pad_len; | ||||
| 	const u8 *key; | ||||
| 	size_t key_len; | ||||
| 	u8 keybuf[32]; | ||||
| 
 | ||||
| 	/* GTK subslement */ | ||||
| 	key_len = gsm->GTK_len; | ||||
| 	if (key_len > sizeof(keybuf)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Pad key for AES Key Wrap if it is not multiple of 8 bytes or is less | ||||
| 	 * than 16 bytes. | ||||
| 	 */ | ||||
| 	pad_len = key_len % 8; | ||||
| 	if (pad_len) | ||||
| 		pad_len = 8 - pad_len; | ||||
| 	if (key_len + pad_len < 16) | ||||
| 		pad_len += 8; | ||||
| 	if (pad_len) { | ||||
| 		os_memcpy(keybuf, gsm->GTK[gsm->GN - 1], key_len); | ||||
| 		os_memset(keybuf + key_len, 0, pad_len); | ||||
| 		keybuf[key_len] = 0xdd; | ||||
| 		key_len += pad_len; | ||||
| 		key = keybuf; | ||||
| 	} else | ||||
| 		key = gsm->GTK[gsm->GN - 1]; | ||||
| 	u8 *start = pos; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * GTK subelement: | ||||
| 	 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] | | ||||
| 	 * Key[5..32] | 8 padding. | ||||
| 	 * Key[5..32] | ||||
| 	 */ | ||||
| 	subelem_len = 13 + key_len + 8; | ||||
| 	subelem = os_zalloc(subelem_len); | ||||
| 	if (subelem == NULL) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	subelem[0] = WNM_SLEEP_SUBELEM_GTK; | ||||
| 	subelem[1] = 11 + key_len + 8; | ||||
| 	*pos++ = WNM_SLEEP_SUBELEM_GTK; | ||||
| 	*pos++ = 11 + gsm->GTK_len; | ||||
| 	/* Key ID in B0-B1 of Key Info */ | ||||
| 	WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03); | ||||
| 	subelem[4] = gsm->GTK_len; | ||||
| 	if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5) != 0) | ||||
| 	{ | ||||
| 		os_free(subelem); | ||||
| 	WPA_PUT_LE16(pos, gsm->GN & 0x03); | ||||
| 	pos += 2; | ||||
| 	*pos++ = gsm->GTK_len; | ||||
| 	if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0) | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 13)) { | ||||
| 		os_free(subelem); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	pos += 8; | ||||
| 	os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len); | ||||
| 	pos += gsm->GTK_len; | ||||
| 
 | ||||
| 	os_memcpy(pos, subelem, subelem_len); | ||||
| 
 | ||||
| 	wpa_hexdump_key(MSG_DEBUG, "Plaintext GTK", | ||||
| 	wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit", | ||||
| 		   gsm->GN); | ||||
| 	wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit", | ||||
| 			gsm->GTK[gsm->GN - 1], gsm->GTK_len); | ||||
| 	os_free(subelem); | ||||
| 
 | ||||
| 	return subelem_len; | ||||
| 	return pos - start; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifdef CONFIG_IEEE80211W | ||||
| int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) | ||||
| { | ||||
| 	u8 *subelem, *ptr; | ||||
| 	struct wpa_group *gsm = sm->group; | ||||
| 	size_t subelem_len; | ||||
| 	u8 *start = pos; | ||||
| 
 | ||||
| 	/* IGTK subelement
 | ||||
| 	 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | | ||||
| 	 * Key[16] | 8 padding */ | ||||
| 	subelem_len = 1 + 1 + 2 + 6 + WPA_IGTK_LEN + 8; | ||||
| 	subelem = os_zalloc(subelem_len); | ||||
| 	if (subelem == NULL) | ||||
| 	/*
 | ||||
| 	 * IGTK subelement: | ||||
| 	 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16] | ||||
| 	 */ | ||||
| 	*pos++ = WNM_SLEEP_SUBELEM_IGTK; | ||||
| 	*pos++ = 2 + 6 + WPA_IGTK_LEN; | ||||
| 	WPA_PUT_LE16(pos, gsm->GN_igtk); | ||||
| 	pos += 2; | ||||
| 	if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0) | ||||
| 		return 0; | ||||
| 	pos += 6; | ||||
| 
 | ||||
| 	ptr = subelem; | ||||
| 	*ptr++ = WNM_SLEEP_SUBELEM_IGTK; | ||||
| 	*ptr++ = subelem_len - 2; | ||||
| 	WPA_PUT_LE16(ptr, gsm->GN_igtk); | ||||
| 	ptr += 2; | ||||
| 	if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, ptr) != 0) { | ||||
| 		os_free(subelem); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	ptr += 6; | ||||
| 	if (aes_wrap(sm->PTK.kek, WPA_IGTK_LEN / 8, | ||||
| 		     gsm->IGTK[gsm->GN_igtk - 4], ptr)) { | ||||
| 		os_free(subelem); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); | ||||
| 	pos += WPA_IGTK_LEN; | ||||
| 
 | ||||
| 	os_memcpy(pos, subelem, subelem_len); | ||||
| 
 | ||||
| 	wpa_hexdump_key(MSG_DEBUG, "Plaintext IGTK", | ||||
| 	wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit", | ||||
| 		   gsm->GN_igtk); | ||||
| 	wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit", | ||||
| 			gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); | ||||
| 	os_free(subelem); | ||||
| 
 | ||||
| 	return subelem_len; | ||||
| 	return pos - start; | ||||
| } | ||||
| #endif /* CONFIG_IEEE80211W */ | ||||
| #endif /* CONFIG_WNM */ | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Jouni Malinen
						Jouni Malinen