diff options
author | Rui Paulo <rpaulo@FreeBSD.org> | 2015-10-14 04:30:17 +0000 |
---|---|---|
committer | Rui Paulo <rpaulo@FreeBSD.org> | 2015-10-14 04:30:17 +0000 |
commit | b834757ea3bcd1bba3381ff7cab216458d8f7efb (patch) | |
tree | dadb24e00f30aa959ea0981e649b18c668304498 /src/eap_peer | |
parent | fbffd80fb2ba16c68f799da68a119d5e69643604 (diff) |
Notes
Diffstat (limited to 'src/eap_peer')
-rw-r--r-- | src/eap_peer/Makefile | 18 | ||||
-rw-r--r-- | src/eap_peer/eap.c | 14 | ||||
-rw-r--r-- | src/eap_peer/eap.h | 2 | ||||
-rw-r--r-- | src/eap_peer/eap_aka.c | 2 | ||||
-rw-r--r-- | src/eap_peer/eap_eke.c | 105 | ||||
-rw-r--r-- | src/eap_peer/eap_fast.c | 78 | ||||
-rw-r--r-- | src/eap_peer/eap_gpsk.c | 27 | ||||
-rw-r--r-- | src/eap_peer/eap_i.h | 8 | ||||
-rw-r--r-- | src/eap_peer/eap_mschapv2.c | 6 | ||||
-rw-r--r-- | src/eap_peer/eap_pax.c | 2 | ||||
-rw-r--r-- | src/eap_peer/eap_peap.c | 18 | ||||
-rw-r--r-- | src/eap_peer/eap_pwd.c | 116 | ||||
-rw-r--r-- | src/eap_peer/eap_sake.c | 25 | ||||
-rw-r--r-- | src/eap_peer/eap_sim.c | 2 | ||||
-rw-r--r-- | src/eap_peer/eap_tls.c | 18 | ||||
-rw-r--r-- | src/eap_peer/eap_tls_common.c | 137 | ||||
-rw-r--r-- | src/eap_peer/eap_tls_common.h | 2 | ||||
-rw-r--r-- | src/eap_peer/eap_ttls.c | 41 | ||||
-rw-r--r-- | src/eap_peer/eap_wsc.c | 3 |
19 files changed, 392 insertions, 232 deletions
diff --git a/src/eap_peer/Makefile b/src/eap_peer/Makefile index f79519b718499..6531ccd5dac0b 100644 --- a/src/eap_peer/Makefile +++ b/src/eap_peer/Makefile @@ -1,11 +1,23 @@ -all: - @echo Nothing to be made. +all: libeap_peer.a clean: - rm -f *~ *.o *.so *.d *.gcno *.gcda *.gcov + rm -f *~ *.o *.so *.d *.gcno *.gcda *.gcov libeap_peer.a install: if ls *.so >/dev/null 2>&1; then \ install -d $(DESTDIR)$(LIBDIR)/wpa_supplicant && \ cp *.so $(DESTDIR)$(LIBDIR)/wpa_supplicant \ ; fi + +include ../lib.rules + +CFLAGS += -DIEEE8021X_EAPOL + +LIB_OBJS= \ + eap.o \ + eap_methods.o + +libeap_peer.a: $(LIB_OBJS) + $(AR) crT $@ $? + +-include $(OBJS:%.o=%.d) diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c index 35433f3bd8e41..56c24b5503200 100644 --- a/src/eap_peer/eap.c +++ b/src/eap_peer/eap.c @@ -584,7 +584,7 @@ static int eap_peer_erp_reauth_start(struct eap_sm *sm, wpa_printf(MSG_DEBUG, "EAP: Valid ERP key found %s (SEQ=%u)", erp->keyname_nai, erp->next_seq); - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_ERP_TYPE_REAUTH, + msg = eap_msg_alloc(EAP_VENDOR_IETF, (EapType) EAP_ERP_TYPE_REAUTH, 1 + 2 + 2 + os_strlen(erp->keyname_nai) + 1 + 16, EAP_CODE_INITIATE, hdr->identifier); if (msg == NULL) @@ -708,7 +708,7 @@ SM_STATE(EAP, SEND_RESPONSE) wpabuf_free(sm->lastRespData); if (sm->eapRespData) { if (sm->workaround) - os_memcpy(sm->last_md5, sm->req_md5, 16); + os_memcpy(sm->last_sha1, sm->req_sha1, 20); sm->lastId = sm->reqId; sm->lastRespData = wpabuf_dup(sm->eapRespData); eapol_set_bool(sm, EAPOL_eapResp, TRUE); @@ -914,12 +914,12 @@ static int eap_peer_req_is_duplicate(struct eap_sm *sm) duplicate = (sm->reqId == sm->lastId) && sm->rxReq; if (sm->workaround && duplicate && - os_memcmp(sm->req_md5, sm->last_md5, 16) != 0) { + os_memcmp(sm->req_sha1, sm->last_sha1, 20) != 0) { /* * RFC 4137 uses (reqId == lastId) as the only verification for * duplicate EAP requests. However, this misses cases where the * AS is incorrectly using the same id again; and - * unfortunately, such implementations exist. Use MD5 hash as + * unfortunately, such implementations exist. Use SHA1 hash as * an extra verification for the packets being duplicate to * workaround these issues. */ @@ -1765,7 +1765,7 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) if (sm->workaround) { const u8 *addr[1]; addr[0] = wpabuf_head(req); - md5_vector(1, addr, &plen, sm->req_md5); + sha1_vector(1, addr, &plen, sm->req_sha1); } switch (hdr->code) { @@ -1911,7 +1911,7 @@ static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev, * structure remains alive while the EAP state machine is active. */ struct eap_sm * eap_peer_sm_init(void *eapol_ctx, - struct eapol_callbacks *eapol_cb, + const struct eapol_callbacks *eapol_cb, void *msg_ctx, struct eap_config *conf) { struct eap_sm *sm; @@ -2400,7 +2400,7 @@ static int eap_allowed_phase2_type(int vendor, int type) u32 eap_get_phase2_type(const char *name, int *vendor) { int v; - u8 type = eap_peer_get_type(name, &v); + u32 type = eap_peer_get_type(name, &v); if (eap_allowed_phase2_type(v, type)) { *vendor = v; return type; diff --git a/src/eap_peer/eap.h b/src/eap_peer/eap.h index 702463b9d5146..1a645af8b2003 100644 --- a/src/eap_peer/eap.h +++ b/src/eap_peer/eap.h @@ -307,7 +307,7 @@ struct eap_config { }; struct eap_sm * eap_peer_sm_init(void *eapol_ctx, - struct eapol_callbacks *eapol_cb, + const struct eapol_callbacks *eapol_cb, void *msg_ctx, struct eap_config *conf); void eap_peer_sm_deinit(struct eap_sm *sm); int eap_peer_sm_step(struct eap_sm *sm); diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c index 0662ae7383674..dc9e8cc34d4af 100644 --- a/src/eap_peer/eap_aka.c +++ b/src/eap_peer/eap_aka.c @@ -1296,7 +1296,7 @@ static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, reqData, &len); - if (pos == NULL || len < 1) { + if (pos == NULL || len < 3) { ret->ignore = TRUE; return NULL; } diff --git a/src/eap_peer/eap_eke.c b/src/eap_peer/eap_eke.c index 9fec66c068679..dfbda5644f6fc 100644 --- a/src/eap_peer/eap_eke.c +++ b/src/eap_peer/eap_eke.c @@ -195,15 +195,14 @@ static int eap_eke_supp_mac(u8 mac) static struct wpabuf * eap_eke_build_fail(struct eap_eke_data *data, struct eap_method_ret *ret, - const struct wpabuf *reqData, - u32 failure_code) + u8 id, u32 failure_code) { struct wpabuf *resp; wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Failure/Response - code=0x%x", failure_code); - resp = eap_eke_build_msg(data, eap_get_id(reqData), 4, EAP_EKE_FAILURE); + resp = eap_eke_build_msg(data, id, 4, EAP_EKE_FAILURE); if (resp) wpabuf_put_be32(resp, failure_code); @@ -230,9 +229,10 @@ static struct wpabuf * eap_eke_process_id(struct eap_eke_data *data, const u8 *pos, *end; const u8 *prop = NULL; u8 idtype; + u8 id = eap_get_id(reqData); if (data->state != IDENTITY) { - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PROTO_ERROR); } @@ -240,7 +240,7 @@ static struct wpabuf * eap_eke_process_id(struct eap_eke_data *data, if (payload_len < 2 + 4) { wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data"); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PROTO_ERROR); } @@ -253,7 +253,7 @@ static struct wpabuf * eap_eke_process_id(struct eap_eke_data *data, if (pos + num_prop * 4 > end) { wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data (num_prop=%u)", num_prop); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PROTO_ERROR); } @@ -293,7 +293,7 @@ static struct wpabuf * eap_eke_process_id(struct eap_eke_data *data, if (prop == NULL) { wpa_printf(MSG_DEBUG, "EAP-EKE: No acceptable proposal found"); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_NO_PROPOSAL_CHOSEN); } @@ -301,7 +301,7 @@ static struct wpabuf * eap_eke_process_id(struct eap_eke_data *data, if (pos == end) { wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data to include IDType/Identity"); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PROTO_ERROR); } @@ -312,7 +312,7 @@ static struct wpabuf * eap_eke_process_id(struct eap_eke_data *data, os_free(data->serverid); data->serverid = os_malloc(end - pos); if (data->serverid == NULL) { - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } os_memcpy(data->serverid, pos, end - pos); @@ -320,11 +320,11 @@ static struct wpabuf * eap_eke_process_id(struct eap_eke_data *data, wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-ID/Response"); - resp = eap_eke_build_msg(data, eap_get_id(reqData), + resp = eap_eke_build_msg(data, id, 2 + 4 + 1 + data->peerid_len, EAP_EKE_ID); if (resp == NULL) { - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } @@ -339,7 +339,7 @@ static struct wpabuf * eap_eke_process_id(struct eap_eke_data *data, data->msgs = wpabuf_alloc(wpabuf_len(reqData) + wpabuf_len(resp)); if (data->msgs == NULL) { wpabuf_free(resp); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } wpabuf_put_buf(data->msgs, reqData); @@ -366,10 +366,11 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, u8 pub[EAP_EKE_MAX_DH_LEN]; const u8 *password; size_t password_len; + u8 id = eap_get_id(reqData); if (data->state != COMMIT) { wpa_printf(MSG_DEBUG, "EAP-EKE: EAP-EKE-Commit/Request received in unexpected state (%d)", data->state); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PROTO_ERROR); } @@ -378,7 +379,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, password = eap_get_config_password(sm, &password_len); if (password == NULL) { wpa_printf(MSG_INFO, "EAP-EKE: No password configured!"); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PASSWD_NOT_FOUND); } @@ -387,7 +388,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, if (pos + data->sess.dhcomp_len > end) { wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Commit"); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PROTO_ERROR); } @@ -405,7 +406,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, data->serverid, data->serverid_len, data->peerid, data->peerid_len, key) < 0) { wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive key"); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } @@ -416,7 +417,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, if (eap_eke_dh_init(data->sess.dhgroup, data->dh_priv, pub) < 0) { wpa_printf(MSG_INFO, "EAP-EKE: Failed to initialize DH"); os_memset(key, 0, sizeof(key)); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } @@ -424,7 +425,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, { wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive shared secret"); os_memset(key, 0, sizeof(key)); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } @@ -433,18 +434,18 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, data->peerid, data->peerid_len) < 0) { wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive Ke/Ki"); os_memset(key, 0, sizeof(key)); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Commit/Response"); - resp = eap_eke_build_msg(data, eap_get_id(reqData), + resp = eap_eke_build_msg(data, id, data->sess.dhcomp_len + data->sess.pnonce_len, EAP_EKE_COMMIT); if (resp == NULL) { os_memset(key, 0, sizeof(key)); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } @@ -453,7 +454,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, if (eap_eke_dhcomp(&data->sess, key, pub, rpos) < 0) { wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_P"); os_memset(key, 0, sizeof(key)); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } os_memset(key, 0, sizeof(key)); @@ -463,7 +464,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, if (random_get_bytes(data->nonce_p, data->sess.nonce_len)) { wpabuf_free(resp); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_P", @@ -472,7 +473,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, if (eap_eke_prot(&data->sess, data->nonce_p, data->sess.nonce_len, wpabuf_put(resp, 0), &prot_len) < 0) { wpabuf_free(resp); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } wpa_hexdump(MSG_DEBUG, "EAP-EKE: PNonce_P", @@ -484,7 +485,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, if (wpabuf_resize(&data->msgs, wpabuf_len(reqData) + wpabuf_len(resp)) < 0) { wpabuf_free(resp); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } wpabuf_put_buf(data->msgs, reqData); @@ -509,11 +510,12 @@ static struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data, u8 auth_s[EAP_EKE_MAX_HASH_LEN]; size_t decrypt_len; u8 *auth; + u8 id = eap_get_id(reqData); if (data->state != CONFIRM) { wpa_printf(MSG_DEBUG, "EAP-EKE: EAP-EKE-Confirm/Request received in unexpected state (%d)", data->state); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PROTO_ERROR); } @@ -524,7 +526,7 @@ static struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data, if (pos + data->sess.pnonce_ps_len + data->sess.prf_len > end) { wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Confirm"); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PROTO_ERROR); } @@ -532,19 +534,19 @@ static struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data, if (eap_eke_decrypt_prot(&data->sess, pos, data->sess.pnonce_ps_len, nonces, &decrypt_len) < 0) { wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_PS"); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_AUTHENTICATION_FAIL); } if (decrypt_len != (size_t) 2 * data->sess.nonce_len) { wpa_printf(MSG_INFO, "EAP-EKE: PNonce_PS protected data length does not match length of Nonce_P and Nonce_S"); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_AUTHENTICATION_FAIL); } wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_P | Nonce_S", nonces, 2 * data->sess.nonce_len); if (os_memcmp(data->nonce_p, nonces, data->sess.nonce_len) != 0) { wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_P does not match transmitted Nonce_P"); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_AUTHENTICATION_FAIL); } @@ -556,30 +558,30 @@ static struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data, if (eap_eke_derive_ka(&data->sess, data->serverid, data->serverid_len, data->peerid, data->peerid_len, data->nonce_p, data->nonce_s) < 0) { - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } if (eap_eke_auth(&data->sess, "EAP-EKE server", data->msgs, auth_s) < 0) { - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_S", auth_s, data->sess.prf_len); if (os_memcmp_const(auth_s, pos + data->sess.pnonce_ps_len, data->sess.prf_len) != 0) { wpa_printf(MSG_INFO, "EAP-EKE: Auth_S does not match"); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_AUTHENTICATION_FAIL); } wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Confirm/Response"); - resp = eap_eke_build_msg(data, eap_get_id(reqData), + resp = eap_eke_build_msg(data, id, data->sess.pnonce_len + data->sess.prf_len, EAP_EKE_CONFIRM); if (resp == NULL) { - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } @@ -587,7 +589,7 @@ static struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data, if (eap_eke_prot(&data->sess, data->nonce_s, data->sess.nonce_len, wpabuf_put(resp, 0), &prot_len) < 0) { wpabuf_free(resp); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } wpabuf_put(resp, prot_len); @@ -595,7 +597,7 @@ static struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data, auth = wpabuf_put(resp, data->sess.prf_len); if (eap_eke_auth(&data->sess, "EAP-EKE peer", data->msgs, auth) < 0) { wpabuf_free(resp); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_P", auth, data->sess.prf_len); @@ -606,7 +608,7 @@ static struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data, data->msk, data->emsk) < 0) { wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive MSK/EMSK"); wpabuf_free(resp); - return eap_eke_build_fail(data, ret, reqData, + return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } @@ -638,7 +640,8 @@ static struct wpabuf * eap_eke_process_failure(struct eap_eke_data *data, wpa_printf(MSG_INFO, "EAP-EKE: Failure-Code 0x%x", code); } - return eap_eke_build_fail(data, ret, reqData, EAP_EKE_FAIL_NO_ERROR); + return eap_eke_build_fail(data, ret, eap_get_id(reqData), + EAP_EKE_FAIL_NO_ERROR); } @@ -741,6 +744,29 @@ static u8 * eap_eke_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } +static u8 * eap_eke_get_session_id(struct eap_sm *sm, void *priv, size_t *len) +{ + struct eap_eke_data *data = priv; + u8 *sid; + size_t sid_len; + + if (data->state != SUCCESS) + return NULL; + + sid_len = 1 + 2 * data->sess.nonce_len; + sid = os_malloc(sid_len); + if (sid == NULL) + return NULL; + sid[0] = EAP_TYPE_EKE; + os_memcpy(sid + 1, data->nonce_p, data->sess.nonce_len); + os_memcpy(sid + 1 + data->sess.nonce_len, data->nonce_s, + data->sess.nonce_len); + *len = sid_len; + + return sid; +} + + int eap_peer_eke_register(void) { struct eap_method *eap; @@ -757,6 +783,7 @@ int eap_peer_eke_register(void) eap->isKeyAvailable = eap_eke_isKeyAvailable; eap->getKey = eap_eke_getKey; eap->get_emsk = eap_eke_get_emsk; + eap->getSessionId = eap_eke_get_session_id; ret = eap_peer_method_register(eap); if (ret) diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c index 68d7fba8892ef..4cbe3bacb0a61 100644 --- a/src/eap_peer/eap_fast.c +++ b/src/eap_peer/eap_fast.c @@ -267,8 +267,8 @@ static int eap_fast_derive_msk(struct eap_fast_data *data) } -static void eap_fast_derive_key_auth(struct eap_sm *sm, - struct eap_fast_data *data) +static int eap_fast_derive_key_auth(struct eap_sm *sm, + struct eap_fast_data *data) { u8 *sks; @@ -281,7 +281,7 @@ static void eap_fast_derive_key_auth(struct eap_sm *sm, if (sks == NULL) { wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive " "session_key_seed"); - return; + return -1; } /* @@ -294,11 +294,12 @@ static void eap_fast_derive_key_auth(struct eap_sm *sm, data->simck_idx = 0; os_memcpy(data->simck, sks, EAP_FAST_SIMCK_LEN); os_free(sks); + return 0; } -static void eap_fast_derive_key_provisioning(struct eap_sm *sm, - struct eap_fast_data *data) +static int eap_fast_derive_key_provisioning(struct eap_sm *sm, + struct eap_fast_data *data) { os_free(data->key_block_p); data->key_block_p = (struct eap_fast_key_block_provisioning *) @@ -307,7 +308,7 @@ static void eap_fast_derive_key_provisioning(struct eap_sm *sm, sizeof(*data->key_block_p)); if (data->key_block_p == NULL) { wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block"); - return; + return -1; } /* * RFC 4851, Section 5.2: @@ -326,15 +327,19 @@ static void eap_fast_derive_key_provisioning(struct eap_sm *sm, wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: client_challenge", data->key_block_p->client_challenge, sizeof(data->key_block_p->client_challenge)); + return 0; } -static void eap_fast_derive_keys(struct eap_sm *sm, struct eap_fast_data *data) +static int eap_fast_derive_keys(struct eap_sm *sm, struct eap_fast_data *data) { + int res; + if (data->anon_provisioning) - eap_fast_derive_key_provisioning(sm, data); + res = eap_fast_derive_key_provisioning(sm, data); else - eap_fast_derive_key_auth(sm, data); + res = eap_fast_derive_key_auth(sm, data); + return res; } @@ -1172,7 +1177,7 @@ static struct wpabuf * eap_fast_pac_request(void) static int eap_fast_process_decrypted(struct eap_sm *sm, struct eap_fast_data *data, struct eap_method_ret *ret, - const struct eap_hdr *req, + u8 identifier, struct wpabuf *decrypted, struct wpabuf **out_data) { @@ -1184,18 +1189,18 @@ static int eap_fast_process_decrypted(struct eap_sm *sm, return 0; if (resp) return eap_fast_encrypt_response(sm, data, resp, - req->identifier, out_data); + identifier, out_data); if (tlv.result == EAP_TLV_RESULT_FAILURE) { resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0); return eap_fast_encrypt_response(sm, data, resp, - req->identifier, out_data); + identifier, out_data); } if (tlv.iresult == EAP_TLV_RESULT_FAILURE) { resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1); return eap_fast_encrypt_response(sm, data, resp, - req->identifier, out_data); + identifier, out_data); } if (tlv.crypto_binding) { @@ -1277,14 +1282,13 @@ static int eap_fast_process_decrypted(struct eap_sm *sm, resp = wpabuf_alloc(1); } - return eap_fast_encrypt_response(sm, data, resp, req->identifier, + return eap_fast_encrypt_response(sm, data, resp, identifier, out_data); } static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data, - struct eap_method_ret *ret, - const struct eap_hdr *req, + struct eap_method_ret *ret, u8 identifier, const struct wpabuf *in_data, struct wpabuf **out_data) { @@ -1309,7 +1313,7 @@ static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data, /* Received TLS ACK - requesting more fragments */ return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_FAST, data->fast_version, - req->identifier, NULL, out_data); + identifier, NULL, out_data); } res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); @@ -1328,7 +1332,7 @@ continue_req: return -1; } - res = eap_fast_process_decrypted(sm, data, ret, req, + res = eap_fast_process_decrypted(sm, data, ret, identifier, in_decrypted, out_data); wpabuf_free(in_decrypted); @@ -1340,7 +1344,7 @@ continue_req: static const u8 * eap_fast_get_a_id(const u8 *buf, size_t len, size_t *id_len) { const u8 *a_id; - struct pac_tlv_hdr *hdr; + const struct pac_tlv_hdr *hdr; /* * Parse authority identity (A-ID) from the EAP-FAST/Start. This @@ -1350,13 +1354,13 @@ static const u8 * eap_fast_get_a_id(const u8 *buf, size_t len, size_t *id_len) *id_len = len; if (len > sizeof(*hdr)) { int tlen; - hdr = (struct pac_tlv_hdr *) buf; + hdr = (const struct pac_tlv_hdr *) buf; tlen = be_to_host16(hdr->len); if (be_to_host16(hdr->type) == PAC_TYPE_A_ID && sizeof(*hdr) + tlen <= len) { wpa_printf(MSG_DEBUG, "EAP-FAST: A-ID was in TLV " "(Start)"); - a_id = (u8 *) (hdr + 1); + a_id = (const u8 *) (hdr + 1); *id_len = tlen; } } @@ -1529,6 +1533,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv, struct wpabuf *resp; const u8 *pos; struct eap_fast_data *data = priv; + struct wpabuf msg; pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_FAST, ret, reqData, &left, &flags); @@ -1545,13 +1550,13 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv, left = 0; /* A-ID is not used in further packet processing */ } + wpabuf_set(&msg, pos, left); + resp = NULL; if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && !data->resuming) { /* Process tunneled (encrypted) phase 2 data. */ - struct wpabuf msg; - wpabuf_set(&msg, pos, left); - res = eap_fast_decrypt(sm, data, ret, req, &msg, &resp); + res = eap_fast_decrypt(sm, data, ret, id, &msg, &resp); if (res < 0) { ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; @@ -1565,8 +1570,15 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv, /* Continue processing TLS handshake (phase 1). */ res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_FAST, - data->fast_version, id, pos, - left, &resp); + data->fast_version, id, &msg, + &resp); + if (res < 0) { + wpa_printf(MSG_DEBUG, + "EAP-FAST: TLS processing failed"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + return resp; + } if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { char cipher[80]; @@ -1586,20 +1598,24 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv, } else data->anon_provisioning = 0; data->resuming = 0; - eap_fast_derive_keys(sm, data); + if (eap_fast_derive_keys(sm, data) < 0) { + wpa_printf(MSG_DEBUG, + "EAP-FAST: Could not derive keys"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + wpabuf_free(resp); + return NULL; + } } if (res == 2) { - struct wpabuf msg; /* * Application data included in the handshake message. */ wpabuf_free(data->pending_phase2_req); data->pending_phase2_req = resp; resp = NULL; - wpabuf_set(&msg, pos, left); - res = eap_fast_decrypt(sm, data, ret, req, &msg, - &resp); + res = eap_fast_decrypt(sm, data, ret, id, &msg, &resp); } } diff --git a/src/eap_peer/eap_gpsk.c b/src/eap_peer/eap_gpsk.c index c54bf116477c8..902b4ba26d6e4 100644 --- a/src/eap_peer/eap_gpsk.c +++ b/src/eap_peer/eap_gpsk.c @@ -274,7 +274,7 @@ static const u8 * eap_gpsk_process_csuite_list(struct eap_sm *sm, static struct wpabuf * eap_gpsk_process_gpsk_1(struct eap_sm *sm, struct eap_gpsk_data *data, struct eap_method_ret *ret, - const struct wpabuf *reqData, + u8 identifier, const u8 *payload, size_t payload_len) { @@ -301,7 +301,7 @@ static struct wpabuf * eap_gpsk_process_gpsk_1(struct eap_sm *sm, return NULL; } - resp = eap_gpsk_send_gpsk_2(data, eap_get_id(reqData), + resp = eap_gpsk_send_gpsk_2(data, identifier, csuite_list, csuite_list_len); if (resp == NULL) return NULL; @@ -583,7 +583,7 @@ static const u8 * eap_gpsk_validate_gpsk_3_mic(struct eap_gpsk_data *data, static struct wpabuf * eap_gpsk_process_gpsk_3(struct eap_sm *sm, struct eap_gpsk_data *data, struct eap_method_ret *ret, - const struct wpabuf *reqData, + u8 identifier, const u8 *payload, size_t payload_len) { @@ -615,7 +615,7 @@ static struct wpabuf * eap_gpsk_process_gpsk_3(struct eap_sm *sm, (unsigned long) (end - pos)); } - resp = eap_gpsk_send_gpsk_4(data, eap_get_id(reqData)); + resp = eap_gpsk_send_gpsk_4(data, identifier); if (resp == NULL) return NULL; @@ -670,6 +670,7 @@ static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, struct wpabuf *resp; const u8 *pos; size_t len; + u8 opcode, id; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, reqData, &len); if (pos == NULL || len < 1) { @@ -677,25 +678,27 @@ static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, return NULL; } - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", *pos); + id = eap_get_id(reqData); + opcode = *pos++; + len--; + wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", opcode); ret->ignore = FALSE; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; ret->allowNotifications = FALSE; - switch (*pos) { + switch (opcode) { case EAP_GPSK_OPCODE_GPSK_1: - resp = eap_gpsk_process_gpsk_1(sm, data, ret, reqData, - pos + 1, len - 1); + resp = eap_gpsk_process_gpsk_1(sm, data, ret, id, pos, len); break; case EAP_GPSK_OPCODE_GPSK_3: - resp = eap_gpsk_process_gpsk_3(sm, data, ret, reqData, - pos + 1, len - 1); + resp = eap_gpsk_process_gpsk_3(sm, data, ret, id, pos, len); break; default: - wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignoring message with " - "unknown opcode %d", *pos); + wpa_printf(MSG_DEBUG, + "EAP-GPSK: Ignoring message with unknown opcode %d", + opcode); ret->ignore = TRUE; return NULL; } diff --git a/src/eap_peer/eap_i.h b/src/eap_peer/eap_i.h index 2d7fdea227747..99b44dae4e34e 100644 --- a/src/eap_peer/eap_i.h +++ b/src/eap_peer/eap_i.h @@ -328,7 +328,7 @@ struct eap_sm { /* not defined in RFC 4137 */ Boolean changed; void *eapol_ctx; - struct eapol_callbacks *eapol_cb; + const struct eapol_callbacks *eapol_cb; void *eap_method_priv; int init_phase2; int fast_reauth; @@ -338,9 +338,9 @@ struct eap_sm { Boolean rxResp /* LEAP only */; Boolean leap_done; Boolean peap_done; - u8 req_md5[16]; /* MD5() of the current EAP packet */ - u8 last_md5[16]; /* MD5() of the previously received EAP packet; used - * in duplicate request detection. */ + u8 req_sha1[20]; /* SHA1() of the current EAP packet */ + u8 last_sha1[20]; /* SHA1() of the previously received EAP packet; used + * in duplicate request detection. */ void *msg_ctx; void *scard_ctx; diff --git a/src/eap_peer/eap_mschapv2.c b/src/eap_peer/eap_mschapv2.c index 9e486e7d18fac..6acf1e8ad390a 100644 --- a/src/eap_peer/eap_mschapv2.c +++ b/src/eap_peer/eap_mschapv2.c @@ -511,6 +511,11 @@ static struct wpabuf * eap_mschapv2_change_password( struct eap_sm *sm, struct eap_mschapv2_data *data, struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, u8 id) { +#ifdef CONFIG_NO_RC4 + wpa_printf(MSG_ERROR, + "EAP-MSCHAPV2: RC4 not support in the build - cannot change password"); + return NULL; +#else /* CONFIG_NO_RC4 */ struct wpabuf *resp; int ms_len; const u8 *username, *password, *new_password; @@ -628,6 +633,7 @@ static struct wpabuf * eap_mschapv2_change_password( fail: wpabuf_free(resp); return NULL; +#endif /* CONFIG_NO_RC4 */ } diff --git a/src/eap_peer/eap_pax.c b/src/eap_peer/eap_pax.c index 6d1ff208ac7ef..c920bcd3182f8 100644 --- a/src/eap_peer/eap_pax.c +++ b/src/eap_peer/eap_pax.c @@ -333,7 +333,7 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, u16 flen, mlen; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, reqData, &len); - if (pos == NULL || len < EAP_PAX_ICV_LEN) { + if (pos == NULL || len < sizeof(*req) + EAP_PAX_ICV_LEN) { ret->ignore = TRUE; return NULL; } diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c index 86a18bb866de4..98a48a6cf5d31 100644 --- a/src/eap_peer/eap_peap.c +++ b/src/eap_peer/eap_peap.c @@ -968,6 +968,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, struct wpabuf *resp; const u8 *pos; struct eap_peap_data *data = priv; + struct wpabuf msg; pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret, reqData, &left, &flags); @@ -998,18 +999,25 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, * should always be, anyway */ } + wpabuf_set(&msg, pos, left); + resp = NULL; if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && !data->resuming) { - struct wpabuf msg; - wpabuf_set(&msg, pos, left); res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp); } else { res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_PEAP, - data->peap_version, id, pos, - left, &resp); + data->peap_version, id, &msg, + &resp); + if (res < 0) { + wpa_printf(MSG_DEBUG, + "EAP-PEAP: TLS processing failed"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + return resp; + } if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { char *label; wpa_printf(MSG_DEBUG, @@ -1077,14 +1085,12 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, } if (res == 2) { - struct wpabuf msg; /* * Application data included in the handshake message. */ wpabuf_free(data->pending_phase2_req); data->pending_phase2_req = resp; resp = NULL; - wpabuf_set(&msg, pos, left); res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp); } diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c index 059bbeecb72da..1f785443ee5ac 100644 --- a/src/eap_peer/eap_pwd.c +++ b/src/eap_peer/eap_pwd.c @@ -10,6 +10,7 @@ #include "common.h" #include "crypto/sha256.h" +#include "crypto/ms_funcs.h" #include "eap_peer/eap_i.h" #include "eap_common/eap_pwd_common.h" @@ -25,6 +26,7 @@ struct eap_pwd_data { size_t id_server_len; u8 *password; size_t password_len; + int password_hash; u16 group_num; EAP_PWD_group *grp; @@ -86,8 +88,9 @@ static void * eap_pwd_init(struct eap_sm *sm) const u8 *identity, *password; size_t identity_len, password_len; int fragment_size; + int pwhash; - password = eap_get_config_password(sm, &password_len); + password = eap_get_config_password2(sm, &password_len, &pwhash); if (password == NULL) { wpa_printf(MSG_INFO, "EAP-PWD: No password configured!"); return NULL; @@ -129,6 +132,7 @@ static void * eap_pwd_init(struct eap_sm *sm) } os_memcpy(data->password, password, password_len); data->password_len = password_len; + data->password_hash = pwhash; data->out_frag_pos = data->in_frag_pos = 0; data->inbuf = data->outbuf = NULL; @@ -216,6 +220,10 @@ eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data, const u8 *payload, size_t payload_len) { struct eap_pwd_id *id; + const u8 *password; + size_t password_len; + u8 pwhashhash[16]; + int res; if (data->state != PWD_ID_Req) { ret->ignore = TRUE; @@ -231,6 +239,9 @@ eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data, id = (struct eap_pwd_id *) payload; data->group_num = be_to_host16(id->group_num); + wpa_printf(MSG_DEBUG, + "EAP-PWD: Server EAP-pwd-ID proposal: group=%u random=%u prf=%u prep=%u", + data->group_num, id->random_function, id->prf, id->prep); if ((id->random_function != EAP_PWD_DEFAULT_RAND_FUNC) || (id->prf != EAP_PWD_DEFAULT_PRF)) { ret->ignore = TRUE; @@ -238,6 +249,22 @@ eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data, return; } + if (id->prep != EAP_PWD_PREP_NONE && + id->prep != EAP_PWD_PREP_MS) { + wpa_printf(MSG_DEBUG, + "EAP-PWD: Unsupported password pre-processing technique (Prep=%u)", + id->prep); + eap_pwd_state(data, FAILURE); + return; + } + + if (id->prep == EAP_PWD_PREP_NONE && data->password_hash) { + wpa_printf(MSG_DEBUG, + "EAP-PWD: Unhashed password not available"); + eap_pwd_state(data, FAILURE); + return; + } + wpa_printf(MSG_DEBUG, "EAP-PWD (peer): using group %d", data->group_num); @@ -260,12 +287,46 @@ eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data, return; } + if (id->prep == EAP_PWD_PREP_MS) { +#ifdef CONFIG_FIPS + wpa_printf(MSG_ERROR, + "EAP-PWD (peer): MS password hash not supported in FIPS mode"); + eap_pwd_state(data, FAILURE); + return; +#else /* CONFIG_FIPS */ + if (data->password_hash) { + res = hash_nt_password_hash(data->password, pwhashhash); + } else { + u8 pwhash[16]; + + res = nt_password_hash(data->password, + data->password_len, pwhash); + if (res == 0) + res = hash_nt_password_hash(pwhash, pwhashhash); + os_memset(pwhash, 0, sizeof(pwhash)); + } + + if (res) { + eap_pwd_state(data, FAILURE); + return; + } + + password = pwhashhash; + password_len = sizeof(pwhashhash); +#endif /* CONFIG_FIPS */ + } else { + password = data->password; + password_len = data->password_len; + } + /* compute PWE */ - if (compute_password_element(data->grp, data->group_num, - data->password, data->password_len, - data->id_server, data->id_server_len, - data->id_peer, data->id_peer_len, - id->token)) { + res = compute_password_element(data->grp, data->group_num, + password, password_len, + data->id_server, data->id_server_len, + data->id_peer, data->id_peer_len, + id->token); + os_memset(pwhashhash, 0, sizeof(pwhashhash)); + if (res) { wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute PWE"); eap_pwd_state(data, FAILURE); return; @@ -301,6 +362,23 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data, BIGNUM *mask = NULL, *x = NULL, *y = NULL, *cofactor = NULL; u16 offset; u8 *ptr, *scalar = NULL, *element = NULL; + size_t prime_len, order_len; + + if (data->state != PWD_Commit_Req) { + ret->ignore = TRUE; + goto fin; + } + + prime_len = BN_num_bytes(data->grp->prime); + order_len = BN_num_bytes(data->grp->order); + + if (payload_len != 2 * prime_len + order_len) { + wpa_printf(MSG_INFO, + "EAP-pwd: Unexpected Commit payload length %u (expected %u)", + (unsigned int) payload_len, + (unsigned int) (2 * prime_len + order_len)); + goto fin; + } if (((data->private_value = BN_new()) == NULL) || ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) || @@ -500,6 +578,18 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data, u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr; int offset; + if (data->state != PWD_Confirm_Req) { + ret->ignore = TRUE; + goto fin; + } + + if (payload_len != SHA256_MAC_LEN) { + wpa_printf(MSG_INFO, + "EAP-pwd: Unexpected Confirm payload length %u (expected %u)", + (unsigned int) payload_len, SHA256_MAC_LEN); + goto fin; + } + /* * first build up the ciphersuite which is group | random_function | * prf @@ -783,17 +873,30 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, * if it's the first fragment there'll be a length field */ if (EAP_PWD_GET_LENGTH_BIT(lm_exch)) { + if (len < 2) { + wpa_printf(MSG_DEBUG, + "EAP-pwd: Frame too short to contain Total-Length field"); + ret->ignore = TRUE; + return NULL; + } tot_len = WPA_GET_BE16(pos); wpa_printf(MSG_DEBUG, "EAP-pwd: Incoming fragments whose " "total length = %d", tot_len); if (tot_len > 15000) return NULL; + if (data->inbuf) { + wpa_printf(MSG_DEBUG, + "EAP-pwd: Unexpected new fragment start when previous fragment is still in use"); + ret->ignore = TRUE; + return NULL; + } data->inbuf = wpabuf_alloc(tot_len); if (data->inbuf == NULL) { wpa_printf(MSG_INFO, "Out of memory to buffer " "fragments!"); return NULL; } + data->in_frag_pos = 0; pos += sizeof(u16); len -= sizeof(u16); } @@ -873,6 +976,7 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, /* * we have output! Do we need to fragment it? */ + lm_exch = EAP_PWD_GET_EXCHANGE(lm_exch); len = wpabuf_len(data->outbuf); if ((len + EAP_PWD_HDR_SIZE) > data->mtu) { resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, data->mtu, diff --git a/src/eap_peer/eap_sake.c b/src/eap_peer/eap_sake.c index 7d14907433e50..c4f9843febb35 100644 --- a/src/eap_peer/eap_sake.c +++ b/src/eap_peer/eap_sake.c @@ -141,7 +141,7 @@ static struct wpabuf * eap_sake_build_msg(struct eap_sake_data *data, static struct wpabuf * eap_sake_process_identity(struct eap_sm *sm, struct eap_sake_data *data, struct eap_method_ret *ret, - const struct wpabuf *reqData, + u8 id, const u8 *payload, size_t payload_len) { @@ -166,8 +166,7 @@ static struct wpabuf * eap_sake_process_identity(struct eap_sm *sm, wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Identity"); - resp = eap_sake_build_msg(data, eap_get_id(reqData), - 2 + data->peerid_len, + resp = eap_sake_build_msg(data, id, 2 + data->peerid_len, EAP_SAKE_SUBTYPE_IDENTITY); if (resp == NULL) return NULL; @@ -185,7 +184,7 @@ static struct wpabuf * eap_sake_process_identity(struct eap_sm *sm, static struct wpabuf * eap_sake_process_challenge(struct eap_sm *sm, struct eap_sake_data *data, struct eap_method_ret *ret, - const struct wpabuf *reqData, + u8 id, const u8 *payload, size_t payload_len) { @@ -247,8 +246,7 @@ static struct wpabuf * eap_sake_process_challenge(struct eap_sm *sm, rlen = 2 + EAP_SAKE_RAND_LEN + 2 + EAP_SAKE_MIC_LEN; if (data->peerid) rlen += 2 + data->peerid_len; - resp = eap_sake_build_msg(data, eap_get_id(reqData), rlen, - EAP_SAKE_SUBTYPE_CHALLENGE); + resp = eap_sake_build_msg(data, id, rlen, EAP_SAKE_SUBTYPE_CHALLENGE); if (resp == NULL) return NULL; @@ -285,6 +283,7 @@ static struct wpabuf * eap_sake_process_challenge(struct eap_sm *sm, static struct wpabuf * eap_sake_process_confirm(struct eap_sm *sm, struct eap_sake_data *data, struct eap_method_ret *ret, + u8 id, const struct wpabuf *reqData, const u8 *payload, size_t payload_len) @@ -323,14 +322,13 @@ static struct wpabuf * eap_sake_process_confirm(struct eap_sm *sm, ret->allowNotifications = FALSE; wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending " "Response/Auth-Reject"); - return eap_sake_build_msg(data, eap_get_id(reqData), 0, + return eap_sake_build_msg(data, id, 0, EAP_SAKE_SUBTYPE_AUTH_REJECT); } wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Confirm"); - resp = eap_sake_build_msg(data, eap_get_id(reqData), - 2 + EAP_SAKE_MIC_LEN, + resp = eap_sake_build_msg(data, id, 2 + EAP_SAKE_MIC_LEN, EAP_SAKE_SUBTYPE_CONFIRM); if (resp == NULL) return NULL; @@ -367,7 +365,7 @@ static struct wpabuf * eap_sake_process(struct eap_sm *sm, void *priv, struct wpabuf *resp; const u8 *pos, *end; size_t len; - u8 subtype, session_id; + u8 subtype, session_id, id; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, reqData, &len); if (pos == NULL || len < sizeof(struct eap_sake_hdr)) { @@ -377,6 +375,7 @@ static struct wpabuf * eap_sake_process(struct eap_sm *sm, void *priv, req = (const struct eap_sake_hdr *) pos; end = pos + len; + id = eap_get_id(reqData); subtype = req->subtype; session_id = req->session_id; pos = (const u8 *) (req + 1); @@ -402,15 +401,15 @@ static struct wpabuf * eap_sake_process(struct eap_sm *sm, void *priv, switch (subtype) { case EAP_SAKE_SUBTYPE_IDENTITY: - resp = eap_sake_process_identity(sm, data, ret, reqData, + resp = eap_sake_process_identity(sm, data, ret, id, pos, end - pos); break; case EAP_SAKE_SUBTYPE_CHALLENGE: - resp = eap_sake_process_challenge(sm, data, ret, reqData, + resp = eap_sake_process_challenge(sm, data, ret, id, pos, end - pos); break; case EAP_SAKE_SUBTYPE_CONFIRM: - resp = eap_sake_process_confirm(sm, data, ret, reqData, + resp = eap_sake_process_confirm(sm, data, ret, id, reqData, pos, end - pos); break; default: diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c index bd06df78db4c4..99a2816ce61ed 100644 --- a/src/eap_peer/eap_sim.c +++ b/src/eap_peer/eap_sim.c @@ -1042,7 +1042,7 @@ static struct wpabuf * eap_sim_process(struct eap_sm *sm, void *priv, } pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, reqData, &len); - if (pos == NULL || len < 1) { + if (pos == NULL || len < 3) { ret->ignore = TRUE; return NULL; } diff --git a/src/eap_peer/eap_tls.c b/src/eap_peer/eap_tls.c index 5aa3fd5912563..66a027a626e0d 100644 --- a/src/eap_peer/eap_tls.c +++ b/src/eap_peer/eap_tls.c @@ -156,20 +156,6 @@ static struct wpabuf * eap_tls_failure(struct eap_sm *sm, ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - if (res == -1) { - struct eap_peer_config *config = eap_get_config(sm); - if (config) { - /* - * The TLS handshake failed. So better forget the old - * PIN. It may be wrong, we cannot be sure but trying - * the wrong one again might block it on the card--so - * better ask the user again. - */ - os_free(config->pin); - config->pin = NULL; - } - } - if (resp) { /* * This is likely an alert message, so send it instead of just @@ -228,6 +214,7 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, u8 flags, id; const u8 *pos; struct eap_tls_data *data = priv; + struct wpabuf msg; pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret, reqData, &left, &flags); @@ -242,8 +229,9 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, } resp = NULL; + wpabuf_set(&msg, pos, left); res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0, - id, pos, left, &resp); + id, &msg, &resp); if (res < 0) { return eap_tls_failure(sm, data, ret, res, resp, id); diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c index 8710781618eff..af2b7541d7016 100644 --- a/src/eap_peer/eap_tls_common.c +++ b/src/eap_peer/eap_tls_common.c @@ -68,6 +68,10 @@ static void eap_tls_params_flags(struct tls_connection_params *params, params->flags |= TLS_CONN_DISABLE_SESSION_TICKET; if (os_strstr(txt, "tls_disable_session_ticket=0")) params->flags &= ~TLS_CONN_DISABLE_SESSION_TICKET; + if (os_strstr(txt, "tls_disable_tlsv1_0=1")) + params->flags |= TLS_CONN_DISABLE_TLSv1_0; + if (os_strstr(txt, "tls_disable_tlsv1_0=0")) + params->flags &= ~TLS_CONN_DISABLE_TLSv1_0; if (os_strstr(txt, "tls_disable_tlsv1_1=1")) params->flags |= TLS_CONN_DISABLE_TLSv1_1; if (os_strstr(txt, "tls_disable_tlsv1_1=0")) @@ -196,28 +200,25 @@ static int eap_tls_init_connection(struct eap_sm *sm, } res = tls_connection_set_params(data->ssl_ctx, data->conn, params); - if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) { + if (res == TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN) { /* - * At this point with the pkcs11 engine the PIN might be wrong. - * We reset the PIN in the configuration to be sure to not use - * it again and the calling function must request a new one. + * At this point with the pkcs11 engine the PIN is wrong. We + * reset the PIN in the configuration to be sure to not use it + * again and the calling function must request a new one. */ + wpa_printf(MSG_INFO, + "TLS: Bad PIN provided, requesting a new one"); os_free(config->pin); config->pin = NULL; + eap_sm_request_pin(sm); + sm->ignore = TRUE; + } else if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) { + wpa_printf(MSG_INFO, "TLS: Failed to initialize engine"); } else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) { wpa_printf(MSG_INFO, "TLS: Failed to load private key"); - /* - * We do not know exactly but maybe the PIN was wrong, - * so ask for a new one. - */ - os_free(config->pin); - config->pin = NULL; - eap_sm_request_pin(sm); sm->ignore = TRUE; - tls_connection_deinit(data->ssl_ctx, data->conn); - data->conn = NULL; - return -1; - } else if (res) { + } + if (res) { wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection " "parameters"); tls_connection_deinit(data->ssl_ctx, data->conn); @@ -313,53 +314,19 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, const char *label, size_t len) { -#ifndef CONFIG_FIPS - struct tls_keys keys; -#endif /* CONFIG_FIPS */ - u8 *rnd = NULL, *out; + u8 *out; out = os_malloc(len); if (out == NULL) return NULL; - /* First, try to use TLS library function for PRF, if available. */ - if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, out, len) - == 0) - return out; - -#ifndef CONFIG_FIPS - /* - * TLS library did not support key generation, so get the needed TLS - * session parameters and use an internal implementation of TLS PRF to - * derive the key. - */ - if (tls_connection_get_keys(data->ssl_ctx, data->conn, &keys)) - goto fail; - - if (keys.client_random == NULL || keys.server_random == NULL || - keys.master_key == NULL) - goto fail; - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - if (rnd == NULL) - goto fail; - os_memcpy(rnd, keys.client_random, keys.client_random_len); - os_memcpy(rnd + keys.client_random_len, keys.server_random, - keys.server_random_len); - - if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len, - label, rnd, keys.client_random_len + - keys.server_random_len, out, len)) - goto fail; + if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, 0, + out, len)) { + os_free(out); + return NULL; + } - os_free(rnd); return out; - -fail: -#endif /* CONFIG_FIPS */ - os_free(out); - os_free(rnd); - return NULL; } @@ -380,10 +347,10 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm, struct eap_ssl_data *data, u8 eap_type, size_t *len) { - struct tls_keys keys; + struct tls_random keys; u8 *out; - if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) + if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys)) return NULL; if (keys.client_random == NULL || keys.server_random == NULL) @@ -514,22 +481,19 @@ static const struct wpabuf * eap_peer_tls_data_reassemble( * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() * @data: Data for TLS processing * @in_data: Message received from the server - * @in_len: Length of in_data * @out_data: Buffer for returning a pointer to application data (if available) * Returns: 0 on success, 1 if more input data is needed, 2 if application data * is available, -1 on failure */ static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data, - const u8 *in_data, size_t in_len, + const struct wpabuf *in_data, struct wpabuf **out_data) { const struct wpabuf *msg; int need_more_input; struct wpabuf *appl_data; - struct wpabuf buf; - wpabuf_set(&buf, in_data, in_len); - msg = eap_peer_tls_data_reassemble(data, &buf, &need_more_input); + msg = eap_peer_tls_data_reassemble(data, in_data, &need_more_input); if (msg == NULL) return need_more_input ? 1 : -1; @@ -649,7 +613,6 @@ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type, * @peap_version: Version number for EAP-PEAP/TTLS * @id: EAP identifier for the response * @in_data: Message received from the server - * @in_len: Length of in_data * @out_data: Buffer for returning a pointer to the response message * Returns: 0 on success, 1 if more input data is needed, 2 if application data * is available, or -1 on failure @@ -672,14 +635,15 @@ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type, */ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, EapType eap_type, int peap_version, - u8 id, const u8 *in_data, size_t in_len, + u8 id, const struct wpabuf *in_data, struct wpabuf **out_data) { int ret = 0; *out_data = NULL; - if (data->tls_out && wpabuf_len(data->tls_out) > 0 && in_len > 0) { + if (data->tls_out && wpabuf_len(data->tls_out) > 0 && + wpabuf_len(in_data) > 0) { wpa_printf(MSG_DEBUG, "SSL: Received non-ACK when output " "fragments are waiting to be sent out"); return -1; @@ -690,8 +654,7 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, * No more data to send out - expect to receive more data from * the AS. */ - int res = eap_tls_process_input(sm, data, in_data, in_len, - out_data); + int res = eap_tls_process_input(sm, data, in_data, out_data); if (res) { /* * Input processing failed (res = -1) or more data is @@ -719,12 +682,18 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, if (tls_connection_get_failed(data->ssl_ctx, data->conn)) { /* TLS processing has failed - return error */ wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to " - "report error"); + "report error (len=%u)", + (unsigned int) wpabuf_len(data->tls_out)); ret = -1; /* TODO: clean pin if engine used? */ + if (wpabuf_len(data->tls_out) == 0) { + wpabuf_free(data->tls_out); + data->tls_out = NULL; + return -1; + } } - if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) { + if (wpabuf_len(data->tls_out) == 0) { /* * TLS negotiation should now be complete since all other cases * needing more data should have been caught above based on @@ -790,20 +759,24 @@ int eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data) int eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, char *buf, size_t buflen, int verbose) { - char name[128]; + char version[20], name[128]; int len = 0, ret; - if (tls_get_cipher(data->ssl_ctx, data->conn, name, sizeof(name)) == 0) - { - ret = os_snprintf(buf + len, buflen - len, - "EAP TLS cipher=%s\n" - "tls_session_reused=%d\n", - name, tls_connection_resumed(data->ssl_ctx, - data->conn)); - if (os_snprintf_error(buflen - len, ret)) - return len; - len += ret; - } + if (tls_get_version(data->ssl_ctx, data->conn, version, + sizeof(version)) < 0) + version[0] = '\0'; + if (tls_get_cipher(data->ssl_ctx, data->conn, name, sizeof(name)) < 0) + name[0] = '\0'; + + ret = os_snprintf(buf + len, buflen - len, + "eap_tls_version=%s\n" + "EAP TLS cipher=%s\n" + "tls_session_reused=%d\n", + version, name, + tls_connection_resumed(data->ssl_ctx, data->conn)); + if (os_snprintf_error(buflen - len, ret)) + return len; + len += ret; return len; } @@ -1032,7 +1005,7 @@ int eap_peer_select_phase2_methods(struct eap_peer_config *config, { char *start, *pos, *buf; struct eap_method_type *methods = NULL, *_methods; - u8 method; + u32 method; size_t num_methods = 0, prefix_len; if (config == NULL || config->phase2 == NULL) diff --git a/src/eap_peer/eap_tls_common.h b/src/eap_peer/eap_tls_common.h index 390c2165927cb..acd2b783617fe 100644 --- a/src/eap_peer/eap_tls_common.h +++ b/src/eap_peer/eap_tls_common.h @@ -100,7 +100,7 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm, size_t *len); int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, EapType eap_type, int peap_version, - u8 id, const u8 *in_data, size_t in_len, + u8 id, const struct wpabuf *in_data, struct wpabuf **out_data); struct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type, int peap_version); diff --git a/src/eap_peer/eap_ttls.c b/src/eap_peer/eap_ttls.c index b5c028b5276d5..b186c9156a741 100644 --- a/src/eap_peer/eap_ttls.c +++ b/src/eap_peer/eap_ttls.c @@ -175,7 +175,8 @@ static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id, } avp->avp_code = host_to_be32(avp_code); - avp->avp_length = host_to_be32((flags << 24) | (u32) (hdrlen + len)); + avp->avp_length = host_to_be32(((u32) flags << 24) | + (u32) (hdrlen + len)); return avphdr + hdrlen; } @@ -253,11 +254,13 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm, } +#ifndef CONFIG_FIPS static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, struct eap_ttls_data *data, size_t len) { return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len); } +#endif /* CONFIG_FIPS */ static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data, @@ -428,6 +431,10 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, struct eap_method_ret *ret, struct wpabuf **resp) { +#ifdef CONFIG_FIPS + wpa_printf(MSG_ERROR, "EAP-TTLS: MSCHAPV2 not supported in FIPS build"); + return -1; +#else /* CONFIG_FIPS */ #ifdef EAP_MSCHAPv2 struct wpabuf *msg; u8 *buf, *pos, *challenge, *peer_challenge; @@ -510,6 +517,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, wpa_printf(MSG_ERROR, "EAP-TTLS: MSCHAPv2 not included in the build"); return -1; #endif /* EAP_MSCHAPv2 */ +#endif /* CONFIG_FIPS */ } @@ -518,6 +526,10 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm, struct eap_method_ret *ret, struct wpabuf **resp) { +#ifdef CONFIG_FIPS + wpa_printf(MSG_ERROR, "EAP-TTLS: MSCHAP not supported in FIPS build"); + return -1; +#else /* CONFIG_FIPS */ struct wpabuf *msg; u8 *buf, *pos, *challenge; const u8 *identity, *password; @@ -592,6 +604,7 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm, ret->decision = DECISION_COND_SUCC; return 0; +#endif /* CONFIG_FIPS */ } @@ -654,6 +667,10 @@ static int eap_ttls_phase2_request_chap(struct eap_sm *sm, struct eap_method_ret *ret, struct wpabuf **resp) { +#ifdef CONFIG_FIPS + wpa_printf(MSG_ERROR, "EAP-TTLS: CHAP not supported in FIPS build"); + return -1; +#else /* CONFIG_FIPS */ struct wpabuf *msg; u8 *buf, *pos, *challenge; const u8 *identity, *password; @@ -722,6 +739,7 @@ static int eap_ttls_phase2_request_chap(struct eap_sm *sm, ret->decision = DECISION_COND_SUCC; return 0; +#endif /* CONFIG_FIPS */ } @@ -1385,14 +1403,20 @@ static int eap_ttls_process_handshake(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret, u8 identifier, - const u8 *in_data, size_t in_len, + const struct wpabuf *in_data, struct wpabuf **out_data) { int res; res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS, data->ttls_version, identifier, - in_data, in_len, out_data); + in_data, out_data); + if (res < 0) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS processing failed"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + return -1; + } if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to " @@ -1419,15 +1443,13 @@ static int eap_ttls_process_handshake(struct eap_sm *sm, } if (res == 2) { - struct wpabuf msg; /* * Application data included in the handshake message. */ wpabuf_free(data->pending_phase2_req); data->pending_phase2_req = *out_data; *out_data = NULL; - wpabuf_set(&msg, in_data, in_len); - res = eap_ttls_decrypt(sm, data, ret, identifier, &msg, + res = eap_ttls_decrypt(sm, data, ret, identifier, in_data, out_data); } @@ -1477,6 +1499,7 @@ static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv, struct wpabuf *resp; const u8 *pos; struct eap_ttls_data *data = priv; + struct wpabuf msg; pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TTLS, ret, reqData, &left, &flags); @@ -1497,15 +1520,15 @@ static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv, left = 0; } + wpabuf_set(&msg, pos, left); + resp = NULL; if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && !data->resuming) { - struct wpabuf msg; - wpabuf_set(&msg, pos, left); res = eap_ttls_decrypt(sm, data, ret, id, &msg, &resp); } else { res = eap_ttls_process_handshake(sm, data, ret, id, - pos, left, &resp); + &msg, &resp); } eap_ttls_check_auth_status(sm, data, ret); diff --git a/src/eap_peer/eap_wsc.c b/src/eap_peer/eap_wsc.c index 7ce0a53d0b299..7ac99c7ce727b 100644 --- a/src/eap_peer/eap_wsc.c +++ b/src/eap_peer/eap_wsc.c @@ -557,6 +557,9 @@ send_msg: if (data->out_buf == NULL) { wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to receive " "message from WPS"); + eap_wsc_state(data, FAIL); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; return NULL; } data->out_used = 0; |