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;
+}
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 */
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;
/* 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 ||
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
{
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;
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;
/* 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,
fin:
crypto_ec_point_deinit(K, 1);
- crypto_ec_point_deinit(point, 1);
crypto_bignum_deinit(cofactor, 1);
if (res)