diff options
5 files changed, 467 insertions, 1 deletions
diff --git a/package/network/services/hostapd/Makefile b/package/network/services/hostapd/Makefile index 6308dca84f..235f178bc9 100644 --- a/package/network/services/hostapd/Makefile +++ b/package/network/services/hostapd/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=hostapd -PKG_RELEASE:=5 +PKG_RELEASE:=6 PKG_SOURCE_URL:=http://w1.fi/hostap.git PKG_SOURCE_PROTO:=git diff --git a/package/network/services/hostapd/patches/064-0011-EAP-pwd-server-Verify-received-scalar-and-element.patch b/package/network/services/hostapd/patches/064-0011-EAP-pwd-server-Verify-received-scalar-and-element.patch new file mode 100644 index 0000000000..8ecb5fd502 --- /dev/null +++ b/package/network/services/hostapd/patches/064-0011-EAP-pwd-server-Verify-received-scalar-and-element.patch @@ -0,0 +1,53 @@ +From 70ff850e89fbc8bc7da515321b4d15b5eef70581 Mon Sep 17 00:00:00 2001 +From: Mathy Vanhoef <mathy.vanhoef@nyu.edu> +Date: Sun, 31 Mar 2019 17:13:06 +0200 +Subject: [PATCH 11/14] EAP-pwd server: Verify received scalar and element + +When processing an EAP-pwd Commit frame, the peer's scalar and element +(elliptic curve point) were not validated. This allowed an adversary to +bypass authentication, and impersonate any user if the crypto +implementation did not verify the validity of the EC point. + +Fix this vulnerability by assuring the received scalar lies within the +valid range, and by checking that the received element is not the point +at infinity and lies on the elliptic curve being used. (CVE-2019-9498) + +The vulnerability is only exploitable if OpenSSL version 1.0.2 or lower +is used, or if LibreSSL or wolfssl is used. Newer versions of OpenSSL +(and also BoringSSL) implicitly validate the elliptic curve point in +EC_POINT_set_affine_coordinates_GFp(), preventing the attack. + +Signed-off-by: Mathy Vanhoef <mathy.vanhoef@nyu.edu> +--- + src/eap_server/eap_server_pwd.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/src/eap_server/eap_server_pwd.c ++++ b/src/eap_server/eap_server_pwd.c +@@ -718,6 +718,26 @@ eap_pwd_process_commit_resp(struct eap_s + goto fin; + } + ++ /* verify received scalar */ ++ if (crypto_bignum_is_zero(data->peer_scalar) || ++ crypto_bignum_is_one(data->peer_scalar) || ++ crypto_bignum_cmp(data->peer_scalar, ++ crypto_ec_get_order(data->grp->group)) >= 0) { ++ wpa_printf(MSG_INFO, ++ "EAP-PWD (server): received scalar is invalid"); ++ goto fin; ++ } ++ ++ /* verify received element */ ++ if (!crypto_ec_point_is_on_curve(data->grp->group, ++ data->peer_element) || ++ crypto_ec_point_is_at_infinity(data->grp->group, ++ data->peer_element)) { ++ wpa_printf(MSG_INFO, ++ "EAP-PWD (server): received element is invalid"); ++ goto fin; ++ } ++ + /* check to ensure peer's element is not in a small sub-group */ + if (!crypto_bignum_is_one(cofactor)) { + if (crypto_ec_point_mul(data->grp->group, data->peer_element, diff --git a/package/network/services/hostapd/patches/064-0012-EAP-pwd-server-Detect-reflection-attacks.patch b/package/network/services/hostapd/patches/064-0012-EAP-pwd-server-Detect-reflection-attacks.patch new file mode 100644 index 0000000000..44949cb24d --- /dev/null +++ b/package/network/services/hostapd/patches/064-0012-EAP-pwd-server-Detect-reflection-attacks.patch @@ -0,0 +1,40 @@ +From d63edfa90243e9a7de6ae5c275032f2cc79fef95 Mon Sep 17 00:00:00 2001 +From: Mathy Vanhoef <mathy.vanhoef@nyu.edu> +Date: Sun, 31 Mar 2019 17:26:01 +0200 +Subject: [PATCH 12/14] EAP-pwd server: Detect reflection attacks + +When processing an EAP-pwd Commit frame, verify that the peer's scalar +and elliptic curve element differ from the one sent by the server. This +prevents reflection attacks where the adversary reflects the scalar and +element sent by the server. (CVE-2019-9497) + +The vulnerability allows an adversary to complete the EAP-pwd handshake +as any user. However, the adversary does not learn the negotiated +session key, meaning the subsequent 4-way handshake would fail. As a +result, this cannot be abused to bypass authentication unless EAP-pwd is +used in non-WLAN cases without any following key exchange that would +require the attacker to learn the MSK. + +Signed-off-by: Mathy Vanhoef <mathy.vanhoef@nyu.edu> +--- + src/eap_server/eap_server_pwd.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/src/eap_server/eap_server_pwd.c ++++ b/src/eap_server/eap_server_pwd.c +@@ -753,6 +753,15 @@ eap_pwd_process_commit_resp(struct eap_s + } + } + ++ /* detect reflection attacks */ ++ if (crypto_bignum_cmp(data->my_scalar, data->peer_scalar) == 0 || ++ crypto_ec_point_cmp(data->grp->group, data->my_element, ++ data->peer_element) == 0) { ++ wpa_printf(MSG_INFO, ++ "EAP-PWD (server): detected reflection attack!"); ++ goto fin; ++ } ++ + /* compute the shared key, k */ + if ((crypto_ec_point_mul(data->grp->group, data->grp->pwe, + data->peer_scalar, K) < 0) || diff --git a/package/network/services/hostapd/patches/064-0013-EAP-pwd-client-Verify-received-scalar-and-element.patch b/package/network/services/hostapd/patches/064-0013-EAP-pwd-client-Verify-received-scalar-and-element.patch new file mode 100644 index 0000000000..9c7707ae3f --- /dev/null +++ b/package/network/services/hostapd/patches/064-0013-EAP-pwd-client-Verify-received-scalar-and-element.patch @@ -0,0 +1,53 @@ +From 8ad8585f91823ddcc3728155e288e0f9f872e31a Mon Sep 17 00:00:00 2001 +From: Mathy Vanhoef <mathy.vanhoef@nyu.edu> +Date: Sun, 31 Mar 2019 17:43:44 +0200 +Subject: [PATCH 13/14] EAP-pwd client: Verify received scalar and element + +When processing an EAP-pwd Commit frame, the server's scalar and element +(elliptic curve point) were not validated. This allowed an adversary to +bypass authentication, and act as a rogue Access Point (AP) if the +crypto implementation did not verify the validity of the EC point. + +Fix this vulnerability by assuring the received scalar lies within the +valid range, and by checking that the received element is not the point +at infinity and lies on the elliptic curve being used. (CVE-2019-9499) + +The vulnerability is only exploitable if OpenSSL version 1.0.2 or lower +is used, or if LibreSSL or wolfssl is used. Newer versions of OpenSSL +(and also BoringSSL) implicitly validate the elliptic curve point in +EC_POINT_set_affine_coordinates_GFp(), preventing the attack. + +Signed-off-by: Mathy Vanhoef <mathy.vanhoef@nyu.edu> +--- + src/eap_peer/eap_pwd.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/src/eap_peer/eap_pwd.c ++++ b/src/eap_peer/eap_pwd.c +@@ -594,6 +594,26 @@ eap_pwd_perform_commit_exchange(struct e + goto fin; + } + ++ /* verify received scalar */ ++ if (crypto_bignum_is_zero(data->server_scalar) || ++ crypto_bignum_is_one(data->server_scalar) || ++ crypto_bignum_cmp(data->server_scalar, ++ crypto_ec_get_order(data->grp->group)) >= 0) { ++ wpa_printf(MSG_INFO, ++ "EAP-PWD (peer): received scalar is invalid"); ++ goto fin; ++ } ++ ++ /* verify received element */ ++ if (!crypto_ec_point_is_on_curve(data->grp->group, ++ data->server_element) || ++ crypto_ec_point_is_at_infinity(data->grp->group, ++ data->server_element)) { ++ wpa_printf(MSG_INFO, ++ "EAP-PWD (peer): received element is invalid"); ++ goto fin; ++ } ++ + /* check to ensure server's element is not in a small sub-group */ + if (!crypto_bignum_is_one(cofactor)) { + if (crypto_ec_point_mul(data->grp->group, data->server_element, diff --git a/package/network/services/hostapd/patches/064-0014-EAP-pwd-Check-element-x-y-coordinates-explicitly.patch b/package/network/services/hostapd/patches/064-0014-EAP-pwd-Check-element-x-y-coordinates-explicitly.patch new file mode 100644 index 0000000000..ab1edfaffc --- /dev/null +++ b/package/network/services/hostapd/patches/064-0014-EAP-pwd-Check-element-x-y-coordinates-explicitly.patch @@ -0,0 +1,320 @@ +From 16d4f1069118aa19bfce013493e1ac5783f92f1d Mon Sep 17 00:00:00 2001 +From: Jouni Malinen <jouni@codeaurora.org> +Date: Fri, 5 Apr 2019 02:12:50 +0300 +Subject: [PATCH 14/14] EAP-pwd: Check element x,y coordinates explicitly + +This adds an explicit check for 0 < x,y < prime based on RFC 5931, +2.8.5.2.2 requirement. The earlier checks might have covered this +implicitly, but it is safer to avoid any dependency on implicit checks +and specific crypto library behavior. (CVE-2019-9498 and CVE-2019-9499) + +Furthermore, this moves the EAP-pwd element and scalar parsing and +validation steps into shared helper functions so that there is no need +to maintain two separate copies of this common functionality between the +server and peer implementations. + +Signed-off-by: Jouni Malinen <jouni@codeaurora.org> +--- + src/eap_common/eap_pwd_common.c | 106 ++++++++++++++++++++++++++++++++++++++++ + src/eap_common/eap_pwd_common.h | 3 ++ + src/eap_peer/eap_pwd.c | 45 ++--------------- + src/eap_server/eap_server_pwd.c | 45 ++--------------- + 4 files changed, 117 insertions(+), 82 deletions(-) + +--- a/src/eap_common/eap_pwd_common.c ++++ b/src/eap_common/eap_pwd_common.c +@@ -427,3 +427,109 @@ int compute_keys(EAP_PWD_group *grp, con + + return 1; + } ++ ++ ++static int eap_pwd_element_coord_ok(const struct crypto_bignum *prime, ++ const u8 *buf, size_t len) ++{ ++ struct crypto_bignum *val; ++ int ok = 1; ++ ++ val = crypto_bignum_init_set(buf, len); ++ if (!val || crypto_bignum_is_zero(val) || ++ crypto_bignum_cmp(val, prime) >= 0) ++ ok = 0; ++ crypto_bignum_deinit(val, 0); ++ return ok; ++} ++ ++ ++struct crypto_ec_point * eap_pwd_get_element(EAP_PWD_group *group, ++ const u8 *buf) ++{ ++ struct crypto_ec_point *element; ++ const struct crypto_bignum *prime; ++ size_t prime_len; ++ struct crypto_bignum *cofactor = NULL; ++ ++ prime = crypto_ec_get_prime(group->group); ++ prime_len = crypto_ec_prime_len(group->group); ++ ++ /* RFC 5931, 2.8.5.2.2: 0 < x,y < p */ ++ if (!eap_pwd_element_coord_ok(prime, buf, prime_len) || ++ !eap_pwd_element_coord_ok(prime, buf + prime_len, prime_len)) { ++ wpa_printf(MSG_INFO, "EAP-pwd: Invalid coordinate in element"); ++ return NULL; ++ } ++ ++ element = crypto_ec_point_from_bin(group->group, buf); ++ if (!element) { ++ wpa_printf(MSG_INFO, "EAP-pwd: EC point from element failed"); ++ return NULL; ++ } ++ ++ /* RFC 5931, 2.8.5.2.2: on curve and not the point at infinity */ ++ if (!crypto_ec_point_is_on_curve(group->group, element) || ++ crypto_ec_point_is_at_infinity(group->group, element)) { ++ wpa_printf(MSG_INFO, "EAP-pwd: Invalid element"); ++ goto fail; ++ } ++ ++ cofactor = crypto_bignum_init(); ++ if (!cofactor || crypto_ec_cofactor(group->group, cofactor) < 0) { ++ wpa_printf(MSG_INFO, ++ "EAP-pwd: Unable to get cofactor for curve"); ++ goto fail; ++ } ++ ++ if (!crypto_bignum_is_one(cofactor)) { ++ struct crypto_ec_point *point; ++ int ok = 1; ++ ++ /* check to ensure peer's element is not in a small sub-group */ ++ point = crypto_ec_point_init(group->group); ++ if (!point || ++ crypto_ec_point_mul(group->group, element, ++ cofactor, point) != 0 || ++ crypto_ec_point_is_at_infinity(group->group, point)) ++ ok = 0; ++ crypto_ec_point_deinit(point, 0); ++ ++ if (!ok) { ++ wpa_printf(MSG_INFO, ++ "EAP-pwd: Small sub-group check on peer element failed"); ++ goto fail; ++ } ++ } ++ ++out: ++ crypto_bignum_deinit(cofactor, 0); ++ return element; ++fail: ++ crypto_ec_point_deinit(element, 0); ++ element = NULL; ++ goto out; ++} ++ ++ ++struct crypto_bignum * eap_pwd_get_scalar(EAP_PWD_group *group, const u8 *buf) ++{ ++ struct crypto_bignum *scalar; ++ const struct crypto_bignum *order; ++ size_t order_len; ++ ++ order = crypto_ec_get_order(group->group); ++ order_len = crypto_ec_order_len(group->group); ++ ++ /* RFC 5931, 2.8.5.2: 1 < scalar < r */ ++ scalar = crypto_bignum_init_set(buf, order_len); ++ if (!scalar || crypto_bignum_is_zero(scalar) || ++ crypto_bignum_is_one(scalar) || ++ crypto_bignum_cmp(scalar, order) >= 0) { ++ wpa_printf(MSG_INFO, "EAP-pwd: received scalar is invalid"); ++ crypto_bignum_deinit(scalar, 0); ++ scalar = NULL; ++ } ++ ++ return scalar; ++} +--- a/src/eap_common/eap_pwd_common.h ++++ b/src/eap_common/eap_pwd_common.h +@@ -67,5 +67,8 @@ int compute_keys(EAP_PWD_group *grp, con + struct crypto_hash * eap_pwd_h_init(void); + void eap_pwd_h_update(struct crypto_hash *hash, const u8 *data, size_t len); + void eap_pwd_h_final(struct crypto_hash *hash, u8 *digest); ++struct crypto_ec_point * eap_pwd_get_element(EAP_PWD_group *group, ++ const u8 *buf); ++struct crypto_bignum * eap_pwd_get_scalar(EAP_PWD_group *group, const u8 *buf); + + #endif /* EAP_PWD_COMMON_H */ +--- a/src/eap_peer/eap_pwd.c ++++ b/src/eap_peer/eap_pwd.c +@@ -308,7 +308,7 @@ eap_pwd_perform_commit_exchange(struct e + const struct wpabuf *reqData, + const u8 *payload, size_t payload_len) + { +- struct crypto_ec_point *K = NULL, *point = NULL; ++ struct crypto_ec_point *K = NULL; + struct crypto_bignum *mask = NULL, *cofactor = NULL; + const u8 *ptr = payload; + u8 *scalar = NULL, *element = NULL; +@@ -572,63 +572,27 @@ eap_pwd_perform_commit_exchange(struct e + /* process the request */ + data->k = crypto_bignum_init(); + K = crypto_ec_point_init(data->grp->group); +- point = crypto_ec_point_init(data->grp->group); +- if (!data->k || !K || !point) { ++ if (!data->k || !K) { + wpa_printf(MSG_INFO, "EAP-PWD (peer): peer data allocation " + "fail"); + goto fin; + } + + /* element, x then y, followed by scalar */ +- data->server_element = crypto_ec_point_from_bin(data->grp->group, ptr); ++ data->server_element = eap_pwd_get_element(data->grp, ptr); + if (!data->server_element) { + wpa_printf(MSG_INFO, "EAP-PWD (peer): setting peer element " + "fail"); + goto fin; + } + ptr += prime_len * 2; +- data->server_scalar = crypto_bignum_init_set(ptr, order_len); ++ data->server_scalar = eap_pwd_get_scalar(data->grp, ptr); + if (!data->server_scalar) { + wpa_printf(MSG_INFO, + "EAP-PWD (peer): setting peer scalar fail"); + goto fin; + } + +- /* verify received scalar */ +- if (crypto_bignum_is_zero(data->server_scalar) || +- crypto_bignum_is_one(data->server_scalar) || +- crypto_bignum_cmp(data->server_scalar, +- crypto_ec_get_order(data->grp->group)) >= 0) { +- wpa_printf(MSG_INFO, +- "EAP-PWD (peer): received scalar is invalid"); +- goto fin; +- } +- +- /* verify received element */ +- if (!crypto_ec_point_is_on_curve(data->grp->group, +- data->server_element) || +- crypto_ec_point_is_at_infinity(data->grp->group, +- data->server_element)) { +- wpa_printf(MSG_INFO, +- "EAP-PWD (peer): received element is invalid"); +- goto fin; +- } +- +- /* check to ensure server's element is not in a small sub-group */ +- if (!crypto_bignum_is_one(cofactor)) { +- if (crypto_ec_point_mul(data->grp->group, data->server_element, +- cofactor, point) < 0) { +- wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply " +- "server element by order!\n"); +- goto fin; +- } +- if (crypto_ec_point_is_at_infinity(data->grp->group, point)) { +- wpa_printf(MSG_INFO, "EAP-PWD (peer): server element " +- "is at infinity!\n"); +- goto fin; +- } +- } +- + /* compute the shared key, k */ + if (crypto_ec_point_mul(data->grp->group, data->grp->pwe, + data->server_scalar, K) < 0 || +@@ -702,7 +666,6 @@ fin: + crypto_bignum_deinit(mask, 1); + crypto_bignum_deinit(cofactor, 1); + crypto_ec_point_deinit(K, 1); +- crypto_ec_point_deinit(point, 1); + if (data->outbuf == NULL) + eap_pwd_state(data, FAILURE); + else +--- a/src/eap_server/eap_server_pwd.c ++++ b/src/eap_server/eap_server_pwd.c +@@ -669,7 +669,7 @@ eap_pwd_process_commit_resp(struct eap_s + { + const u8 *ptr; + struct crypto_bignum *cofactor = NULL; +- struct crypto_ec_point *K = NULL, *point = NULL; ++ struct crypto_ec_point *K = NULL; + int res = 0; + size_t prime_len, order_len; + +@@ -688,9 +688,8 @@ eap_pwd_process_commit_resp(struct eap_s + + data->k = crypto_bignum_init(); + cofactor = crypto_bignum_init(); +- point = crypto_ec_point_init(data->grp->group); + K = crypto_ec_point_init(data->grp->group); +- if (!data->k || !cofactor || !point || !K) { ++ if (!data->k || !cofactor || !K) { + wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation " + "fail"); + goto fin; +@@ -704,55 +703,20 @@ eap_pwd_process_commit_resp(struct eap_s + + /* element, x then y, followed by scalar */ + ptr = payload; +- data->peer_element = crypto_ec_point_from_bin(data->grp->group, ptr); ++ data->peer_element = eap_pwd_get_element(data->grp, ptr); + if (!data->peer_element) { + wpa_printf(MSG_INFO, "EAP-PWD (server): setting peer element " + "fail"); + goto fin; + } + ptr += prime_len * 2; +- data->peer_scalar = crypto_bignum_init_set(ptr, order_len); ++ data->peer_scalar = eap_pwd_get_scalar(data->grp, ptr); + if (!data->peer_scalar) { + wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation " + "fail"); + goto fin; + } + +- /* verify received scalar */ +- if (crypto_bignum_is_zero(data->peer_scalar) || +- crypto_bignum_is_one(data->peer_scalar) || +- crypto_bignum_cmp(data->peer_scalar, +- crypto_ec_get_order(data->grp->group)) >= 0) { +- wpa_printf(MSG_INFO, +- "EAP-PWD (server): received scalar is invalid"); +- goto fin; +- } +- +- /* verify received element */ +- if (!crypto_ec_point_is_on_curve(data->grp->group, +- data->peer_element) || +- crypto_ec_point_is_at_infinity(data->grp->group, +- data->peer_element)) { +- wpa_printf(MSG_INFO, +- "EAP-PWD (server): received element is invalid"); +- goto fin; +- } +- +- /* check to ensure peer's element is not in a small sub-group */ +- if (!crypto_bignum_is_one(cofactor)) { +- if (crypto_ec_point_mul(data->grp->group, data->peer_element, +- cofactor, point) != 0) { +- wpa_printf(MSG_INFO, "EAP-PWD (server): cannot " +- "multiply peer element by order"); +- goto fin; +- } +- if (crypto_ec_point_is_at_infinity(data->grp->group, point)) { +- wpa_printf(MSG_INFO, "EAP-PWD (server): peer element " +- "is at infinity!\n"); +- goto fin; +- } +- } +- + /* detect reflection attacks */ + if (crypto_bignum_cmp(data->my_scalar, data->peer_scalar) == 0 || + crypto_ec_point_cmp(data->grp->group, data->my_element, +@@ -804,7 +768,6 @@ eap_pwd_process_commit_resp(struct eap_s + + fin: + crypto_ec_point_deinit(K, 1); +- crypto_ec_point_deinit(point, 1); + crypto_bignum_deinit(cofactor, 1); + + if (res) |