Added protection against EAP-AKA' -> EAP-AKA bidding down attacks
AT_BIDDING attribute is included in EAP-AKA/Challenge to allow peer to know whether the server would have preferred EAP-AKA'.
This commit is contained in:
parent
8de5048e26
commit
01b0569437
6 changed files with 59 additions and 1 deletions
|
@ -903,6 +903,16 @@ int eap_sim_parse_attr(const u8 *start, const u8 *end,
|
||||||
attr->kdf[attr->kdf_count] = WPA_GET_BE16(apos);
|
attr->kdf[attr->kdf_count] = WPA_GET_BE16(apos);
|
||||||
attr->kdf_count++;
|
attr->kdf_count++;
|
||||||
break;
|
break;
|
||||||
|
case EAP_SIM_AT_BIDDING:
|
||||||
|
wpa_printf(MSG_DEBUG, "EAP-AKA: AT_BIDDING");
|
||||||
|
if (alen != 2) {
|
||||||
|
wpa_printf(MSG_INFO, "EAP-AKA: Invalid "
|
||||||
|
"AT_BIDDING (len %lu)",
|
||||||
|
(unsigned long) alen);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
attr->bidding = apos;
|
||||||
|
break;
|
||||||
#endif /* EAP_AKA_PRIME */
|
#endif /* EAP_AKA_PRIME */
|
||||||
default:
|
default:
|
||||||
if (pos[0] < 128) {
|
if (pos[0] < 128) {
|
||||||
|
|
|
@ -138,6 +138,7 @@ void eap_aka_prime_derive_ck_ik_prime(u8 *ck, u8 *ik, const u8 *sqn_ak,
|
||||||
#define EAP_SIM_AT_NEXT_REAUTH_ID 133 /* only encrypted */
|
#define EAP_SIM_AT_NEXT_REAUTH_ID 133 /* only encrypted */
|
||||||
#define EAP_SIM_AT_CHECKCODE 134 /* only AKA */
|
#define EAP_SIM_AT_CHECKCODE 134 /* only AKA */
|
||||||
#define EAP_SIM_AT_RESULT_IND 135
|
#define EAP_SIM_AT_RESULT_IND 135
|
||||||
|
#define EAP_SIM_AT_BIDDING 136
|
||||||
|
|
||||||
/* AT_NOTIFICATION notification code values */
|
/* AT_NOTIFICATION notification code values */
|
||||||
#define EAP_SIM_GENERAL_FAILURE_AFTER_AUTH 0
|
#define EAP_SIM_GENERAL_FAILURE_AFTER_AUTH 0
|
||||||
|
@ -149,6 +150,10 @@ void eap_aka_prime_derive_ck_ik_prime(u8 *ck, u8 *ik, const u8 *sqn_ak,
|
||||||
/* EAP-AKA' AT_KDF Key Derivation Function values */
|
/* EAP-AKA' AT_KDF Key Derivation Function values */
|
||||||
#define EAP_AKA_PRIME_KDF 1
|
#define EAP_AKA_PRIME_KDF 1
|
||||||
|
|
||||||
|
/* AT_BIDDING flags */
|
||||||
|
#define EAP_AKA_BIDDING_FLAG_D 0x8000
|
||||||
|
|
||||||
|
|
||||||
enum eap_sim_id_req {
|
enum eap_sim_id_req {
|
||||||
NO_ID_REQ, ANY_ID, FULLAUTH_ID, PERMANENT_ID
|
NO_ID_REQ, ANY_ID, FULLAUTH_ID, PERMANENT_ID
|
||||||
};
|
};
|
||||||
|
@ -160,6 +165,7 @@ struct eap_sim_attrs {
|
||||||
const u8 *nonce_mt, *identity, *res, *auts;
|
const u8 *nonce_mt, *identity, *res, *auts;
|
||||||
const u8 *checkcode;
|
const u8 *checkcode;
|
||||||
const u8 *kdf_input;
|
const u8 *kdf_input;
|
||||||
|
const u8 *bidding;
|
||||||
size_t num_chal, version_list_len, encr_data_len;
|
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 next_pseudonym_len, next_reauth_id_len, identity_len, res_len;
|
||||||
size_t res_len_bits;
|
size_t res_len_bits;
|
||||||
|
|
|
@ -106,7 +106,7 @@ static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
|
||||||
* @method: EAP type
|
* @method: EAP type
|
||||||
* Returns: 1 = allowed EAP method, 0 = not allowed
|
* Returns: 1 = allowed EAP method, 0 = not allowed
|
||||||
*/
|
*/
|
||||||
static int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
|
int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
|
||||||
{
|
{
|
||||||
struct eap_peer_config *config = eap_get_config(sm);
|
struct eap_peer_config *config = eap_get_config(sm);
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -791,6 +791,18 @@ static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm,
|
||||||
data->kdf = EAP_AKA_PRIME_KDF;
|
data->kdf = EAP_AKA_PRIME_KDF;
|
||||||
wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf);
|
wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->eap_method == EAP_TYPE_AKA && attr->bidding) {
|
||||||
|
u16 flags = WPA_GET_BE16(attr->bidding);
|
||||||
|
if ((flags & EAP_AKA_BIDDING_FLAG_D) &&
|
||||||
|
eap_allowed_method(sm, EAP_VENDOR_IETF,
|
||||||
|
EAP_TYPE_AKA_PRIME)) {
|
||||||
|
wpa_printf(MSG_WARNING, "EAP-AKA: Bidding down from "
|
||||||
|
"AKA' to AKA detected");
|
||||||
|
/* Fail authentication as if AUTN had been incorrect */
|
||||||
|
return eap_aka_authentication_reject(data, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif /* EAP_AKA_PRIME */
|
#endif /* EAP_AKA_PRIME */
|
||||||
|
|
||||||
data->reauth = 0;
|
data->reauth = 0;
|
||||||
|
|
|
@ -349,5 +349,6 @@ void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob);
|
||||||
const struct wpa_config_blob *
|
const struct wpa_config_blob *
|
||||||
eap_get_config_blob(struct eap_sm *sm, const char *name);
|
eap_get_config_blob(struct eap_sm *sm, const char *name);
|
||||||
void eap_notify_pending(struct eap_sm *sm);
|
void eap_notify_pending(struct eap_sm *sm);
|
||||||
|
int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method);
|
||||||
|
|
||||||
#endif /* EAP_I_H */
|
#endif /* EAP_I_H */
|
||||||
|
|
|
@ -396,6 +396,35 @@ static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm,
|
||||||
eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
|
eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EAP_AKA_PRIME
|
||||||
|
if (data->eap_method == EAP_TYPE_AKA) {
|
||||||
|
u16 flags = 0;
|
||||||
|
int i;
|
||||||
|
int aka_prime_preferred = 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (sm->user && i < EAP_MAX_METHODS &&
|
||||||
|
(sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
|
||||||
|
sm->user->methods[i].method != EAP_TYPE_NONE)) {
|
||||||
|
if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) {
|
||||||
|
if (sm->user->methods[i].method ==
|
||||||
|
EAP_TYPE_AKA)
|
||||||
|
break;
|
||||||
|
if (sm->user->methods[i].method ==
|
||||||
|
EAP_TYPE_AKA_PRIME) {
|
||||||
|
aka_prime_preferred = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aka_prime_preferred)
|
||||||
|
flags |= EAP_AKA_BIDDING_FLAG_D;
|
||||||
|
eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0);
|
||||||
|
}
|
||||||
|
#endif /* EAP_AKA_PRIME */
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, " AT_MAC");
|
wpa_printf(MSG_DEBUG, " AT_MAC");
|
||||||
eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
|
eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
|
||||||
return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
|
return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
|
||||||
|
|
Loading…
Reference in a new issue