This change breaks interoperability with older wpa_supplicant versions
(everything up to and including wpa_supplicant 0.5.10 and 0.6.5) which
incorrectly used this field as number of bytes, not bits, in RES.
break;
case EAP_SIM_AT_RES:
wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RES");
break;
case EAP_SIM_AT_RES:
wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RES");
+ attr->res_len_bits = WPA_GET_BE16(apos);
apos += 2;
alen -= 2;
if (!aka || alen < EAP_AKA_MIN_RES_LEN ||
apos += 2;
alen -= 2;
if (!aka || alen < EAP_AKA_MIN_RES_LEN ||
const u8 *checkcode;
size_t num_chal, version_list_len, encr_data_len;
size_t next_pseudonym_len, next_reauth_id_len, identity_len, res_len;
const u8 *checkcode;
size_t num_chal, version_list_len, encr_data_len;
size_t next_pseudonym_len, next_reauth_id_len, identity_len, res_len;
size_t checkcode_len;
enum eap_sim_id_req id_req;
int notification, counter, selected_version, client_error_code;
size_t checkcode_len;
enum eap_sim_id_req id_req;
int notification, counter, selected_version, client_error_code;
- if (attr->res == NULL || attr->res_len != data->res_len ||
+ /*
+ * AT_RES is padded, so verify that there is enough room for RES and
+ * that the RES length in bits matches with the expected RES.
+ */
+ if (attr->res == NULL || attr->res_len < data->res_len ||
+ attr->res_len_bits != data->res_len * 8 ||
os_memcmp(attr->res, data->res, data->res_len) != 0) {
wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not "
os_memcmp(attr->res, data->res, data->res_len) != 0) {
wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not "
- "include valid AT_RES");
+ "include valid AT_RES (attr len=%lu, res len=%lu "
+ "bits, expected %lu bits)",
+ (unsigned long) attr->res_len,
+ (unsigned long) attr->res_len_bits,
+ (unsigned long) data->res_len);
data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
eap_aka_state(data, NOTIFICATION);
return;
data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
eap_aka_state(data, NOTIFICATION);
return;