PASN: Encode the public key properly

When a public key is included in the PASN Parameters element, it should
be encoded using the RFC 5480 conventions, and thus the first octet of
the Ephemeral Public Key field should indicate whether the public key is
compressed and the actual key part starts from the second octet.

Fix the implementation to properly adhere to the convention
requirements for both wpa_supplicant and hostapd.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
master
Ilan Peer 3 years ago committed by Jouni Malinen
parent cd0813763a
commit 2efa60344e

@ -2937,7 +2937,7 @@ static int handle_auth_pasn_resp(struct hostapd_data *hapd,
wpa_pasn_add_parameter_ie(buf, sta->pasn->group,
sta->pasn->wrapped_data_format,
pubkey, NULL, 0);
pubkey, true, NULL, 0);
if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
goto fail;
@ -3034,7 +3034,7 @@ static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta,
const int *groups = hapd->conf->pasn_groups;
static const int default_groups[] = { 19, 0 };
u16 status = WLAN_STATUS_SUCCESS;
int ret;
int ret, inc_y;
bool derive_keys;
u32 i;
@ -3118,9 +3118,22 @@ static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta,
sta->pasn->group = pasn_params.group;
secret = crypto_ecdh_set_peerkey(sta->pasn->ecdh, 0,
pasn_params.pubkey,
pasn_params.pubkey_len);
if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_UNCOMPRESSED) {
inc_y = 1;
} else if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_0 ||
pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_1) {
inc_y = 0;
} else {
wpa_printf(MSG_DEBUG,
"PASN: Invalid first octet in pubkey=0x%x",
pasn_params.pubkey[0]);
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
goto send_resp;
}
secret = crypto_ecdh_set_peerkey(sta->pasn->ecdh, inc_y,
pasn_params.pubkey + 1,
pasn_params.pubkey_len - 1);
if (!secret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to derive shared secret");
status = WLAN_STATUS_UNSPECIFIED_FAILURE;

@ -3419,13 +3419,16 @@ int wpa_pasn_add_rsne(struct wpabuf *buf, const u8 *pmkid, int akmp, int cipher)
* @pasn_group: Finite Cyclic Group ID for PASN authentication
* @wrapped_data_format: Format of the data in the Wrapped Data IE
* @pubkey: A buffer holding the local public key. Can be NULL
* @compressed: In case pubkey is included, indicates if the public key is
* compressed (only x coordinate is included) or not (both x and y
* coordinates are included)
* @comeback: A buffer holding the comeback token. Can be NULL
* @after: If comeback is set, defined the comeback time in seconds. -1 to not
* include the Comeback After field (frames from non-AP STA).
*/
void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group,
u8 wrapped_data_format,
struct wpabuf *pubkey,
struct wpabuf *pubkey, bool compressed,
struct wpabuf *comeback, int after)
{
struct pasn_parameter_ie *params;
@ -3465,13 +3468,22 @@ void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group,
/*
* 2 octets for the finite cyclic group + 2 octets public key
* length + the actual key
* length + 1 octet for the compressed/uncompressed indication +
* the actual key.
*/
params->len += 2 + 1 + wpabuf_len(pubkey);
params->len += 2 + 1 + 1 + wpabuf_len(pubkey);
params->control |= WPA_PASN_CTRL_GROUP_AND_KEY_PRESENT;
wpabuf_put_le16(buf, pasn_group);
wpabuf_put_u8(buf, wpabuf_len(pubkey));
/*
* The first octet indicates whether the public key is
* compressed, as defined in RFC 5480 section 2.2.
*/
wpabuf_put_u8(buf, wpabuf_len(pubkey) + 1);
wpabuf_put_u8(buf, compressed ? WPA_PASN_PUBKEY_COMPRESSED_0 :
WPA_PASN_PUBKEY_UNCOMPRESSED);
wpabuf_put_buf(buf, pubkey);
}
}

@ -546,6 +546,11 @@ struct wpa_pasn_params_data {
const u8 *pubkey;
};
/* See RFC 5480 section 2.2 */
#define WPA_PASN_PUBKEY_COMPRESSED_0 0x02
#define WPA_PASN_PUBKEY_COMPRESSED_1 0x03
#define WPA_PASN_PUBKEY_UNCOMPRESSED 0x04
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
int use_sha384);
@ -657,7 +662,7 @@ int wpa_pasn_add_rsne(struct wpabuf *buf, const u8 *pmkid,
void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group,
u8 wrapped_data_format,
struct wpabuf *pubkey,
struct wpabuf *pubkey, bool compressed,
struct wpabuf *comeback, int after);
int wpa_pasn_add_wrapped_data(struct wpabuf *buf,

@ -680,7 +680,7 @@ static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s)
wrapped_data = WPA_PASN_WRAPPED_DATA_NO;
wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data,
pubkey, NULL, -1);
pubkey, true, NULL, -1);
if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
goto fail;
@ -753,7 +753,7 @@ static struct wpabuf * wpas_pasn_build_auth_3(struct wpa_supplicant *wpa_s)
wrapped_data = WPA_PASN_WRAPPED_DATA_NO;
wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data,
NULL, NULL, -1);
NULL, false, NULL, -1);
if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
goto fail;
@ -1226,7 +1226,7 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
u8 mic[WPA_PASN_MAX_MIC_LEN], out_mic[WPA_PASN_MAX_MIC_LEN];
u8 mic_len;
u16 status;
int ret;
int ret, inc_y;
u16 fc = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
(WLAN_FC_STYPE_AUTH << 4));
@ -1344,9 +1344,21 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
goto fail;
}
secret = crypto_ecdh_set_peerkey(pasn->ecdh, 0,
pasn_params.pubkey,
pasn_params.pubkey_len);
if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_UNCOMPRESSED) {
inc_y = 1;
} else if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_0 ||
pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_1) {
inc_y = 0;
} else {
wpa_printf(MSG_DEBUG,
"PASN: Invalid first octet in pubkey=0x%x",
pasn_params.pubkey[0]);
goto fail;
}
secret = crypto_ecdh_set_peerkey(pasn->ecdh, inc_y,
pasn_params.pubkey + 1,
pasn_params.pubkey_len - 1);
if (!secret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to derive shared secret");

Loading…
Cancel
Save