hostapd: fix CVE-2019-9497, CVE-2019-9498, CVE-2019-9499
authorStefan Lippers-Hollmann <s.l-h@gmx.de>
Thu, 11 Apr 2019 00:57:09 +0000 (02:57 +0200)
committerJo-Philipp Wich <jo@mein.io>
Thu, 11 Apr 2019 09:26:01 +0000 (11:26 +0200)
EAP-pwd missing commit validation

Published: April 10, 2019
Identifiers:
- CVE-2019-9497 (EAP-pwd server not checking for reflection attack)
- CVE-2019-9498 (EAP-pwd server missing commit validation for
  scalar/element)
- CVE-2019-9499 (EAP-pwd peer missing commit validation for
  scalar/element)

Latest version available from: https://w1.fi/security/2019-4/

Vulnerability

EAP-pwd implementation in hostapd (EAP server) and wpa_supplicant (EAP
peer) was discovered not to validate the received scalar and element
values in EAP-pwd-Commit messages properly. This could result in attacks
that would be able to complete EAP-pwd authentication exchange without
the attacker having to know the used password.

A reflection attack is possible against the EAP-pwd server since the
hostapd EAP server did not verify that the EAP-pwd-Commit contains
scalar/element values that differ from the ones the server sent out
itself. This allows the attacker to complete EAP-pwd authentication
without knowing the password, but this does not result in the attacker
being able to derive the session key (MSK), i.e., the attacker would not
be able to complete the following key exchange (e.g., 4-way handshake in
RSN/WPA).

An attack using invalid scalar/element values is possible against both
the EAP-pwd server and peer since hostapd and wpa_supplicant did not
validate these values in the received EAP-pwd-Commit messages. If the
used crypto library does not implement additional checks for the element
(EC point), this could result in attacks where the attacker could use a
specially crafted commit message values to manipulate the exchange to
result in deriving a session key value from a very small set of possible
values. This could further be used to attack the EAP-pwd server in a
practical manner. An attack against the EAP-pwd peer is slightly more
complex, but still consider practical. These invalid scalar/element
attacks could result in the attacker being able to complete
authentication and learn the session key and MSK to allow the key
exchange to be completed as well, i.e., the attacker gaining access to
the network in case of the attack against the EAP server or the attacker
being able to operate a rogue AP in case of the attack against the EAP
peer.

While similar attacks might be applicable against SAE, it should be
noted that the SAE implementation in hostapd and wpa_supplicant does
have the validation steps that were missing from the EAP-pwd
implementation and as such, these attacks do not apply to the current
SAE implementation. Old versions of wpa_supplicant/hostapd did not
include the reflection attack check in the SAE implementation, though,
since that was added in June 2015 for v2.5 (commit 6a58444d27fd 'SAE:
Verify that own/peer commit-scalar and COMMIT-ELEMENT are different').

Vulnerable versions/configurations

All hostapd versions with EAP-pwd support (CONFIG_EAP_PWD=y in the build
configuration and EAP-pwd being enabled in the runtime configuration)
are vulnerable against the reflection attack.

All wpa_supplicant and hostapd versions with EAP-pwd support
(CONFIG_EAP_PWD=y in the build configuration and EAP-pwd being enabled
in the runtime configuration) are vulnerable against the invalid
scalar/element attack when built against a crypto library that does not
have an explicit validation step on imported EC points. The following
list indicates which cases are vulnerable/not vulnerable:
- OpenSSL v1.0.2 or older: vulnerable
- OpenSSL v1.1.0 or newer: not vulnerable
- BoringSSL with commit 38feb990a183 ('Require that EC points are on the
  curve.') from September 2015: not vulnerable
- BoringSSL without commit 38feb990a183: vulnerable
- LibreSSL: vulnerable
- wolfssl: vulnerable

Acknowledgments

Thanks to Mathy Vanhoef (New York University Abu Dhabi) for discovering
and reporting the issues and for proposing changes to address them in
the implementation.

Possible mitigation steps

- Merge the following commits to wpa_supplicant/hostapd and rebuild:

  CVE-2019-9497:
  EAP-pwd server: Detect reflection attacks

  CVE-2019-9498:
  EAP-pwd server: Verify received scalar and element
  EAP-pwd: Check element x,y coordinates explicitly

  CVE-2019-9499:
  EAP-pwd client: Verify received scalar and element
  EAP-pwd: Check element x,y coordinates explicitly

  These patches are available from https://w1.fi/security/2019-4/

- Update to wpa_supplicant/hostapd v2.8 or newer, once available

Signed-off-by: Stefan Lippers-Hollmann <s.l-h@gmx.de>
[bump PKG_RELEASE]
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
package/network/services/hostapd/Makefile
package/network/services/hostapd/patches/064-0011-EAP-pwd-server-Verify-received-scalar-and-element.patch [new file with mode: 0644]
package/network/services/hostapd/patches/064-0012-EAP-pwd-server-Detect-reflection-attacks.patch [new file with mode: 0644]
package/network/services/hostapd/patches/064-0013-EAP-pwd-client-Verify-received-scalar-and-element.patch [new file with mode: 0644]
package/network/services/hostapd/patches/064-0014-EAP-pwd-Check-element-x-y-coordinates-explicitly.patch [new file with mode: 0644]

index 6308dca..235f178 100644 (file)
@@ -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 (file)
index 0000000..8ecb5fd
--- /dev/null
@@ -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 (file)
index 0000000..44949cb
--- /dev/null
@@ -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 (file)
index 0000000..9c7707a
--- /dev/null
@@ -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 (file)
index 0000000..ab1edfa
--- /dev/null
@@ -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)