Merge ~awe/snappy-hwe-snaps/+git/wpa-supplicant:2.4-cve-updates into ~snappy-hwe-team/snappy-hwe-snaps/+git/wpa-supplicant:wpa-supplicant/xenial/2.4

Proposed by Tony Espy
Status: Merged
Approved by: Alfonso Sanchez-Beato
Approved revision: b0b72d1358e43c2226e70a38ea1a8ed2496d55a3
Merged at revision: 1861ee9275d251111c3fd6435cdf26ab6c1d3e1f
Proposed branch: ~awe/snappy-hwe-snaps/+git/wpa-supplicant:2.4-cve-updates
Merge into: ~snappy-hwe-team/snappy-hwe-snaps/+git/wpa-supplicant:wpa-supplicant/xenial/2.4
Diff against target: 2849 lines (+1134/-618)
23 files modified
hostapd/Android.mk (+1/-0)
hostapd/Makefile (+1/-0)
src/ap/wps_hostapd.c (+2/-1)
src/crypto/crypto.h (+87/-0)
src/crypto/crypto_openssl.c (+140/-5)
src/eap_common/eap_pwd_common.c (+333/-144)
src/eap_common/eap_pwd_common.h (+11/-10)
src/eap_peer/eap_pwd.c (+122/-213)
src/eap_server/eap_server_pwd.c (+131/-227)
src/rsn_supp/wpa.c (+11/-0)
src/utils/common.c (+23/-0)
src/utils/common.h (+2/-0)
src/utils/const_time.h (+191/-0)
src/wps/wps.h (+1/-1)
src/wps/wps_attr_process.c (+10/-0)
src/wps/wps_common.c (+5/-7)
wpa_supplicant/Android.mk (+1/-0)
wpa_supplicant/Makefile (+1/-0)
wpa_supplicant/ap.c (+6/-2)
wpa_supplicant/config.c (+33/-3)
wpa_supplicant/ctrl_iface.c (+2/-1)
wpa_supplicant/p2p_supplicant.c (+16/-3)
wpa_supplicant/wps_supplicant.c (+4/-1)
Reviewer Review Type Date Requested Status
Alfonso Sanchez-Beato Approve
System Enablement Bot continuous-integration Approve
Review via email: mp+369190@code.launchpad.net

Description of the change

This merge proposal brings the wpa-supplicant snap up-to-date with respect to CVEs as compared to the latest Debian package in xenial-updates and xenial-security (2.4-0ubuntu6.5).

Note I skipped the patches from /2017-1/, as these were the Krack attack patches and they'd been merged directly from upstream instead of being pulled from 2.4-0ubuntu6.2. I did not verify that the krack fixes that
landed in this tree *exactly* matched the patches from 2.4-0ubuntu6.2 though. I tried to apply the first patch in the directory /debian/patches/2017-1/ and it failed to apply, so I assumed all of those patches had been applied.

Finally there are two commits in this merge proposal which apply on to EAP server, however as later patches included changes to the client and the server, it was just easier to leave these server-only patches in the sequence.

To post a comment you must log in.
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote :

LGTM, thanks! As I suggested in https://trello.com/c/5SeKC9JO/119-wpa-supplicant , the next step would be to create an MP for master to reflect the changes in the ChangeLog and trigger any spread tests.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 6fcefdd..47dcb77 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -382,6 +382,7 @@ ifdef CONFIG_EAP_PWD
382L_CFLAGS += -DEAP_SERVER_PWD382L_CFLAGS += -DEAP_SERVER_PWD
383OBJS += src/eap_server/eap_server_pwd.c src/eap_common/eap_pwd_common.c383OBJS += src/eap_server/eap_server_pwd.c src/eap_common/eap_pwd_common.c
384NEED_SHA256=y384NEED_SHA256=y
385NEED_ECC=y
385endif386endif
386387
387ifdef CONFIG_EAP_EKE388ifdef CONFIG_EAP_EKE
diff --git a/hostapd/Makefile b/hostapd/Makefile
index eace68c..c6f70cd 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -377,6 +377,7 @@ ifdef CONFIG_EAP_PWD
377CFLAGS += -DEAP_SERVER_PWD377CFLAGS += -DEAP_SERVER_PWD
378OBJS += ../src/eap_server/eap_server_pwd.o ../src/eap_common/eap_pwd_common.o378OBJS += ../src/eap_server/eap_server_pwd.o ../src/eap_common/eap_pwd_common.o
379NEED_SHA256=y379NEED_SHA256=y
380NEED_ECC=y
380endif381endif
381382
382ifdef CONFIG_EAP_EKE383ifdef CONFIG_EAP_EKE
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index b0e8b0b..d5ca84d 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -1561,7 +1561,8 @@ const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout)
1561 unsigned int pin;1561 unsigned int pin;
1562 struct wps_ap_pin_data data;1562 struct wps_ap_pin_data data;
15631563
1564 pin = wps_generate_pin();1564 if (wps_generate_pin(&pin) < 0)
1565 return NULL;
1565 os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%08u", pin);1566 os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%08u", pin);
1566 data.timeout = timeout;1567 data.timeout = timeout;
1567 hostapd_wps_for_each(hapd, wps_ap_pin_set, &data);1568 hostapd_wps_for_each(hapd, wps_ap_pin_set, &data);
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index f2d5662..c7cb090 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -391,6 +391,13 @@ int __must_check crypto_public_key_decrypt_pkcs1(
391 struct crypto_public_key *key, const u8 *crypt, size_t crypt_len,391 struct crypto_public_key *key, const u8 *crypt, size_t crypt_len,
392 u8 *plain, size_t *plain_len);392 u8 *plain, size_t *plain_len);
393393
394int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
395 u8 *pubkey);
396int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
397 const u8 *privkey, size_t privkey_len,
398 const u8 *pubkey, size_t pubkey_len,
399 u8 *secret, size_t *len);
400
394/**401/**
395 * crypto_global_init - Initialize crypto wrapper402 * crypto_global_init - Initialize crypto wrapper
396 *403 *
@@ -503,6 +510,14 @@ int crypto_bignum_to_bin(const struct crypto_bignum *a,
503 u8 *buf, size_t buflen, size_t padlen);510 u8 *buf, size_t buflen, size_t padlen);
504511
505/**512/**
513 * crypto_bignum_rand - Create a random number in range of modulus
514 * @r: Bignum; set to a random value
515 * @m: Bignum; modulus
516 * Returns: 0 on success, -1 on failure
517 */
518int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m);
519
520/**
506 * crypto_bignum_add - c = a + b521 * crypto_bignum_add - c = a + b
507 * @a: Bignum522 * @a: Bignum
508 * @b: Bignum523 * @b: Bignum
@@ -584,6 +599,16 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a,
584 struct crypto_bignum *d);599 struct crypto_bignum *d);
585600
586/**601/**
602 * crypto_bignum_rshift - r = a >> n
603 * @a: Bignum
604 * @n: Number of bits
605 * @r: Bignum; used to store the result of a >> n
606 * Returns: 0 on success, -1 on failure
607 */
608int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
609 struct crypto_bignum *r);
610
611/**
587 * crypto_bignum_cmp - Compare two bignums612 * crypto_bignum_cmp - Compare two bignums
588 * @a: Bignum613 * @a: Bignum
589 * @b: Bignum614 * @b: Bignum
@@ -614,6 +639,22 @@ int crypto_bignum_is_zero(const struct crypto_bignum *a);
614int crypto_bignum_is_one(const struct crypto_bignum *a);639int crypto_bignum_is_one(const struct crypto_bignum *a);
615640
616/**641/**
642 * crypto_bignum_is_odd - Is the given bignum odd
643 * @a: Bignum
644 * Returns: 1 if @a is odd or 0 if not
645 */
646int crypto_bignum_is_odd(const struct crypto_bignum *a);
647
648/**
649 * crypto_bignum_legendre - Compute the Legendre symbol (a/p)
650 * @a: Bignum
651 * @p: Bignum
652 * Returns: Legendre symbol -1,0,1 on success; -2 on calculation failure
653 */
654int crypto_bignum_legendre(const struct crypto_bignum *a,
655 const struct crypto_bignum *p);
656
657/**
617 * struct crypto_ec - Elliptic curve context658 * struct crypto_ec - Elliptic curve context
618 *659 *
619 * Internal data structure for EC implementation. The contents is specific660 * Internal data structure for EC implementation. The contents is specific
@@ -636,6 +677,14 @@ struct crypto_ec * crypto_ec_init(int group);
636void crypto_ec_deinit(struct crypto_ec *e);677void crypto_ec_deinit(struct crypto_ec *e);
637678
638/**679/**
680 * crypto_ec_cofactor - Set the cofactor into the big number
681 * @e: EC context from crypto_ec_init()
682 * @cofactor: Cofactor of curve.
683 * Returns: 0 on success, -1 on failure
684 */
685int crypto_ec_cofactor(struct crypto_ec *e, struct crypto_bignum *cofactor);
686
687/**
639 * crypto_ec_prime_len - Get length of the prime in octets688 * crypto_ec_prime_len - Get length of the prime in octets
640 * @e: EC context from crypto_ec_init()689 * @e: EC context from crypto_ec_init()
641 * Returns: Length of the prime defining the group690 * Returns: Length of the prime defining the group
@@ -650,6 +699,13 @@ size_t crypto_ec_prime_len(struct crypto_ec *e);
650size_t crypto_ec_prime_len_bits(struct crypto_ec *e);699size_t crypto_ec_prime_len_bits(struct crypto_ec *e);
651700
652/**701/**
702 * crypto_ec_order_len - Get length of the order in octets
703 * @e: EC context from crypto_ec_init()
704 * Returns: Length of the order defining the group
705 */
706size_t crypto_ec_order_len(struct crypto_ec *e);
707
708/**
653 * crypto_ec_get_prime - Get prime defining an EC group709 * crypto_ec_get_prime - Get prime defining an EC group
654 * @e: EC context from crypto_ec_init()710 * @e: EC context from crypto_ec_init()
655 * Returns: Prime (bignum) defining the group711 * Returns: Prime (bignum) defining the group
@@ -686,6 +742,16 @@ struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e);
686void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear);742void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear);
687743
688/**744/**
745 * crypto_ec_point_x - Copies the x-ordinate point into big number
746 * @e: EC context from crypto_ec_init()
747 * @p: EC point data
748 * @x: Big number to set to the copy of x-ordinate
749 * Returns: 0 on success, -1 on failure
750 */
751int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p,
752 struct crypto_bignum *x);
753
754/**
689 * crypto_ec_point_to_bin - Write EC point value as binary data755 * crypto_ec_point_to_bin - Write EC point value as binary data
690 * @e: EC context from crypto_ec_init()756 * @e: EC context from crypto_ec_init()
691 * @p: EC point data from crypto_ec_point_init()757 * @p: EC point data from crypto_ec_point_init()
@@ -758,6 +824,16 @@ int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
758 const struct crypto_bignum *x, int y_bit);824 const struct crypto_bignum *x, int y_bit);
759825
760/**826/**
827 * crypto_ec_point_compute_y_sqr - Compute y^2 = x^3 + ax + b
828 * @e: EC context from crypto_ec_init()
829 * @x: x coordinate
830 * Returns: y^2 on success, %NULL failure
831 */
832struct crypto_bignum *
833crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
834 const struct crypto_bignum *x);
835
836/**
761 * crypto_ec_point_is_at_infinity - Check whether EC point is neutral element837 * crypto_ec_point_is_at_infinity - Check whether EC point is neutral element
762 * @e: EC context from crypto_ec_init()838 * @e: EC context from crypto_ec_init()
763 * @p: EC point839 * @p: EC point
@@ -776,4 +852,15 @@ int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
776int crypto_ec_point_is_on_curve(struct crypto_ec *e,852int crypto_ec_point_is_on_curve(struct crypto_ec *e,
777 const struct crypto_ec_point *p);853 const struct crypto_ec_point *p);
778854
855/**
856 * crypto_ec_point_cmp - Compare two EC points
857 * @e: EC context from crypto_ec_init()
858 * @a: EC point
859 * @b: EC point
860 * Returns: 0 on equal, non-zero otherwise
861 */
862int crypto_ec_point_cmp(const struct crypto_ec *e,
863 const struct crypto_ec_point *a,
864 const struct crypto_ec_point *b);
865
779#endif /* CRYPTO_H */866#endif /* CRYPTO_H */
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index f158ef4..0b57a6a 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -24,6 +24,7 @@
24#endif /* CONFIG_ECC */24#endif /* CONFIG_ECC */
2525
26#include "common.h"26#include "common.h"
27#include "utils/const_time.h"
27#include "wpabuf.h"28#include "wpabuf.h"
28#include "dh_group5.h"29#include "dh_group5.h"
29#include "sha1.h"30#include "sha1.h"
@@ -346,7 +347,8 @@ int crypto_mod_exp(const u8 *base, size_t base_len,
346 bn_result == NULL)347 bn_result == NULL)
347 goto error;348 goto error;
348349
349 if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1)350 if (BN_mod_exp_mont_consttime(bn_result, bn_base, bn_exp, bn_modulus,
351 ctx, NULL) != 1)
350 goto error;352 goto error;
351353
352 *result_len = BN_bn2bin(bn_result, result);354 *result_len = BN_bn2bin(bn_result, result);
@@ -920,6 +922,12 @@ int crypto_bignum_to_bin(const struct crypto_bignum *a,
920}922}
921923
922924
925int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
926{
927 return BN_rand_range((BIGNUM *) r, (const BIGNUM *) m) == 1 ? 0 : -1;
928}
929
930
923int crypto_bignum_add(const struct crypto_bignum *a,931int crypto_bignum_add(const struct crypto_bignum *a,
924 const struct crypto_bignum *b,932 const struct crypto_bignum *b,
925 struct crypto_bignum *c)933 struct crypto_bignum *c)
@@ -958,8 +966,9 @@ int crypto_bignum_exptmod(const struct crypto_bignum *a,
958 bnctx = BN_CTX_new();966 bnctx = BN_CTX_new();
959 if (bnctx == NULL)967 if (bnctx == NULL)
960 return -1;968 return -1;
961 res = BN_mod_exp((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,969 res = BN_mod_exp_mont_consttime((BIGNUM *) d, (const BIGNUM *) a,
962 (const BIGNUM *) c, bnctx);970 (const BIGNUM *) b, (const BIGNUM *) c,
971 bnctx, NULL);
963 BN_CTX_free(bnctx);972 BN_CTX_free(bnctx);
964973
965 return res ? 0 : -1;974 return res ? 0 : -1;
@@ -976,6 +985,11 @@ int crypto_bignum_inverse(const struct crypto_bignum *a,
976 bnctx = BN_CTX_new();985 bnctx = BN_CTX_new();
977 if (bnctx == NULL)986 if (bnctx == NULL)
978 return -1;987 return -1;
988#ifdef OPENSSL_IS_BORINGSSL
989 /* TODO: use BN_mod_inverse_blinded() ? */
990#else /* OPENSSL_IS_BORINGSSL */
991 BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME);
992#endif /* OPENSSL_IS_BORINGSSL */
979 res = BN_mod_inverse((BIGNUM *) c, (const BIGNUM *) a,993 res = BN_mod_inverse((BIGNUM *) c, (const BIGNUM *) a,
980 (const BIGNUM *) b, bnctx);994 (const BIGNUM *) b, bnctx);
981 BN_CTX_free(bnctx);995 BN_CTX_free(bnctx);
@@ -1004,6 +1018,9 @@ int crypto_bignum_div(const struct crypto_bignum *a,
1004 bnctx = BN_CTX_new();1018 bnctx = BN_CTX_new();
1005 if (bnctx == NULL)1019 if (bnctx == NULL)
1006 return -1;1020 return -1;
1021#ifndef OPENSSL_IS_BORINGSSL
1022 BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME);
1023#endif /* OPENSSL_IS_BORINGSSL */
1007 res = BN_div((BIGNUM *) c, NULL, (const BIGNUM *) a,1024 res = BN_div((BIGNUM *) c, NULL, (const BIGNUM *) a,
1008 (const BIGNUM *) b, bnctx);1025 (const BIGNUM *) b, bnctx);
1009 BN_CTX_free(bnctx);1026 BN_CTX_free(bnctx);
@@ -1032,6 +1049,15 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a,
1032}1049}
10331050
10341051
1052int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
1053 struct crypto_bignum *r)
1054{
1055 /* Note: BN_rshift() does not modify the first argument even though it
1056 * has not been marked const. */
1057 return BN_rshift((BIGNUM *) a, (BIGNUM *) r, n) == 1 ? 0 : -1;
1058}
1059
1060
1035int crypto_bignum_cmp(const struct crypto_bignum *a,1061int crypto_bignum_cmp(const struct crypto_bignum *a,
1036 const struct crypto_bignum *b)1062 const struct crypto_bignum *b)
1037{1063{
@@ -1057,6 +1083,50 @@ int crypto_bignum_is_one(const struct crypto_bignum *a)
1057}1083}
10581084
10591085
1086int crypto_bignum_is_odd(const struct crypto_bignum *a)
1087{
1088 return BN_is_odd((const BIGNUM *) a);
1089}
1090
1091
1092int crypto_bignum_legendre(const struct crypto_bignum *a,
1093 const struct crypto_bignum *p)
1094{
1095 BN_CTX *bnctx;
1096 BIGNUM *exp = NULL, *tmp = NULL;
1097 int res = -2;
1098 unsigned int mask;
1099
1100 bnctx = BN_CTX_new();
1101 if (bnctx == NULL)
1102 return -2;
1103
1104 exp = BN_new();
1105 tmp = BN_new();
1106 if (!exp || !tmp ||
1107 /* exp = (p-1) / 2 */
1108 !BN_sub(exp, (const BIGNUM *) p, BN_value_one()) ||
1109 !BN_rshift1(exp, exp) ||
1110 !BN_mod_exp_mont_consttime(tmp, (const BIGNUM *) a, exp,
1111 (const BIGNUM *) p, bnctx, NULL))
1112 goto fail;
1113
1114 /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need to use
1115 * constant time selection to avoid branches here. */
1116 res = -1;
1117 mask = const_time_eq(BN_is_word(tmp, 1), 1);
1118 res = const_time_select_int(mask, 1, res);
1119 mask = const_time_eq(BN_is_zero(tmp), 1);
1120 res = const_time_select_int(mask, 0, res);
1121
1122fail:
1123 BN_clear_free(tmp);
1124 BN_clear_free(exp);
1125 BN_CTX_free(bnctx);
1126 return res;
1127}
1128
1129
1060#ifdef CONFIG_ECC1130#ifdef CONFIG_ECC
10611131
1062struct crypto_ec {1132struct crypto_ec {
@@ -1064,6 +1134,8 @@ struct crypto_ec {
1064 BN_CTX *bnctx;1134 BN_CTX *bnctx;
1065 BIGNUM *prime;1135 BIGNUM *prime;
1066 BIGNUM *order;1136 BIGNUM *order;
1137 BIGNUM *a;
1138 BIGNUM *b;
1067};1139};
10681140
1069struct crypto_ec * crypto_ec_init(int group)1141struct crypto_ec * crypto_ec_init(int group)
@@ -1100,9 +1172,11 @@ struct crypto_ec * crypto_ec_init(int group)
1100 e->group = EC_GROUP_new_by_curve_name(nid);1172 e->group = EC_GROUP_new_by_curve_name(nid);
1101 e->prime = BN_new();1173 e->prime = BN_new();
1102 e->order = BN_new();1174 e->order = BN_new();
1175 e->a = BN_new();
1176 e->b = BN_new();
1103 if (e->group == NULL || e->bnctx == NULL || e->prime == NULL ||1177 if (e->group == NULL || e->bnctx == NULL || e->prime == NULL ||
1104 e->order == NULL ||1178 e->order == NULL || e->a == NULL || e->b == NULL ||
1105 !EC_GROUP_get_curve_GFp(e->group, e->prime, NULL, NULL, e->bnctx) ||1179 !EC_GROUP_get_curve_GFp(e->group, e->prime, e->a, e->b, e->bnctx) ||
1106 !EC_GROUP_get_order(e->group, e->order, e->bnctx)) {1180 !EC_GROUP_get_order(e->group, e->order, e->bnctx)) {
1107 crypto_ec_deinit(e);1181 crypto_ec_deinit(e);
1108 e = NULL;1182 e = NULL;
@@ -1116,6 +1190,8 @@ void crypto_ec_deinit(struct crypto_ec *e)
1116{1190{
1117 if (e == NULL)1191 if (e == NULL)
1118 return;1192 return;
1193 BN_clear_free(e->b);
1194 BN_clear_free(e->a);
1119 BN_clear_free(e->order);1195 BN_clear_free(e->order);
1120 BN_clear_free(e->prime);1196 BN_clear_free(e->prime);
1121 EC_GROUP_free(e->group);1197 EC_GROUP_free(e->group);
@@ -1124,6 +1200,13 @@ void crypto_ec_deinit(struct crypto_ec *e)
1124}1200}
11251201
11261202
1203int crypto_ec_cofactor(struct crypto_ec *e, struct crypto_bignum *cofactor)
1204{
1205 return EC_GROUP_get_cofactor(e->group, (BIGNUM *) cofactor,
1206 e->bnctx) == 0 ? -1 : 0;
1207}
1208
1209
1127struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e)1210struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e)
1128{1211{
1129 if (e == NULL)1212 if (e == NULL)
@@ -1144,6 +1227,12 @@ size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
1144}1227}
11451228
11461229
1230size_t crypto_ec_order_len(struct crypto_ec *e)
1231{
1232 return BN_num_bytes(e->order);
1233}
1234
1235
1147const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e)1236const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e)
1148{1237{
1149 return (const struct crypto_bignum *) e->prime;1238 return (const struct crypto_bignum *) e->prime;
@@ -1165,6 +1254,16 @@ void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
1165}1254}
11661255
11671256
1257int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p,
1258 struct crypto_bignum *x)
1259{
1260 return EC_POINT_get_affine_coordinates_GFp(e->group,
1261 (const EC_POINT *) p,
1262 (BIGNUM *) x, NULL,
1263 e->bnctx) == 1 ? 0 : -1;
1264}
1265
1266
1168int crypto_ec_point_to_bin(struct crypto_ec *e,1267int crypto_ec_point_to_bin(struct crypto_ec *e,
1169 const struct crypto_ec_point *point, u8 *x, u8 *y)1268 const struct crypto_ec_point *point, u8 *x, u8 *y)
1170{1269{
@@ -1263,6 +1362,33 @@ int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
1263}1362}
12641363
12651364
1365struct crypto_bignum *
1366crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
1367 const struct crypto_bignum *x)
1368{
1369 BIGNUM *tmp, *tmp2, *y_sqr = NULL;
1370
1371 tmp = BN_new();
1372 tmp2 = BN_new();
1373
1374 /* y^2 = x^3 + ax + b */
1375 if (tmp && tmp2 &&
1376 BN_mod_sqr(tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
1377 BN_mod_mul(tmp, tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
1378 BN_mod_mul(tmp2, e->a, (const BIGNUM *) x, e->prime, e->bnctx) &&
1379 BN_mod_add_quick(tmp2, tmp2, tmp, e->prime) &&
1380 BN_mod_add_quick(tmp2, tmp2, e->b, e->prime)) {
1381 y_sqr = tmp2;
1382 tmp2 = NULL;
1383 }
1384
1385 BN_clear_free(tmp);
1386 BN_clear_free(tmp2);
1387
1388 return (struct crypto_bignum *) y_sqr;
1389}
1390
1391
1266int crypto_ec_point_is_at_infinity(struct crypto_ec *e,1392int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
1267 const struct crypto_ec_point *p)1393 const struct crypto_ec_point *p)
1268{1394{
@@ -1276,4 +1402,13 @@ int crypto_ec_point_is_on_curve(struct crypto_ec *e,
1276 return EC_POINT_is_on_curve(e->group, (const EC_POINT *) p, e->bnctx);1402 return EC_POINT_is_on_curve(e->group, (const EC_POINT *) p, e->bnctx);
1277}1403}
12781404
1405
1406int crypto_ec_point_cmp(const struct crypto_ec *e,
1407 const struct crypto_ec_point *a,
1408 const struct crypto_ec_point *b)
1409{
1410 return EC_POINT_cmp(e->group, (const EC_POINT *) a,
1411 (const EC_POINT *) b, e->bnctx);
1412}
1413
1279#endif /* CONFIG_ECC */1414#endif /* CONFIG_ECC */
diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
index 631c363..cace4a4 100644
--- a/src/eap_common/eap_pwd_common.c
+++ b/src/eap_common/eap_pwd_common.c
@@ -8,11 +8,15 @@
88
9#include "includes.h"9#include "includes.h"
10#include "common.h"10#include "common.h"
11#include "utils/const_time.h"
11#include "crypto/sha256.h"12#include "crypto/sha256.h"
12#include "crypto/crypto.h"13#include "crypto/crypto.h"
13#include "eap_defs.h"14#include "eap_defs.h"
14#include "eap_pwd_common.h"15#include "eap_pwd_common.h"
1516
17#define MAX_ECC_PRIME_LEN 66
18
19
16/* The random function H(x) = HMAC-SHA256(0^32, x) */20/* The random function H(x) = HMAC-SHA256(0^32, x) */
17struct crypto_hash * eap_pwd_h_init(void)21struct crypto_hash * eap_pwd_h_init(void)
18{22{
@@ -81,6 +85,36 @@ static int eap_pwd_kdf(const u8 *key, size_t keylen, const u8 *label,
81}85}
8286
8387
88EAP_PWD_group * get_eap_pwd_group(u16 num)
89{
90 EAP_PWD_group *grp;
91
92 grp = os_zalloc(sizeof(EAP_PWD_group));
93 if (!grp)
94 return NULL;
95 grp->group = crypto_ec_init(num);
96 if (!grp->group) {
97 wpa_printf(MSG_INFO, "EAP-pwd: unable to create EC group");
98 os_free(grp);
99 return NULL;
100 }
101
102 grp->group_num = num;
103 wpa_printf(MSG_INFO, "EAP-pwd: provisioned group %d", num);
104
105 return grp;
106}
107
108
109static void buf_shift_right(u8 *buf, size_t len, size_t bits)
110{
111 size_t i;
112 for (i = len - 1; i > 0; i--)
113 buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits);
114 buf[0] >>= bits;
115}
116
117
84/*118/*
85 * compute a "random" secret point on an elliptic curve based119 * compute a "random" secret point on an elliptic curve based
86 * on the password and identities.120 * on the password and identities.
@@ -90,85 +124,84 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
90 u8 *id_server, int id_server_len,124 u8 *id_server, int id_server_len,
91 u8 *id_peer, int id_peer_len, u8 *token)125 u8 *id_peer, int id_peer_len, u8 *token)
92{126{
93 BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL;127 struct crypto_bignum *qr = NULL, *qnr = NULL, *one = NULL;
128 struct crypto_bignum *qr_or_qnr = NULL;
129 u8 qr_bin[MAX_ECC_PRIME_LEN];
130 u8 qnr_bin[MAX_ECC_PRIME_LEN];
131 u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN];
132 u8 x_bin[MAX_ECC_PRIME_LEN];
133 struct crypto_bignum *tmp1 = NULL, *tmp2 = NULL, *pm1 = NULL;
94 struct crypto_hash *hash;134 struct crypto_hash *hash;
95 unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr;135 unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr;
96 int nid, is_odd, ret = 0;136 int ret = 0, check, res;
97 size_t primebytelen, primebitlen;137 u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
98138 * mask */
99 switch (num) { /* from IANA registry for IKE D-H groups */139 size_t primebytelen = 0, primebitlen;
100 case 19:140 struct crypto_bignum *x_candidate = NULL, *cofactor = NULL;
101 nid = NID_X9_62_prime256v1;141 const struct crypto_bignum *prime;
102 break;142 u8 mask, found_ctr = 0, is_odd = 0;
103 case 20:143
104 nid = NID_secp384r1;144 if (grp->pwe)
105 break;
106 case 21:
107 nid = NID_secp521r1;
108 break;
109#ifndef OPENSSL_IS_BORINGSSL
110 case 25:
111 nid = NID_X9_62_prime192v1;
112 break;
113#endif /* OPENSSL_IS_BORINGSSL */
114 case 26:
115 nid = NID_secp224r1;
116 break;
117 default:
118 wpa_printf(MSG_INFO, "EAP-pwd: unsupported group %d", num);
119 return -1;145 return -1;
120 }
121146
122 grp->pwe = NULL;147 os_memset(x_bin, 0, sizeof(x_bin));
123 grp->order = NULL;
124 grp->prime = NULL;
125148
126 if ((grp->group = EC_GROUP_new_by_curve_name(nid)) == NULL) {149 prime = crypto_ec_get_prime(grp->group);
127 wpa_printf(MSG_INFO, "EAP-pwd: unable to create EC_GROUP");150 cofactor = crypto_bignum_init();
128 goto fail;151 grp->pwe = crypto_ec_point_init(grp->group);
129 }152 tmp1 = crypto_bignum_init();
130153 pm1 = crypto_bignum_init();
131 if (((rnd = BN_new()) == NULL) ||154 one = crypto_bignum_init_set((const u8 *) "\x01", 1);
132 ((cofactor = BN_new()) == NULL) ||155 if (!cofactor || !grp->pwe || !tmp1 || !pm1 || !one) {
133 ((grp->pwe = EC_POINT_new(grp->group)) == NULL) ||
134 ((grp->order = BN_new()) == NULL) ||
135 ((grp->prime = BN_new()) == NULL) ||
136 ((x_candidate = BN_new()) == NULL)) {
137 wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums");156 wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums");
138 goto fail;157 goto fail;
139 }158 }
140159
141 if (!EC_GROUP_get_curve_GFp(grp->group, grp->prime, NULL, NULL, NULL))160 if (crypto_ec_cofactor(grp->group, cofactor) < 0) {
142 {
143 wpa_printf(MSG_INFO, "EAP-pwd: unable to get prime for GFp "
144 "curve");
145 goto fail;
146 }
147 if (!EC_GROUP_get_order(grp->group, grp->order, NULL)) {
148 wpa_printf(MSG_INFO, "EAP-pwd: unable to get order for curve");
149 goto fail;
150 }
151 if (!EC_GROUP_get_cofactor(grp->group, cofactor, NULL)) {
152 wpa_printf(MSG_INFO, "EAP-pwd: unable to get cofactor for "161 wpa_printf(MSG_INFO, "EAP-pwd: unable to get cofactor for "
153 "curve");162 "curve");
154 goto fail;163 goto fail;
155 }164 }
156 primebitlen = BN_num_bits(grp->prime);165 primebitlen = crypto_ec_prime_len_bits(grp->group);
157 primebytelen = BN_num_bytes(grp->prime);166 primebytelen = crypto_ec_prime_len(grp->group);
158 if ((prfbuf = os_malloc(primebytelen)) == NULL) {167 if ((prfbuf = os_malloc(primebytelen)) == NULL) {
159 wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf "168 wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf "
160 "buffer");169 "buffer");
161 goto fail;170 goto fail;
162 }171 }
163 os_memset(prfbuf, 0, primebytelen);172 if (crypto_bignum_sub(prime, one, pm1) < 0)
164 ctr = 0;173 goto fail;
165 while (1) {174
166 if (ctr > 30) {175 /* get a random quadratic residue and nonresidue */
167 wpa_printf(MSG_INFO, "EAP-pwd: unable to find random "176 while (!qr || !qnr) {
168 "point on curve for group %d, something's "177 if (crypto_bignum_rand(tmp1, prime) < 0)
169 "fishy", num);
170 goto fail;178 goto fail;
179 res = crypto_bignum_legendre(tmp1, prime);
180 if (!qr && res == 1) {
181 qr = tmp1;
182 tmp1 = crypto_bignum_init();
183 } else if (!qnr && res == -1) {
184 qnr = tmp1;
185 tmp1 = crypto_bignum_init();
171 }186 }
187 if (!tmp1)
188 goto fail;
189 }
190 if (crypto_bignum_to_bin(qr, qr_bin, sizeof(qr_bin),
191 primebytelen) < 0 ||
192 crypto_bignum_to_bin(qnr, qnr_bin, sizeof(qnr_bin),
193 primebytelen) < 0)
194 goto fail;
195
196 os_memset(prfbuf, 0, primebytelen);
197 ctr = 0;
198
199 /*
200 * Run through the hunting-and-pecking loop 40 times to mask the time
201 * necessary to find PWE. The odds of PWE not being found in 40 loops is
202 * roughly 1 in 1 trillion.
203 */
204 while (ctr < 40) {
172 ctr++;205 ctr++;
173206
174 /*207 /*
@@ -186,114 +219,170 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
186 eap_pwd_h_update(hash, &ctr, sizeof(ctr));219 eap_pwd_h_update(hash, &ctr, sizeof(ctr));
187 eap_pwd_h_final(hash, pwe_digest);220 eap_pwd_h_final(hash, pwe_digest);
188221
189 BN_bin2bn(pwe_digest, SHA256_MAC_LEN, rnd);222 is_odd = const_time_select_u8(
190223 found, is_odd, pwe_digest[SHA256_MAC_LEN - 1] & 0x01);
191 if (eap_pwd_kdf(pwe_digest, SHA256_MAC_LEN,224 if (eap_pwd_kdf(pwe_digest, SHA256_MAC_LEN,
192 (u8 *) "EAP-pwd Hunting And Pecking",225 (u8 *) "EAP-pwd Hunting And Pecking",
193 os_strlen("EAP-pwd Hunting And Pecking"),226 os_strlen("EAP-pwd Hunting And Pecking"),
194 prfbuf, primebitlen) < 0)227 prfbuf, primebitlen) < 0)
195 goto fail;228 goto fail;
196
197 BN_bin2bn(prfbuf, primebytelen, x_candidate);
198
199 /*
200 * eap_pwd_kdf() returns a string of bits 0..primebitlen but
201 * BN_bin2bn will treat that string of bits as a big endian
202 * number. If the primebitlen is not an even multiple of 8
203 * then excessive bits-- those _after_ primebitlen-- so now
204 * we have to shift right the amount we masked off.
205 */
206 if (primebitlen % 8)229 if (primebitlen % 8)
207 BN_rshift(x_candidate, x_candidate,230 buf_shift_right(prfbuf, primebytelen,
208 (8 - (primebitlen % 8)));231 8 - primebitlen % 8);
232
233 crypto_bignum_deinit(x_candidate, 1);
234 x_candidate = crypto_bignum_init_set(prfbuf, primebytelen);
235 if (!x_candidate) {
236 wpa_printf(MSG_INFO,
237 "EAP-pwd: unable to create x_candidate");
238 goto fail;
239 }
209240
210 if (BN_ucmp(x_candidate, grp->prime) >= 0)241 if (crypto_bignum_cmp(x_candidate, prime) >= 0)
211 continue;242 continue;
212243
213 wpa_hexdump(MSG_DEBUG, "EAP-pwd: x_candidate",244 wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: x_candidate",
214 prfbuf, primebytelen);245 prfbuf, primebytelen);
246 const_time_select_bin(found, x_bin, prfbuf, primebytelen,
247 x_bin);
215248
216 /*249 /*
217 * need to unambiguously identify the solution, if there is250 * compute y^2 using the equation of the curve
218 * one...251 *
252 * y^2 = x^3 + ax + b
219 */253 */
220 if (BN_is_odd(rnd))254 crypto_bignum_deinit(tmp2, 1);
221 is_odd = 1;255 tmp2 = crypto_ec_point_compute_y_sqr(grp->group, x_candidate);
222 else256 if (!tmp2)
223 is_odd = 0;257 goto fail;
224258
225 /*259 /*
226 * solve the quadratic equation, if it's not solvable then we260 * mask tmp2 so doing legendre won't leak timing info
227 * don't have a point261 *
262 * tmp1 is a random number between 1 and p-1
228 */263 */
229 if (!EC_POINT_set_compressed_coordinates_GFp(grp->group,264 if (crypto_bignum_rand(tmp1, pm1) < 0 ||
230 grp->pwe,265 crypto_bignum_mulmod(tmp2, tmp1, prime, tmp2) < 0 ||
231 x_candidate,266 crypto_bignum_mulmod(tmp2, tmp1, prime, tmp2) < 0)
232 is_odd, NULL))267 goto fail;
233 continue;268
234 /*269 /*
235 * If there's a solution to the equation then the point must be270 * Now tmp2 (y^2) is masked, all values between 1 and p-1
236 * on the curve so why check again explicitly? OpenSSL code271 * are equally probable. Multiplying by r^2 does not change
237 * says this is required by X9.62. We're not X9.62 but it can't272 * whether or not tmp2 is a quadratic residue, just masks it.
238 * hurt just to be sure.273 *
274 * Flip a coin, multiply by the random quadratic residue or the
275 * random quadratic nonresidue and record heads or tails.
239 */276 */
240 if (!EC_POINT_is_on_curve(grp->group, grp->pwe, NULL)) {277 mask = const_time_eq_u8(crypto_bignum_is_odd(tmp1), 1);
241 wpa_printf(MSG_INFO, "EAP-pwd: point is not on curve");278 check = const_time_select_s8(mask, 1, -1);
242 continue;279 const_time_select_bin(mask, qr_bin, qnr_bin, primebytelen,
243 }280 qr_or_qnr_bin);
281 crypto_bignum_deinit(qr_or_qnr, 1);
282 qr_or_qnr = crypto_bignum_init_set(qr_or_qnr_bin, primebytelen);
283 if (!qr_or_qnr ||
284 crypto_bignum_mulmod(tmp2, qr_or_qnr, prime, tmp2) < 0)
285 goto fail;
244286
245 if (BN_cmp(cofactor, BN_value_one())) {287 /*
246 /* make sure the point is not in a small sub-group */288 * Now it's safe to do legendre, if check is 1 then it's
247 if (!EC_POINT_mul(grp->group, grp->pwe, NULL, grp->pwe,289 * a straightforward test (multiplying by qr does not
248 cofactor, NULL)) {290 * change result), if check is -1 then it's the opposite test
249 wpa_printf(MSG_INFO, "EAP-pwd: cannot "291 * (multiplying a qr by qnr would make a qnr).
250 "multiply generator by order");292 */
251 continue;293 res = crypto_bignum_legendre(tmp2, prime);
252 }294 if (res == -2)
253 if (EC_POINT_is_at_infinity(grp->group, grp->pwe)) {295 goto fail;
254 wpa_printf(MSG_INFO, "EAP-pwd: point is at "296 mask = const_time_eq(res, check);
255 "infinity");297 found_ctr = const_time_select_u8(found, found_ctr, ctr);
256 continue;298 found |= mask;
257 }299 }
300 if (found == 0) {
301 wpa_printf(MSG_INFO,
302 "EAP-pwd: unable to find random point on curve for group %d, something's fishy",
303 num);
304 goto fail;
305 }
306
307 /*
308 * We know x_candidate is a quadratic residue so set it here.
309 */
310 crypto_bignum_deinit(x_candidate, 1);
311 x_candidate = crypto_bignum_init_set(x_bin, primebytelen);
312 if (!x_candidate ||
313 crypto_ec_point_solve_y_coord(grp->group, grp->pwe, x_candidate,
314 is_odd) != 0) {
315 wpa_printf(MSG_INFO, "EAP-pwd: Could not solve for y");
316 goto fail;
317 }
318
319 /*
320 * If there's a solution to the equation then the point must be on the
321 * curve so why check again explicitly? OpenSSL code says this is
322 * required by X9.62. We're not X9.62 but it can't hurt just to be sure.
323 */
324 if (!crypto_ec_point_is_on_curve(grp->group, grp->pwe)) {
325 wpa_printf(MSG_INFO, "EAP-pwd: point is not on curve");
326 goto fail;
327 }
328
329 if (!crypto_bignum_is_one(cofactor)) {
330 /* make sure the point is not in a small sub-group */
331 if (crypto_ec_point_mul(grp->group, grp->pwe, cofactor,
332 grp->pwe) != 0) {
333 wpa_printf(MSG_INFO,
334 "EAP-pwd: cannot multiply generator by order");
335 goto fail;
336 }
337 if (crypto_ec_point_is_at_infinity(grp->group, grp->pwe)) {
338 wpa_printf(MSG_INFO, "EAP-pwd: point is at infinity");
339 goto fail;
258 }340 }
259 /* if we got here then we have a new generator. */
260 break;
261 }341 }
262 wpa_printf(MSG_DEBUG, "EAP-pwd: found a PWE in %d tries", ctr);342 wpa_printf(MSG_DEBUG, "EAP-pwd: found a PWE in %02d tries", found_ctr);
263 grp->group_num = num;343
264 if (0) {344 if (0) {
265 fail:345 fail:
266 EC_GROUP_free(grp->group);346 crypto_ec_point_deinit(grp->pwe, 1);
267 grp->group = NULL;
268 EC_POINT_clear_free(grp->pwe);
269 grp->pwe = NULL;347 grp->pwe = NULL;
270 BN_clear_free(grp->order);
271 grp->order = NULL;
272 BN_clear_free(grp->prime);
273 grp->prime = NULL;
274 ret = 1;348 ret = 1;
275 }349 }
276 /* cleanliness and order.... */350 /* cleanliness and order.... */
277 BN_clear_free(cofactor);351 crypto_bignum_deinit(cofactor, 1);
278 BN_clear_free(x_candidate);352 crypto_bignum_deinit(x_candidate, 1);
279 BN_clear_free(rnd);353 crypto_bignum_deinit(pm1, 0);
280 os_free(prfbuf);354 crypto_bignum_deinit(tmp1, 1);
355 crypto_bignum_deinit(tmp2, 1);
356 crypto_bignum_deinit(qr, 1);
357 crypto_bignum_deinit(qnr, 1);
358 crypto_bignum_deinit(qr_or_qnr, 1);
359 crypto_bignum_deinit(one, 0);
360 bin_clear_free(prfbuf, primebytelen);
361 os_memset(qr_bin, 0, sizeof(qr_bin));
362 os_memset(qnr_bin, 0, sizeof(qnr_bin));
363 os_memset(qr_or_qnr_bin, 0, sizeof(qr_or_qnr_bin));
364 os_memset(pwe_digest, 0, sizeof(pwe_digest));
281365
282 return ret;366 return ret;
283}367}
284368
285369
286int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, BIGNUM *k,370int compute_keys(EAP_PWD_group *grp, const struct crypto_bignum *k,
287 BIGNUM *peer_scalar, BIGNUM *server_scalar,371 const struct crypto_bignum *peer_scalar,
288 u8 *confirm_peer, u8 *confirm_server,372 const struct crypto_bignum *server_scalar,
289 u32 *ciphersuite, u8 *msk, u8 *emsk, u8 *session_id)373 const u8 *confirm_peer, const u8 *confirm_server,
374 const u32 *ciphersuite, u8 *msk, u8 *emsk, u8 *session_id)
290{375{
291 struct crypto_hash *hash;376 struct crypto_hash *hash;
292 u8 mk[SHA256_MAC_LEN], *cruft;377 u8 mk[SHA256_MAC_LEN], *cruft;
293 u8 msk_emsk[EAP_MSK_LEN + EAP_EMSK_LEN];378 u8 msk_emsk[EAP_MSK_LEN + EAP_EMSK_LEN];
294 int offset;379 size_t prime_len, order_len;
380
381 prime_len = crypto_ec_prime_len(grp->group);
382 order_len = crypto_ec_order_len(grp->group);
295383
296 if ((cruft = os_malloc(BN_num_bytes(grp->prime))) == NULL)384 cruft = os_malloc(prime_len);
385 if (!cruft)
297 return -1;386 return -1;
298387
299 /*388 /*
@@ -306,15 +395,11 @@ int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, BIGNUM *k,
306 os_free(cruft);395 os_free(cruft);
307 return -1;396 return -1;
308 }397 }
309 eap_pwd_h_update(hash, (u8 *) ciphersuite, sizeof(u32));398 eap_pwd_h_update(hash, (const u8 *) ciphersuite, sizeof(u32));
310 offset = BN_num_bytes(grp->order) - BN_num_bytes(peer_scalar);399 crypto_bignum_to_bin(peer_scalar, cruft, order_len, order_len);
311 os_memset(cruft, 0, BN_num_bytes(grp->prime));400 eap_pwd_h_update(hash, cruft, order_len);
312 BN_bn2bin(peer_scalar, cruft + offset);401 crypto_bignum_to_bin(server_scalar, cruft, order_len, order_len);
313 eap_pwd_h_update(hash, cruft, BN_num_bytes(grp->order));402 eap_pwd_h_update(hash, cruft, order_len);
314 offset = BN_num_bytes(grp->order) - BN_num_bytes(server_scalar);
315 os_memset(cruft, 0, BN_num_bytes(grp->prime));
316 BN_bn2bin(server_scalar, cruft + offset);
317 eap_pwd_h_update(hash, cruft, BN_num_bytes(grp->order));
318 eap_pwd_h_final(hash, &session_id[1]);403 eap_pwd_h_final(hash, &session_id[1]);
319404
320 /* then compute MK = H(k | confirm-peer | confirm-server) */405 /* then compute MK = H(k | confirm-peer | confirm-server) */
@@ -323,10 +408,8 @@ int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, BIGNUM *k,
323 os_free(cruft);408 os_free(cruft);
324 return -1;409 return -1;
325 }410 }
326 offset = BN_num_bytes(grp->prime) - BN_num_bytes(k);411 crypto_bignum_to_bin(k, cruft, prime_len, prime_len);
327 os_memset(cruft, 0, BN_num_bytes(grp->prime));412 eap_pwd_h_update(hash, cruft, prime_len);
328 BN_bn2bin(k, cruft + offset);
329 eap_pwd_h_update(hash, cruft, BN_num_bytes(grp->prime));
330 os_free(cruft);413 os_free(cruft);
331 eap_pwd_h_update(hash, confirm_peer, SHA256_MAC_LEN);414 eap_pwd_h_update(hash, confirm_peer, SHA256_MAC_LEN);
332 eap_pwd_h_update(hash, confirm_server, SHA256_MAC_LEN);415 eap_pwd_h_update(hash, confirm_server, SHA256_MAC_LEN);
@@ -344,3 +427,109 @@ int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, BIGNUM *k,
344427
345 return 1;428 return 1;
346}429}
430
431
432static int eap_pwd_element_coord_ok(const struct crypto_bignum *prime,
433 const u8 *buf, size_t len)
434{
435 struct crypto_bignum *val;
436 int ok = 1;
437
438 val = crypto_bignum_init_set(buf, len);
439 if (!val || crypto_bignum_is_zero(val) ||
440 crypto_bignum_cmp(val, prime) >= 0)
441 ok = 0;
442 crypto_bignum_deinit(val, 0);
443 return ok;
444}
445
446
447struct crypto_ec_point * eap_pwd_get_element(EAP_PWD_group *group,
448 const u8 *buf)
449{
450 struct crypto_ec_point *element;
451 const struct crypto_bignum *prime;
452 size_t prime_len;
453 struct crypto_bignum *cofactor = NULL;
454
455 prime = crypto_ec_get_prime(group->group);
456 prime_len = crypto_ec_prime_len(group->group);
457
458 /* RFC 5931, 2.8.5.2.2: 0 < x,y < p */
459 if (!eap_pwd_element_coord_ok(prime, buf, prime_len) ||
460 !eap_pwd_element_coord_ok(prime, buf + prime_len, prime_len)) {
461 wpa_printf(MSG_INFO, "EAP-pwd: Invalid coordinate in element");
462 return NULL;
463 }
464
465 element = crypto_ec_point_from_bin(group->group, buf);
466 if (!element) {
467 wpa_printf(MSG_INFO, "EAP-pwd: EC point from element failed");
468 return NULL;
469 }
470
471 /* RFC 5931, 2.8.5.2.2: on curve and not the point at infinity */
472 if (!crypto_ec_point_is_on_curve(group->group, element) ||
473 crypto_ec_point_is_at_infinity(group->group, element)) {
474 wpa_printf(MSG_INFO, "EAP-pwd: Invalid element");
475 goto fail;
476 }
477
478 cofactor = crypto_bignum_init();
479 if (!cofactor || crypto_ec_cofactor(group->group, cofactor) < 0) {
480 wpa_printf(MSG_INFO,
481 "EAP-pwd: Unable to get cofactor for curve");
482 goto fail;
483 }
484
485 if (!crypto_bignum_is_one(cofactor)) {
486 struct crypto_ec_point *point;
487 int ok = 1;
488
489 /* check to ensure peer's element is not in a small sub-group */
490 point = crypto_ec_point_init(group->group);
491 if (!point ||
492 crypto_ec_point_mul(group->group, element,
493 cofactor, point) != 0 ||
494 crypto_ec_point_is_at_infinity(group->group, point))
495 ok = 0;
496 crypto_ec_point_deinit(point, 0);
497
498 if (!ok) {
499 wpa_printf(MSG_INFO,
500 "EAP-pwd: Small sub-group check on peer element failed");
501 goto fail;
502 }
503 }
504
505out:
506 crypto_bignum_deinit(cofactor, 0);
507 return element;
508fail:
509 crypto_ec_point_deinit(element, 0);
510 element = NULL;
511 goto out;
512}
513
514
515struct crypto_bignum * eap_pwd_get_scalar(EAP_PWD_group *group, const u8 *buf)
516{
517 struct crypto_bignum *scalar;
518 const struct crypto_bignum *order;
519 size_t order_len;
520
521 order = crypto_ec_get_order(group->group);
522 order_len = crypto_ec_order_len(group->group);
523
524 /* RFC 5931, 2.8.5.2: 1 < scalar < r */
525 scalar = crypto_bignum_init_set(buf, order_len);
526 if (!scalar || crypto_bignum_is_zero(scalar) ||
527 crypto_bignum_is_one(scalar) ||
528 crypto_bignum_cmp(scalar, order) >= 0) {
529 wpa_printf(MSG_INFO, "EAP-pwd: received scalar is invalid");
530 crypto_bignum_deinit(scalar, 0);
531 scalar = NULL;
532 }
533
534 return scalar;
535}
diff --git a/src/eap_common/eap_pwd_common.h b/src/eap_common/eap_pwd_common.h
index c54c441..e61b4ba 100644
--- a/src/eap_common/eap_pwd_common.h
+++ b/src/eap_common/eap_pwd_common.h
@@ -9,20 +9,14 @@
9#ifndef EAP_PWD_COMMON_H9#ifndef EAP_PWD_COMMON_H
10#define EAP_PWD_COMMON_H10#define EAP_PWD_COMMON_H
1111
12#include <openssl/bn.h>
13#include <openssl/ec.h>
14#include <openssl/evp.h>
15
16/*12/*
17 * definition of a finite cyclic group13 * definition of a finite cyclic group
18 * TODO: support one based on a prime field14 * TODO: support one based on a prime field
19 */15 */
20typedef struct group_definition_ {16typedef struct group_definition_ {
21 u16 group_num;17 u16 group_num;
22 EC_GROUP *group;18 struct crypto_ec *group;
23 EC_POINT *pwe;19 struct crypto_ec_point *pwe;
24 BIGNUM *order;
25 BIGNUM *prime;
26} EAP_PWD_group;20} EAP_PWD_group;
2721
28/*22/*
@@ -56,12 +50,19 @@ struct eap_pwd_id {
56} STRUCT_PACKED;50} STRUCT_PACKED;
5751
58/* common routines */52/* common routines */
53EAP_PWD_group * get_eap_pwd_group(u16 num);
59int compute_password_element(EAP_PWD_group *, u16, u8 *, int, u8 *, int, u8 *,54int compute_password_element(EAP_PWD_group *, u16, u8 *, int, u8 *, int, u8 *,
60 int, u8 *);55 int, u8 *);
61int compute_keys(EAP_PWD_group *, BN_CTX *, BIGNUM *, BIGNUM *, BIGNUM *,56int compute_keys(EAP_PWD_group *grp, const struct crypto_bignum *k,
62 u8 *, u8 *, u32 *, u8 *, u8 *, u8 *);57 const struct crypto_bignum *peer_scalar,
58 const struct crypto_bignum *server_scalar,
59 const u8 *confirm_peer, const u8 *confirm_server,
60 const u32 *ciphersuite, u8 *msk, u8 *emsk, u8 *session_id);
63struct crypto_hash * eap_pwd_h_init(void);61struct crypto_hash * eap_pwd_h_init(void);
64void eap_pwd_h_update(struct crypto_hash *hash, const u8 *data, size_t len);62void eap_pwd_h_update(struct crypto_hash *hash, const u8 *data, size_t len);
65void eap_pwd_h_final(struct crypto_hash *hash, u8 *digest);63void eap_pwd_h_final(struct crypto_hash *hash, u8 *digest);
64struct crypto_ec_point * eap_pwd_get_element(EAP_PWD_group *group,
65 const u8 *buf);
66struct crypto_bignum * eap_pwd_get_scalar(EAP_PWD_group *group, const u8 *buf);
6667
67#endif /* EAP_PWD_COMMON_H */68#endif /* EAP_PWD_COMMON_H */
diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
index 8eecf8d..a0dd00a 100644
--- a/src/eap_peer/eap_pwd.c
+++ b/src/eap_peer/eap_pwd.c
@@ -10,6 +10,7 @@
1010
11#include "common.h"11#include "common.h"
12#include "crypto/sha256.h"12#include "crypto/sha256.h"
13#include "crypto/crypto.h"
13#include "eap_peer/eap_i.h"14#include "eap_peer/eap_i.h"
14#include "eap_common/eap_pwd_common.h"15#include "eap_common/eap_pwd_common.h"
1516
@@ -34,18 +35,16 @@ struct eap_pwd_data {
34 size_t out_frag_pos;35 size_t out_frag_pos;
35 size_t mtu;36 size_t mtu;
3637
37 BIGNUM *k;38 struct crypto_bignum *k;
38 BIGNUM *private_value;39 struct crypto_bignum *private_value;
39 BIGNUM *server_scalar;40 struct crypto_bignum *server_scalar;
40 BIGNUM *my_scalar;41 struct crypto_bignum *my_scalar;
41 EC_POINT *my_element;42 struct crypto_ec_point *my_element;
42 EC_POINT *server_element;43 struct crypto_ec_point *server_element;
4344
44 u8 msk[EAP_MSK_LEN];45 u8 msk[EAP_MSK_LEN];
45 u8 emsk[EAP_EMSK_LEN];46 u8 emsk[EAP_EMSK_LEN];
46 u8 session_id[1 + SHA256_MAC_LEN];47 u8 session_id[1 + SHA256_MAC_LEN];
47
48 BN_CTX *bnctx;
49};48};
5049
5150
@@ -104,15 +103,8 @@ static void * eap_pwd_init(struct eap_sm *sm)
104 return NULL;103 return NULL;
105 }104 }
106105
107 if ((data->bnctx = BN_CTX_new()) == NULL) {
108 wpa_printf(MSG_INFO, "EAP-PWD: bn context allocation fail");
109 os_free(data);
110 return NULL;
111 }
112
113 if ((data->id_peer = os_malloc(identity_len)) == NULL) {106 if ((data->id_peer = os_malloc(identity_len)) == NULL) {
114 wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail");107 wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail");
115 BN_CTX_free(data->bnctx);
116 os_free(data);108 os_free(data);
117 return NULL;109 return NULL;
118 }110 }
@@ -122,7 +114,6 @@ static void * eap_pwd_init(struct eap_sm *sm)
122114
123 if ((data->password = os_malloc(password_len)) == NULL) {115 if ((data->password = os_malloc(password_len)) == NULL) {
124 wpa_printf(MSG_INFO, "EAP-PWD: memory allocation psk fail");116 wpa_printf(MSG_INFO, "EAP-PWD: memory allocation psk fail");
125 BN_CTX_free(data->bnctx);
126 bin_clear_free(data->id_peer, data->id_peer_len);117 bin_clear_free(data->id_peer, data->id_peer_len);
127 os_free(data);118 os_free(data);
128 return NULL;119 return NULL;
@@ -148,21 +139,18 @@ static void eap_pwd_deinit(struct eap_sm *sm, void *priv)
148{139{
149 struct eap_pwd_data *data = priv;140 struct eap_pwd_data *data = priv;
150141
151 BN_clear_free(data->private_value);142 crypto_bignum_deinit(data->private_value, 1);
152 BN_clear_free(data->server_scalar);143 crypto_bignum_deinit(data->server_scalar, 1);
153 BN_clear_free(data->my_scalar);144 crypto_bignum_deinit(data->my_scalar, 1);
154 BN_clear_free(data->k);145 crypto_bignum_deinit(data->k, 1);
155 BN_CTX_free(data->bnctx);146 crypto_ec_point_deinit(data->my_element, 1);
156 EC_POINT_clear_free(data->my_element);147 crypto_ec_point_deinit(data->server_element, 1);
157 EC_POINT_clear_free(data->server_element);
158 bin_clear_free(data->id_peer, data->id_peer_len);148 bin_clear_free(data->id_peer, data->id_peer_len);
159 bin_clear_free(data->id_server, data->id_server_len);149 bin_clear_free(data->id_server, data->id_server_len);
160 bin_clear_free(data->password, data->password_len);150 bin_clear_free(data->password, data->password_len);
161 if (data->grp) {151 if (data->grp) {
162 EC_GROUP_free(data->grp->group);152 crypto_ec_deinit(data->grp->group);
163 EC_POINT_clear_free(data->grp->pwe);153 crypto_ec_point_deinit(data->grp->pwe, 1);
164 BN_clear_free(data->grp->order);
165 BN_clear_free(data->grp->prime);
166 os_free(data->grp);154 os_free(data->grp);
167 }155 }
168 wpabuf_free(data->inbuf);156 wpabuf_free(data->inbuf);
@@ -252,7 +240,7 @@ eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
252 wpa_hexdump_ascii(MSG_INFO, "EAP-PWD (peer): server sent id of",240 wpa_hexdump_ascii(MSG_INFO, "EAP-PWD (peer): server sent id of",
253 data->id_server, data->id_server_len);241 data->id_server, data->id_server_len);
254242
255 data->grp = os_zalloc(sizeof(EAP_PWD_group));243 data->grp = get_eap_pwd_group(data->group_num);
256 if (data->grp == NULL) {244 if (data->grp == NULL) {
257 wpa_printf(MSG_INFO, "EAP-PWD: failed to allocate memory for "245 wpa_printf(MSG_INFO, "EAP-PWD: failed to allocate memory for "
258 "group");246 "group");
@@ -272,7 +260,7 @@ eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
272 }260 }
273261
274 wpa_printf(MSG_DEBUG, "EAP-PWD (peer): computed %d bit PWE...",262 wpa_printf(MSG_DEBUG, "EAP-PWD (peer): computed %d bit PWE...",
275 BN_num_bits(data->grp->prime));263 (int) crypto_ec_prime_len_bits(data->grp->group));
276264
277 data->outbuf = wpabuf_alloc(sizeof(struct eap_pwd_id) +265 data->outbuf = wpabuf_alloc(sizeof(struct eap_pwd_id) +
278 data->id_peer_len);266 data->id_peer_len);
@@ -297,10 +285,10 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
297 const struct wpabuf *reqData,285 const struct wpabuf *reqData,
298 const u8 *payload, size_t payload_len)286 const u8 *payload, size_t payload_len)
299{287{
300 EC_POINT *K = NULL, *point = NULL;288 struct crypto_ec_point *K = NULL;
301 BIGNUM *mask = NULL, *x = NULL, *y = NULL, *cofactor = NULL;289 struct crypto_bignum *mask = NULL, *cofactor = NULL;
302 u16 offset;290 const u8 *ptr;
303 u8 *ptr, *scalar = NULL, *element = NULL;291 u8 *scalar = NULL, *element = NULL;
304 size_t prime_len, order_len;292 size_t prime_len, order_len;
305293
306 if (data->state != PWD_Commit_Req) {294 if (data->state != PWD_Commit_Req) {
@@ -308,8 +296,8 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
308 goto fin;296 goto fin;
309 }297 }
310298
311 prime_len = BN_num_bytes(data->grp->prime);299 prime_len = crypto_ec_prime_len(data->grp->group);
312 order_len = BN_num_bytes(data->grp->order);300 order_len = crypto_ec_order_len(data->grp->group);
313301
314 if (payload_len != 2 * prime_len + order_len) {302 if (payload_len != 2 * prime_len + order_len) {
315 wpa_printf(MSG_INFO,303 wpa_printf(MSG_INFO,
@@ -319,110 +307,90 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
319 goto fin;307 goto fin;
320 }308 }
321309
322 if (((data->private_value = BN_new()) == NULL) ||310 data->private_value = crypto_bignum_init();
323 ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) ||311 data->my_element = crypto_ec_point_init(data->grp->group);
324 ((cofactor = BN_new()) == NULL) ||312 cofactor = crypto_bignum_init();
325 ((data->my_scalar = BN_new()) == NULL) ||313 data->my_scalar = crypto_bignum_init();
326 ((mask = BN_new()) == NULL)) {314 mask = crypto_bignum_init();
315 if (!data->private_value || !data->my_element || !cofactor ||
316 !data->my_scalar || !mask) {
327 wpa_printf(MSG_INFO, "EAP-PWD (peer): scalar allocation fail");317 wpa_printf(MSG_INFO, "EAP-PWD (peer): scalar allocation fail");
328 goto fin;318 goto fin;
329 }319 }
330320
331 if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) {321 if (crypto_ec_cofactor(data->grp->group, cofactor) < 0) {
332 wpa_printf(MSG_INFO, "EAP-pwd (peer): unable to get cofactor "322 wpa_printf(MSG_INFO, "EAP-pwd (peer): unable to get cofactor "
333 "for curve");323 "for curve");
334 goto fin;324 goto fin;
335 }325 }
336326
337 if (BN_rand_range(data->private_value, data->grp->order) != 1 ||327 if (crypto_bignum_rand(data->private_value,
338 BN_rand_range(mask, data->grp->order) != 1 ||328 crypto_ec_get_order(data->grp->group)) < 0 ||
339 BN_add(data->my_scalar, data->private_value, mask) != 1 ||329 crypto_bignum_rand(mask,
340 BN_mod(data->my_scalar, data->my_scalar, data->grp->order,330 crypto_ec_get_order(data->grp->group)) < 0 ||
341 data->bnctx) != 1) {331 crypto_bignum_add(data->private_value, mask,
332 data->my_scalar) < 0 ||
333 crypto_bignum_mod(data->my_scalar,
334 crypto_ec_get_order(data->grp->group),
335 data->my_scalar) < 0) {
342 wpa_printf(MSG_INFO,336 wpa_printf(MSG_INFO,
343 "EAP-pwd (peer): unable to get randomness");337 "EAP-pwd (peer): unable to get randomness");
344 goto fin;338 goto fin;
345 }339 }
346340
347 if (!EC_POINT_mul(data->grp->group, data->my_element, NULL,341 if (crypto_ec_point_mul(data->grp->group, data->grp->pwe, mask,
348 data->grp->pwe, mask, data->bnctx)) {342 data->my_element) < 0) {
349 wpa_printf(MSG_INFO, "EAP-PWD (peer): element allocation "343 wpa_printf(MSG_INFO, "EAP-PWD (peer): element allocation "
350 "fail");344 "fail");
351 eap_pwd_state(data, FAILURE);345 eap_pwd_state(data, FAILURE);
352 goto fin;346 goto fin;
353 }347 }
354348
355 if (!EC_POINT_invert(data->grp->group, data->my_element, data->bnctx))349 if (crypto_ec_point_invert(data->grp->group, data->my_element) < 0) {
356 {
357 wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail");350 wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail");
358 goto fin;351 goto fin;
359 }352 }
360 BN_clear_free(mask);
361
362 if (((x = BN_new()) == NULL) ||
363 ((y = BN_new()) == NULL)) {
364 wpa_printf(MSG_INFO, "EAP-PWD (peer): point allocation fail");
365 goto fin;
366 }
367353
368 /* process the request */354 /* process the request */
369 if (((data->server_scalar = BN_new()) == NULL) ||355 data->k = crypto_bignum_init();
370 ((data->k = BN_new()) == NULL) ||356 K = crypto_ec_point_init(data->grp->group);
371 ((K = EC_POINT_new(data->grp->group)) == NULL) ||357 if (!data->k || !K) {
372 ((point = EC_POINT_new(data->grp->group)) == NULL) ||
373 ((data->server_element = EC_POINT_new(data->grp->group)) == NULL))
374 {
375 wpa_printf(MSG_INFO, "EAP-PWD (peer): peer data allocation "358 wpa_printf(MSG_INFO, "EAP-PWD (peer): peer data allocation "
376 "fail");359 "fail");
377 goto fin;360 goto fin;
378 }361 }
379362
380 /* element, x then y, followed by scalar */363 /* element, x then y, followed by scalar */
381 ptr = (u8 *) payload;364 ptr = payload;
382 BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x);365 data->server_element = eap_pwd_get_element(data->grp, ptr);
383 ptr += BN_num_bytes(data->grp->prime);366 if (!data->server_element) {
384 BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y);
385 ptr += BN_num_bytes(data->grp->prime);
386 BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->server_scalar);
387 if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group,
388 data->server_element, x, y,
389 data->bnctx)) {
390 wpa_printf(MSG_INFO, "EAP-PWD (peer): setting peer element "367 wpa_printf(MSG_INFO, "EAP-PWD (peer): setting peer element "
391 "fail");368 "fail");
392 goto fin;369 goto fin;
393 }370 }
394371 ptr += prime_len * 2;
395 /* check to ensure server's element is not in a small sub-group */372 data->server_scalar = eap_pwd_get_scalar(data->grp, ptr);
396 if (BN_cmp(cofactor, BN_value_one())) {373 if (!data->server_scalar) {
397 if (!EC_POINT_mul(data->grp->group, point, NULL,374 wpa_printf(MSG_INFO,
398 data->server_element, cofactor, NULL)) {375 "EAP-PWD (peer): setting peer scalar fail");
399 wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply "376 goto fin;
400 "server element by order!\n");
401 goto fin;
402 }
403 if (EC_POINT_is_at_infinity(data->grp->group, point)) {
404 wpa_printf(MSG_INFO, "EAP-PWD (peer): server element "
405 "is at infinity!\n");
406 goto fin;
407 }
408 }377 }
409378
410 /* compute the shared key, k */379 /* compute the shared key, k */
411 if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe,380 if (crypto_ec_point_mul(data->grp->group, data->grp->pwe,
412 data->server_scalar, data->bnctx)) ||381 data->server_scalar, K) < 0 ||
413 (!EC_POINT_add(data->grp->group, K, K, data->server_element,382 crypto_ec_point_add(data->grp->group, K, data->server_element,
414 data->bnctx)) ||383 K) < 0 ||
415 (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value,384 crypto_ec_point_mul(data->grp->group, K, data->private_value,
416 data->bnctx))) {385 K) < 0) {
417 wpa_printf(MSG_INFO, "EAP-PWD (peer): computing shared key "386 wpa_printf(MSG_INFO, "EAP-PWD (peer): computing shared key "
418 "fail");387 "fail");
419 goto fin;388 goto fin;
420 }389 }
421390
422 /* ensure that the shared key isn't in a small sub-group */391 /* ensure that the shared key isn't in a small sub-group */
423 if (BN_cmp(cofactor, BN_value_one())) {392 if (!crypto_bignum_is_one(cofactor)) {
424 if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor,393 if (crypto_ec_point_mul(data->grp->group, K, cofactor, K) < 0) {
425 NULL)) {
426 wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply "394 wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply "
427 "shared key point by order");395 "shared key point by order");
428 goto fin;396 goto fin;
@@ -435,30 +403,22 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
435 * never going to happen it is a simple and safe check "just to be403 * never going to happen it is a simple and safe check "just to be
436 * sure" so let's be safe.404 * sure" so let's be safe.
437 */405 */
438 if (EC_POINT_is_at_infinity(data->grp->group, K)) {406 if (crypto_ec_point_is_at_infinity(data->grp->group, K)) {
439 wpa_printf(MSG_INFO, "EAP-PWD (peer): shared key point is at "407 wpa_printf(MSG_INFO, "EAP-PWD (peer): shared key point is at "
440 "infinity!\n");408 "infinity!\n");
441 goto fin;409 goto fin;
442 }410 }
443411
444 if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k,412 if (crypto_ec_point_x(data->grp->group, K, data->k) < 0) {
445 NULL, data->bnctx)) {
446 wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to extract "413 wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to extract "
447 "shared secret from point");414 "shared secret from point");
448 goto fin;415 goto fin;
449 }416 }
450417
451 /* now do the response */418 /* now do the response */
452 if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,419 scalar = os_zalloc(order_len);
453 data->my_element, x, y,420 element = os_zalloc(prime_len * 2);
454 data->bnctx)) {421 if (!scalar || !element) {
455 wpa_printf(MSG_INFO, "EAP-PWD (peer): point assignment fail");
456 goto fin;
457 }
458
459 if (((scalar = os_malloc(BN_num_bytes(data->grp->order))) == NULL) ||
460 ((element = os_malloc(BN_num_bytes(data->grp->prime) * 2)) ==
461 NULL)) {
462 wpa_printf(MSG_INFO, "EAP-PWD (peer): data allocation fail");422 wpa_printf(MSG_INFO, "EAP-PWD (peer): data allocation fail");
463 goto fin;423 goto fin;
464 }424 }
@@ -468,35 +428,27 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
468 * sufficiently smaller than the prime or order might need pre-pending428 * sufficiently smaller than the prime or order might need pre-pending
469 * with zeros.429 * with zeros.
470 */430 */
471 os_memset(scalar, 0, BN_num_bytes(data->grp->order));431 crypto_bignum_to_bin(data->my_scalar, scalar, order_len, order_len);
472 os_memset(element, 0, BN_num_bytes(data->grp->prime) * 2);432 if (crypto_ec_point_to_bin(data->grp->group, data->my_element, element,
473 offset = BN_num_bytes(data->grp->order) -433 element + prime_len) != 0) {
474 BN_num_bytes(data->my_scalar);434 wpa_printf(MSG_INFO, "EAP-PWD (peer): point assignment fail");
475 BN_bn2bin(data->my_scalar, scalar + offset);435 goto fin;
476436 }
477 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);437
478 BN_bn2bin(x, element + offset);438 data->outbuf = wpabuf_alloc(order_len + 2 * prime_len);
479 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
480 BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset);
481
482 data->outbuf = wpabuf_alloc(BN_num_bytes(data->grp->order) +
483 2 * BN_num_bytes(data->grp->prime));
484 if (data->outbuf == NULL)439 if (data->outbuf == NULL)
485 goto fin;440 goto fin;
486441
487 /* we send the element as (x,y) follwed by the scalar */442 /* we send the element as (x,y) follwed by the scalar */
488 wpabuf_put_data(data->outbuf, element,443 wpabuf_put_data(data->outbuf, element, 2 * prime_len);
489 2 * BN_num_bytes(data->grp->prime));444 wpabuf_put_data(data->outbuf, scalar, order_len);
490 wpabuf_put_data(data->outbuf, scalar, BN_num_bytes(data->grp->order));
491445
492fin:446fin:
493 os_free(scalar);447 os_free(scalar);
494 os_free(element);448 os_free(element);
495 BN_clear_free(x);449 crypto_bignum_deinit(mask, 1);
496 BN_clear_free(y);450 crypto_bignum_deinit(cofactor, 1);
497 BN_clear_free(cofactor);451 crypto_ec_point_deinit(K, 1);
498 EC_POINT_clear_free(K);
499 EC_POINT_clear_free(point);
500 if (data->outbuf == NULL)452 if (data->outbuf == NULL)
501 eap_pwd_state(data, FAILURE);453 eap_pwd_state(data, FAILURE);
502 else454 else
@@ -510,12 +462,11 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
510 const struct wpabuf *reqData,462 const struct wpabuf *reqData,
511 const u8 *payload, size_t payload_len)463 const u8 *payload, size_t payload_len)
512{464{
513 BIGNUM *x = NULL, *y = NULL;
514 struct crypto_hash *hash;465 struct crypto_hash *hash;
515 u32 cs;466 u32 cs;
516 u16 grp;467 u16 grp;
517 u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;468 u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
518 int offset;469 size_t prime_len = 0, order_len = 0;
519470
520 if (data->state != PWD_Confirm_Req) {471 if (data->state != PWD_Confirm_Req) {
521 ret->ignore = TRUE;472 ret->ignore = TRUE;
@@ -529,6 +480,9 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
529 goto fin;480 goto fin;
530 }481 }
531482
483 prime_len = crypto_ec_prime_len(data->grp->group);
484 order_len = crypto_ec_order_len(data->grp->group);
485
532 /*486 /*
533 * first build up the ciphersuite which is group | random_function |487 * first build up the ciphersuite which is group | random_function |
534 * prf488 * prf
@@ -541,9 +495,9 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
541 ptr += sizeof(u8);495 ptr += sizeof(u8);
542 *ptr = EAP_PWD_DEFAULT_PRF;496 *ptr = EAP_PWD_DEFAULT_PRF;
543497
544 /* each component of the cruft will be at most as big as the prime */498 /* each component of the point will be at most as big as the prime */
545 if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||499 cruft = os_malloc(prime_len * 2);
546 ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {500 if (!cruft) {
547 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm allocation "501 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm allocation "
548 "fail");502 "fail");
549 goto fin;503 goto fin;
@@ -561,59 +515,34 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
561 * zero the memory each time because this is mod prime math and some515 * zero the memory each time because this is mod prime math and some
562 * value may start with a few zeros and the previous one did not.516 * value may start with a few zeros and the previous one did not.
563 */517 */
564 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));518 crypto_bignum_to_bin(data->k, cruft, prime_len, prime_len);
565 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);519 eap_pwd_h_update(hash, cruft, prime_len);
566 BN_bn2bin(data->k, cruft + offset);
567 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
568520
569 /* server element: x, y */521 /* server element: x, y */
570 if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,522 if (crypto_ec_point_to_bin(data->grp->group, data->server_element,
571 data->server_element, x, y,523 cruft, cruft + prime_len) != 0) {
572 data->bnctx)) {
573 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "524 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
574 "assignment fail");525 "assignment fail");
575 goto fin;526 goto fin;
576 }527 }
577 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));528 eap_pwd_h_update(hash, cruft, prime_len * 2);
578 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
579 BN_bn2bin(x, cruft + offset);
580 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
581 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
582 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
583 BN_bn2bin(y, cruft + offset);
584 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
585529
586 /* server scalar */530 /* server scalar */
587 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));531 crypto_bignum_to_bin(data->server_scalar, cruft, order_len, order_len);
588 offset = BN_num_bytes(data->grp->order) -532 eap_pwd_h_update(hash, cruft, order_len);
589 BN_num_bytes(data->server_scalar);
590 BN_bn2bin(data->server_scalar, cruft + offset);
591 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
592533
593 /* my element: x, y */534 /* my element: x, y */
594 if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,535 if (crypto_ec_point_to_bin(data->grp->group, data->my_element, cruft,
595 data->my_element, x, y,536 cruft + prime_len) != 0) {
596 data->bnctx)) {
597 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "537 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
598 "assignment fail");538 "assignment fail");
599 goto fin;539 goto fin;
600 }540 }
601541 eap_pwd_h_update(hash, cruft, prime_len * 2);
602 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
603 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
604 BN_bn2bin(x, cruft + offset);
605 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
606 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
607 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
608 BN_bn2bin(y, cruft + offset);
609 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
610542
611 /* my scalar */543 /* my scalar */
612 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));544 crypto_bignum_to_bin(data->my_scalar, cruft, order_len, order_len);
613 offset = BN_num_bytes(data->grp->order) -545 eap_pwd_h_update(hash, cruft, order_len);
614 BN_num_bytes(data->my_scalar);
615 BN_bn2bin(data->my_scalar, cruft + offset);
616 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
617546
618 /* the ciphersuite */547 /* the ciphersuite */
619 eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));548 eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));
@@ -639,58 +568,34 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
639 goto fin;568 goto fin;
640569
641 /* k */570 /* k */
642 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));571 crypto_bignum_to_bin(data->k, cruft, prime_len, prime_len);
643 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);572 eap_pwd_h_update(hash, cruft, prime_len);
644 BN_bn2bin(data->k, cruft + offset);
645 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
646573
647 /* my element */574 /* my element */
648 if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,575 if (crypto_ec_point_to_bin(data->grp->group, data->my_element, cruft,
649 data->my_element, x, y,576 cruft + prime_len) != 0) {
650 data->bnctx)) {
651 wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point "577 wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point "
652 "assignment fail");578 "assignment fail");
653 goto fin;579 goto fin;
654 }580 }
655 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));581 eap_pwd_h_update(hash, cruft, prime_len * 2);
656 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
657 BN_bn2bin(x, cruft + offset);
658 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
659 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
660 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
661 BN_bn2bin(y, cruft + offset);
662 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
663582
664 /* my scalar */583 /* my scalar */
665 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));584 crypto_bignum_to_bin(data->my_scalar, cruft, order_len, order_len);
666 offset = BN_num_bytes(data->grp->order) -585 eap_pwd_h_update(hash, cruft, order_len);
667 BN_num_bytes(data->my_scalar);
668 BN_bn2bin(data->my_scalar, cruft + offset);
669 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
670586
671 /* server element: x, y */587 /* server element: x, y */
672 if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,588 if (crypto_ec_point_to_bin(data->grp->group, data->server_element,
673 data->server_element, x, y,589 cruft, cruft + prime_len) != 0) {
674 data->bnctx)) {
675 wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point "590 wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point "
676 "assignment fail");591 "assignment fail");
677 goto fin;592 goto fin;
678 }593 }
679 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));594 eap_pwd_h_update(hash, cruft, prime_len * 2);
680 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
681 BN_bn2bin(x, cruft + offset);
682 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
683 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
684 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
685 BN_bn2bin(y, cruft + offset);
686 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
687595
688 /* server scalar */596 /* server scalar */
689 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));597 crypto_bignum_to_bin(data->server_scalar, cruft, order_len, order_len);
690 offset = BN_num_bytes(data->grp->order) -598 eap_pwd_h_update(hash, cruft, order_len);
691 BN_num_bytes(data->server_scalar);
692 BN_bn2bin(data->server_scalar, cruft + offset);
693 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
694599
695 /* the ciphersuite */600 /* the ciphersuite */
696 eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));601 eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));
@@ -698,7 +603,7 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
698 /* all done */603 /* all done */
699 eap_pwd_h_final(hash, conf);604 eap_pwd_h_final(hash, conf);
700605
701 if (compute_keys(data->grp, data->bnctx, data->k,606 if (compute_keys(data->grp, data->k,
702 data->my_scalar, data->server_scalar, conf, ptr,607 data->my_scalar, data->server_scalar, conf, ptr,
703 &cs, data->msk, data->emsk, data->session_id) < 0) {608 &cs, data->msk, data->emsk, data->session_id) < 0) {
704 wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute MSK | "609 wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute MSK | "
@@ -713,10 +618,7 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
713 wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN);618 wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN);
714619
715fin:620fin:
716 if (data->grp)621 bin_clear_free(cruft, prime_len * 2);
717 bin_clear_free(cruft, BN_num_bytes(data->grp->prime));
718 BN_clear_free(x);
719 BN_clear_free(y);
720 if (data->outbuf == NULL) {622 if (data->outbuf == NULL) {
721 ret->methodState = METHOD_DONE;623 ret->methodState = METHOD_DONE;
722 ret->decision = DECISION_FAIL;624 ret->decision = DECISION_FAIL;
@@ -843,6 +745,13 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret,
843 * buffer and ACK the fragment745 * buffer and ACK the fragment
844 */746 */
845 if (EAP_PWD_GET_MORE_BIT(lm_exch) || data->in_frag_pos) {747 if (EAP_PWD_GET_MORE_BIT(lm_exch) || data->in_frag_pos) {
748 if (!data->inbuf) {
749 wpa_printf(MSG_DEBUG,
750 "EAP-pwd: No buffer for reassembly");
751 ret->methodState = METHOD_DONE;
752 ret->decision = DECISION_FAIL;
753 return NULL;
754 }
846 data->in_frag_pos += len;755 data->in_frag_pos += len;
847 if (data->in_frag_pos > wpabuf_size(data->inbuf)) {756 if (data->in_frag_pos > wpabuf_size(data->inbuf)) {
848 wpa_printf(MSG_INFO, "EAP-pwd: Buffer overflow attack "757 wpa_printf(MSG_INFO, "EAP-pwd: Buffer overflow attack "
@@ -869,7 +778,7 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret,
869 /*778 /*
870 * we're buffering and this is the last fragment779 * we're buffering and this is the last fragment
871 */780 */
872 if (data->in_frag_pos) {781 if (data->in_frag_pos && data->inbuf) {
873 wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",782 wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",
874 (int) len);783 (int) len);
875 pos = wpabuf_head_u8(data->inbuf);784 pos = wpabuf_head_u8(data->inbuf);
diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c
index f57649b..853ad27 100644
--- a/src/eap_server/eap_server_pwd.c
+++ b/src/eap_server/eap_server_pwd.c
@@ -10,6 +10,7 @@
1010
11#include "common.h"11#include "common.h"
12#include "crypto/sha256.h"12#include "crypto/sha256.h"
13#include "crypto/crypto.h"
13#include "eap_server/eap_i.h"14#include "eap_server/eap_i.h"
14#include "eap_common/eap_pwd_common.h"15#include "eap_common/eap_pwd_common.h"
1516
@@ -34,20 +35,18 @@ struct eap_pwd_data {
34 size_t out_frag_pos;35 size_t out_frag_pos;
35 size_t mtu;36 size_t mtu;
3637
37 BIGNUM *k;38 struct crypto_bignum *k;
38 BIGNUM *private_value;39 struct crypto_bignum *private_value;
39 BIGNUM *peer_scalar;40 struct crypto_bignum *peer_scalar;
40 BIGNUM *my_scalar;41 struct crypto_bignum *my_scalar;
41 EC_POINT *my_element;42 struct crypto_ec_point *my_element;
42 EC_POINT *peer_element;43 struct crypto_ec_point *peer_element;
4344
44 u8 my_confirm[SHA256_MAC_LEN];45 u8 my_confirm[SHA256_MAC_LEN];
4546
46 u8 msk[EAP_MSK_LEN];47 u8 msk[EAP_MSK_LEN];
47 u8 emsk[EAP_EMSK_LEN];48 u8 emsk[EAP_EMSK_LEN];
48 u8 session_id[1 + SHA256_MAC_LEN];49 u8 session_id[1 + SHA256_MAC_LEN];
49
50 BN_CTX *bnctx;
51};50};
5251
5352
@@ -113,15 +112,6 @@ static void * eap_pwd_init(struct eap_sm *sm)
113 data->password_len = sm->user->password_len;112 data->password_len = sm->user->password_len;
114 os_memcpy(data->password, sm->user->password, data->password_len);113 os_memcpy(data->password, sm->user->password, data->password_len);
115114
116 data->bnctx = BN_CTX_new();
117 if (data->bnctx == NULL) {
118 wpa_printf(MSG_INFO, "EAP-PWD: bn context allocation fail");
119 bin_clear_free(data->password, data->password_len);
120 bin_clear_free(data->id_server, data->id_server_len);
121 os_free(data);
122 return NULL;
123 }
124
125 data->in_frag_pos = data->out_frag_pos = 0;115 data->in_frag_pos = data->out_frag_pos = 0;
126 data->inbuf = data->outbuf = NULL;116 data->inbuf = data->outbuf = NULL;
127 /* use default MTU from RFC 5931 if not configured otherwise */117 /* use default MTU from RFC 5931 if not configured otherwise */
@@ -135,21 +125,18 @@ static void eap_pwd_reset(struct eap_sm *sm, void *priv)
135{125{
136 struct eap_pwd_data *data = priv;126 struct eap_pwd_data *data = priv;
137127
138 BN_clear_free(data->private_value);128 crypto_bignum_deinit(data->private_value, 1);
139 BN_clear_free(data->peer_scalar);129 crypto_bignum_deinit(data->peer_scalar, 1);
140 BN_clear_free(data->my_scalar);130 crypto_bignum_deinit(data->my_scalar, 1);
141 BN_clear_free(data->k);131 crypto_bignum_deinit(data->k, 1);
142 BN_CTX_free(data->bnctx);132 crypto_ec_point_deinit(data->my_element, 1);
143 EC_POINT_clear_free(data->my_element);133 crypto_ec_point_deinit(data->peer_element, 1);
144 EC_POINT_clear_free(data->peer_element);
145 bin_clear_free(data->id_peer, data->id_peer_len);134 bin_clear_free(data->id_peer, data->id_peer_len);
146 bin_clear_free(data->id_server, data->id_server_len);135 bin_clear_free(data->id_server, data->id_server_len);
147 bin_clear_free(data->password, data->password_len);136 bin_clear_free(data->password, data->password_len);
148 if (data->grp) {137 if (data->grp) {
149 EC_GROUP_free(data->grp->group);138 crypto_ec_deinit(data->grp->group);
150 EC_POINT_clear_free(data->grp->pwe);139 crypto_ec_point_deinit(data->grp->pwe, 1);
151 BN_clear_free(data->grp->order);
152 BN_clear_free(data->grp->prime);
153 os_free(data->grp);140 os_free(data->grp);
154 }141 }
155 wpabuf_free(data->inbuf);142 wpabuf_free(data->inbuf);
@@ -189,9 +176,9 @@ static void eap_pwd_build_id_req(struct eap_sm *sm, struct eap_pwd_data *data,
189static void eap_pwd_build_commit_req(struct eap_sm *sm,176static void eap_pwd_build_commit_req(struct eap_sm *sm,
190 struct eap_pwd_data *data, u8 id)177 struct eap_pwd_data *data, u8 id)
191{178{
192 BIGNUM *mask = NULL, *x = NULL, *y = NULL;179 struct crypto_bignum *mask = NULL;
193 u8 *scalar = NULL, *element = NULL;180 u8 *scalar = NULL, *element = NULL;
194 u16 offset;181 size_t prime_len, order_len;
195182
196 wpa_printf(MSG_DEBUG, "EAP-pwd: Commit/Request");183 wpa_printf(MSG_DEBUG, "EAP-pwd: Commit/Request");
197 /*184 /*
@@ -201,93 +188,75 @@ static void eap_pwd_build_commit_req(struct eap_sm *sm,
201 if (data->out_frag_pos)188 if (data->out_frag_pos)
202 return;189 return;
203190
204 if (((data->private_value = BN_new()) == NULL) ||191 prime_len = crypto_ec_prime_len(data->grp->group);
205 ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) ||192 order_len = crypto_ec_order_len(data->grp->group);
206 ((data->my_scalar = BN_new()) == NULL) ||193
207 ((mask = BN_new()) == NULL)) {194 data->private_value = crypto_bignum_init();
195 data->my_element = crypto_ec_point_init(data->grp->group);
196 data->my_scalar = crypto_bignum_init();
197 mask = crypto_bignum_init();
198 if (!data->private_value || !data->my_element || !data->my_scalar ||
199 !mask) {
208 wpa_printf(MSG_INFO, "EAP-PWD (server): scalar allocation "200 wpa_printf(MSG_INFO, "EAP-PWD (server): scalar allocation "
209 "fail");201 "fail");
210 goto fin;202 goto fin;
211 }203 }
212204
213 if (BN_rand_range(data->private_value, data->grp->order) != 1 ||205 if (crypto_bignum_rand(data->private_value,
214 BN_rand_range(mask, data->grp->order) != 1 ||206 crypto_ec_get_order(data->grp->group)) < 0 ||
215 BN_add(data->my_scalar, data->private_value, mask) != 1 ||207 crypto_bignum_rand(mask,
216 BN_mod(data->my_scalar, data->my_scalar, data->grp->order,208 crypto_ec_get_order(data->grp->group)) < 0 ||
217 data->bnctx) != 1) {209 crypto_bignum_add(data->private_value, mask, data->my_scalar) < 0 ||
210 crypto_bignum_mod(data->my_scalar,
211 crypto_ec_get_order(data->grp->group),
212 data->my_scalar) < 0) {
218 wpa_printf(MSG_INFO,213 wpa_printf(MSG_INFO,
219 "EAP-pwd (server): unable to get randomness");214 "EAP-pwd (server): unable to get randomness");
220 goto fin;215 goto fin;
221 }216 }
222217
223 if (!EC_POINT_mul(data->grp->group, data->my_element, NULL,218 if (crypto_ec_point_mul(data->grp->group, data->grp->pwe, mask,
224 data->grp->pwe, mask, data->bnctx)) {219 data->my_element) < 0) {
225 wpa_printf(MSG_INFO, "EAP-PWD (server): element allocation "220 wpa_printf(MSG_INFO, "EAP-PWD (server): element allocation "
226 "fail");221 "fail");
227 eap_pwd_state(data, FAILURE);222 eap_pwd_state(data, FAILURE);
228 goto fin;223 goto fin;
229 }224 }
230225
231 if (!EC_POINT_invert(data->grp->group, data->my_element, data->bnctx))226 if (crypto_ec_point_invert(data->grp->group, data->my_element) < 0) {
232 {
233 wpa_printf(MSG_INFO, "EAP-PWD (server): element inversion "227 wpa_printf(MSG_INFO, "EAP-PWD (server): element inversion "
234 "fail");228 "fail");
235 goto fin;229 goto fin;
236 }230 }
237 BN_clear_free(mask);
238231
239 if (((x = BN_new()) == NULL) ||232 scalar = os_malloc(order_len);
240 ((y = BN_new()) == NULL)) {233 element = os_malloc(prime_len * 2);
241 wpa_printf(MSG_INFO, "EAP-PWD (server): point allocation "234 if (!scalar || !element) {
242 "fail");235 wpa_printf(MSG_INFO, "EAP-PWD (server): data allocation fail");
243 goto fin;236 goto fin;
244 }237 }
245 if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,238
246 data->my_element, x, y,239 if (crypto_ec_point_to_bin(data->grp->group, data->my_element, element,
247 data->bnctx)) {240 element + prime_len) < 0) {
248 wpa_printf(MSG_INFO, "EAP-PWD (server): point assignment "241 wpa_printf(MSG_INFO, "EAP-PWD (server): point assignment "
249 "fail");242 "fail");
250 goto fin;243 goto fin;
251 }244 }
252245
253 if (((scalar = os_malloc(BN_num_bytes(data->grp->order))) == NULL) ||246 crypto_bignum_to_bin(data->my_scalar, scalar, order_len, order_len);
254 ((element = os_malloc(BN_num_bytes(data->grp->prime) * 2)) ==
255 NULL)) {
256 wpa_printf(MSG_INFO, "EAP-PWD (server): data allocation fail");
257 goto fin;
258 }
259247
260 /*248 data->outbuf = wpabuf_alloc(2 * prime_len + order_len);
261 * bignums occupy as little memory as possible so one that is
262 * sufficiently smaller than the prime or order might need pre-pending
263 * with zeros.
264 */
265 os_memset(scalar, 0, BN_num_bytes(data->grp->order));
266 os_memset(element, 0, BN_num_bytes(data->grp->prime) * 2);
267 offset = BN_num_bytes(data->grp->order) -
268 BN_num_bytes(data->my_scalar);
269 BN_bn2bin(data->my_scalar, scalar + offset);
270
271 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
272 BN_bn2bin(x, element + offset);
273 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
274 BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset);
275
276 data->outbuf = wpabuf_alloc(2 * BN_num_bytes(data->grp->prime) +
277 BN_num_bytes(data->grp->order));
278 if (data->outbuf == NULL)249 if (data->outbuf == NULL)
279 goto fin;250 goto fin;
280251
281 /* We send the element as (x,y) followed by the scalar */252 /* We send the element as (x,y) followed by the scalar */
282 wpabuf_put_data(data->outbuf, element,253 wpabuf_put_data(data->outbuf, element, 2 * prime_len);
283 2 * BN_num_bytes(data->grp->prime));254 wpabuf_put_data(data->outbuf, scalar, order_len);
284 wpabuf_put_data(data->outbuf, scalar, BN_num_bytes(data->grp->order));
285255
286fin:256fin:
257 crypto_bignum_deinit(mask, 1);
287 os_free(scalar);258 os_free(scalar);
288 os_free(element);259 os_free(element);
289 BN_clear_free(x);
290 BN_clear_free(y);
291 if (data->outbuf == NULL)260 if (data->outbuf == NULL)
292 eap_pwd_state(data, FAILURE);261 eap_pwd_state(data, FAILURE);
293}262}
@@ -296,11 +265,10 @@ fin:
296static void eap_pwd_build_confirm_req(struct eap_sm *sm,265static void eap_pwd_build_confirm_req(struct eap_sm *sm,
297 struct eap_pwd_data *data, u8 id)266 struct eap_pwd_data *data, u8 id)
298{267{
299 BIGNUM *x = NULL, *y = NULL;
300 struct crypto_hash *hash;268 struct crypto_hash *hash;
301 u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;269 u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
302 u16 grp;270 u16 grp;
303 int offset;271 size_t prime_len, order_len;
304272
305 wpa_printf(MSG_DEBUG, "EAP-pwd: Confirm/Request");273 wpa_printf(MSG_DEBUG, "EAP-pwd: Confirm/Request");
306 /*274 /*
@@ -310,9 +278,12 @@ static void eap_pwd_build_confirm_req(struct eap_sm *sm,
310 if (data->out_frag_pos)278 if (data->out_frag_pos)
311 return;279 return;
312280
281 prime_len = crypto_ec_prime_len(data->grp->group);
282 order_len = crypto_ec_order_len(data->grp->group);
283
313 /* Each component of the cruft will be at most as big as the prime */284 /* Each component of the cruft will be at most as big as the prime */
314 if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||285 cruft = os_malloc(prime_len * 2);
315 ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {286 if (!cruft) {
316 wpa_printf(MSG_INFO, "EAP-PWD (server): debug allocation "287 wpa_printf(MSG_INFO, "EAP-PWD (server): debug allocation "
317 "fail");288 "fail");
318 goto fin;289 goto fin;
@@ -332,64 +303,38 @@ static void eap_pwd_build_confirm_req(struct eap_sm *sm,
332 *303 *
333 * First is k304 * First is k
334 */305 */
335 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));306 crypto_bignum_to_bin(data->k, cruft, prime_len, prime_len);
336 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);307 eap_pwd_h_update(hash, cruft, prime_len);
337 BN_bn2bin(data->k, cruft + offset);
338 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
339308
340 /* server element: x, y */309 /* server element: x, y */
341 if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,310 if (crypto_ec_point_to_bin(data->grp->group, data->my_element, cruft,
342 data->my_element, x, y,311 cruft + prime_len) < 0) {
343 data->bnctx)) {
344 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "312 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
345 "assignment fail");313 "assignment fail");
346 goto fin;314 goto fin;
347 }315 }
348316 eap_pwd_h_update(hash, cruft, prime_len * 2);
349 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
350 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
351 BN_bn2bin(x, cruft + offset);
352 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
353 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
354 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
355 BN_bn2bin(y, cruft + offset);
356 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
357317
358 /* server scalar */318 /* server scalar */
359 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));319 crypto_bignum_to_bin(data->my_scalar, cruft, order_len, order_len);
360 offset = BN_num_bytes(data->grp->order) -320 eap_pwd_h_update(hash, cruft, order_len);
361 BN_num_bytes(data->my_scalar);
362 BN_bn2bin(data->my_scalar, cruft + offset);
363 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
364321
365 /* peer element: x, y */322 /* peer element: x, y */
366 if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,323 if (crypto_ec_point_to_bin(data->grp->group, data->peer_element, cruft,
367 data->peer_element, x, y,324 cruft + prime_len) < 0) {
368 data->bnctx)) {
369 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "325 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
370 "assignment fail");326 "assignment fail");
371 goto fin;327 goto fin;
372 }328 }
373329 eap_pwd_h_update(hash, cruft, prime_len * 2);
374 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
375 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
376 BN_bn2bin(x, cruft + offset);
377 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
378 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
379 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
380 BN_bn2bin(y, cruft + offset);
381 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
382330
383 /* peer scalar */331 /* peer scalar */
384 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));332 crypto_bignum_to_bin(data->peer_scalar, cruft, order_len, order_len);
385 offset = BN_num_bytes(data->grp->order) -333 eap_pwd_h_update(hash, cruft, order_len);
386 BN_num_bytes(data->peer_scalar);
387 BN_bn2bin(data->peer_scalar, cruft + offset);
388 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
389334
390 /* ciphersuite */335 /* ciphersuite */
391 grp = htons(data->group_num);336 grp = htons(data->group_num);
392 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));337 os_memset(cruft, 0, prime_len);
393 ptr = cruft;338 ptr = cruft;
394 os_memcpy(ptr, &grp, sizeof(u16));339 os_memcpy(ptr, &grp, sizeof(u16));
395 ptr += sizeof(u16);340 ptr += sizeof(u16);
@@ -410,9 +355,7 @@ static void eap_pwd_build_confirm_req(struct eap_sm *sm,
410 wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN);355 wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN);
411356
412fin:357fin:
413 bin_clear_free(cruft, BN_num_bytes(data->grp->prime));358 bin_clear_free(cruft, prime_len * 2);
414 BN_clear_free(x);
415 BN_clear_free(y);
416 if (data->outbuf == NULL)359 if (data->outbuf == NULL)
417 eap_pwd_state(data, FAILURE);360 eap_pwd_state(data, FAILURE);
418}361}
@@ -604,7 +547,7 @@ static void eap_pwd_process_id_resp(struct eap_sm *sm,
604 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PWD (server): peer sent id of",547 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PWD (server): peer sent id of",
605 data->id_peer, data->id_peer_len);548 data->id_peer, data->id_peer_len);
606549
607 data->grp = os_zalloc(sizeof(EAP_PWD_group));550 data->grp = get_eap_pwd_group(data->group_num);
608 if (data->grp == NULL) {551 if (data->grp == NULL) {
609 wpa_printf(MSG_INFO, "EAP-PWD: failed to allocate memory for "552 wpa_printf(MSG_INFO, "EAP-PWD: failed to allocate memory for "
610 "group");553 "group");
@@ -620,7 +563,7 @@ static void eap_pwd_process_id_resp(struct eap_sm *sm,
620 return;563 return;
621 }564 }
622 wpa_printf(MSG_DEBUG, "EAP-PWD (server): computed %d bit PWE...",565 wpa_printf(MSG_DEBUG, "EAP-PWD (server): computed %d bit PWE...",
623 BN_num_bits(data->grp->prime));566 (int) crypto_ec_prime_len_bits(data->grp->group));
624567
625 eap_pwd_state(data, PWD_Commit_Req);568 eap_pwd_state(data, PWD_Commit_Req);
626}569}
@@ -630,16 +573,16 @@ static void
630eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,573eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
631 const u8 *payload, size_t payload_len)574 const u8 *payload, size_t payload_len)
632{575{
633 u8 *ptr;576 const u8 *ptr;
634 BIGNUM *x = NULL, *y = NULL, *cofactor = NULL;577 struct crypto_bignum *cofactor = NULL;
635 EC_POINT *K = NULL, *point = NULL;578 struct crypto_ec_point *K = NULL;
636 int res = 0;579 int res = 0;
637 size_t prime_len, order_len;580 size_t prime_len, order_len;
638581
639 wpa_printf(MSG_DEBUG, "EAP-pwd: Received commit response");582 wpa_printf(MSG_DEBUG, "EAP-pwd: Received commit response");
640583
641 prime_len = BN_num_bytes(data->grp->prime);584 prime_len = crypto_ec_prime_len(data->grp->group);
642 order_len = BN_num_bytes(data->grp->order);585 order_len = crypto_ec_order_len(data->grp->group);
643586
644 if (payload_len != 2 * prime_len + order_len) {587 if (payload_len != 2 * prime_len + order_len) {
645 wpa_printf(MSG_INFO,588 wpa_printf(MSG_INFO,
@@ -649,71 +592,62 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
649 goto fin;592 goto fin;
650 }593 }
651594
652 if (((data->peer_scalar = BN_new()) == NULL) ||595 data->k = crypto_bignum_init();
653 ((data->k = BN_new()) == NULL) ||596 cofactor = crypto_bignum_init();
654 ((cofactor = BN_new()) == NULL) ||597 K = crypto_ec_point_init(data->grp->group);
655 ((x = BN_new()) == NULL) ||598 if (!data->k || !cofactor || !K) {
656 ((y = BN_new()) == NULL) ||
657 ((point = EC_POINT_new(data->grp->group)) == NULL) ||
658 ((K = EC_POINT_new(data->grp->group)) == NULL) ||
659 ((data->peer_element = EC_POINT_new(data->grp->group)) == NULL)) {
660 wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation "599 wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation "
661 "fail");600 "fail");
662 goto fin;601 goto fin;
663 }602 }
664603
665 if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) {604 if (crypto_ec_cofactor(data->grp->group, cofactor) < 0) {
666 wpa_printf(MSG_INFO, "EAP-PWD (server): unable to get "605 wpa_printf(MSG_INFO, "EAP-PWD (server): unable to get "
667 "cofactor for curve");606 "cofactor for curve");
668 goto fin;607 goto fin;
669 }608 }
670609
671 /* element, x then y, followed by scalar */610 /* element, x then y, followed by scalar */
672 ptr = (u8 *) payload;611 ptr = payload;
673 BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x);612 data->peer_element = eap_pwd_get_element(data->grp, ptr);
674 ptr += BN_num_bytes(data->grp->prime);613 if (!data->peer_element) {
675 BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y);
676 ptr += BN_num_bytes(data->grp->prime);
677 BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->peer_scalar);
678 if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group,
679 data->peer_element, x, y,
680 data->bnctx)) {
681 wpa_printf(MSG_INFO, "EAP-PWD (server): setting peer element "614 wpa_printf(MSG_INFO, "EAP-PWD (server): setting peer element "
682 "fail");615 "fail");
683 goto fin;616 goto fin;
684 }617 }
618 ptr += prime_len * 2;
619 data->peer_scalar = eap_pwd_get_scalar(data->grp, ptr);
620 if (!data->peer_scalar) {
621 wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation "
622 "fail");
623 goto fin;
624 }
685625
686 /* check to ensure peer's element is not in a small sub-group */626 /* detect reflection attacks */
687 if (BN_cmp(cofactor, BN_value_one())) {627 if (crypto_bignum_cmp(data->my_scalar, data->peer_scalar) == 0 ||
688 if (!EC_POINT_mul(data->grp->group, point, NULL,628 crypto_ec_point_cmp(data->grp->group, data->my_element,
689 data->peer_element, cofactor, NULL)) {629 data->peer_element) == 0) {
690 wpa_printf(MSG_INFO, "EAP-PWD (server): cannot "630 wpa_printf(MSG_INFO,
691 "multiply peer element by order");631 "EAP-PWD (server): detected reflection attack!");
692 goto fin;632 goto fin;
693 }
694 if (EC_POINT_is_at_infinity(data->grp->group, point)) {
695 wpa_printf(MSG_INFO, "EAP-PWD (server): peer element "
696 "is at infinity!\n");
697 goto fin;
698 }
699 }633 }
700634
701 /* compute the shared key, k */635 /* compute the shared key, k */
702 if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe,636 if ((crypto_ec_point_mul(data->grp->group, data->grp->pwe,
703 data->peer_scalar, data->bnctx)) ||637 data->peer_scalar, K) < 0) ||
704 (!EC_POINT_add(data->grp->group, K, K, data->peer_element,638 (crypto_ec_point_add(data->grp->group, K, data->peer_element,
705 data->bnctx)) ||639 K) < 0) ||
706 (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value,640 (crypto_ec_point_mul(data->grp->group, K, data->private_value,
707 data->bnctx))) {641 K) < 0)) {
708 wpa_printf(MSG_INFO, "EAP-PWD (server): computing shared key "642 wpa_printf(MSG_INFO, "EAP-PWD (server): computing shared key "
709 "fail");643 "fail");
710 goto fin;644 goto fin;
711 }645 }
712646
713 /* ensure that the shared key isn't in a small sub-group */647 /* ensure that the shared key isn't in a small sub-group */
714 if (BN_cmp(cofactor, BN_value_one())) {648 if (!crypto_bignum_is_one(cofactor)) {
715 if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor,649 if (crypto_ec_point_mul(data->grp->group, K, cofactor,
716 NULL)) {650 K) != 0) {
717 wpa_printf(MSG_INFO, "EAP-PWD (server): cannot "651 wpa_printf(MSG_INFO, "EAP-PWD (server): cannot "
718 "multiply shared key point by order!\n");652 "multiply shared key point by order!\n");
719 goto fin;653 goto fin;
@@ -726,13 +660,12 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
726 * never going to happen it is a simple and safe check "just to be660 * never going to happen it is a simple and safe check "just to be
727 * sure" so let's be safe.661 * sure" so let's be safe.
728 */662 */
729 if (EC_POINT_is_at_infinity(data->grp->group, K)) {663 if (crypto_ec_point_is_at_infinity(data->grp->group, K)) {
730 wpa_printf(MSG_INFO, "EAP-PWD (server): shared key point is "664 wpa_printf(MSG_INFO, "EAP-PWD (server): shared key point is "
731 "at infinity");665 "at infinity");
732 goto fin;666 goto fin;
733 }667 }
734 if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k,668 if (crypto_ec_point_x(data->grp->group, K, data->k)) {
735 NULL, data->bnctx)) {
736 wpa_printf(MSG_INFO, "EAP-PWD (server): unable to extract "669 wpa_printf(MSG_INFO, "EAP-PWD (server): unable to extract "
737 "shared secret from secret point");670 "shared secret from secret point");
738 goto fin;671 goto fin;
@@ -740,11 +673,8 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
740 res = 1;673 res = 1;
741674
742fin:675fin:
743 EC_POINT_clear_free(K);676 crypto_ec_point_deinit(K, 1);
744 EC_POINT_clear_free(point);677 crypto_bignum_deinit(cofactor, 1);
745 BN_clear_free(cofactor);
746 BN_clear_free(x);
747 BN_clear_free(y);
748678
749 if (res)679 if (res)
750 eap_pwd_state(data, PWD_Confirm_Req);680 eap_pwd_state(data, PWD_Confirm_Req);
@@ -757,12 +687,14 @@ static void
757eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,687eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
758 const u8 *payload, size_t payload_len)688 const u8 *payload, size_t payload_len)
759{689{
760 BIGNUM *x = NULL, *y = NULL;
761 struct crypto_hash *hash;690 struct crypto_hash *hash;
762 u32 cs;691 u32 cs;
763 u16 grp;692 u16 grp;
764 u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;693 u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
765 int offset;694 size_t prime_len, order_len;
695
696 prime_len = crypto_ec_prime_len(data->grp->group);
697 order_len = crypto_ec_order_len(data->grp->group);
766698
767 if (payload_len != SHA256_MAC_LEN) {699 if (payload_len != SHA256_MAC_LEN) {
768 wpa_printf(MSG_INFO,700 wpa_printf(MSG_INFO,
@@ -781,8 +713,8 @@ eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
781 *ptr = EAP_PWD_DEFAULT_PRF;713 *ptr = EAP_PWD_DEFAULT_PRF;
782714
783 /* each component of the cruft will be at most as big as the prime */715 /* each component of the cruft will be at most as big as the prime */
784 if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||716 cruft = os_malloc(prime_len * 2);
785 ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {717 if (!cruft) {
786 wpa_printf(MSG_INFO, "EAP-PWD (peer): allocation fail");718 wpa_printf(MSG_INFO, "EAP-PWD (peer): allocation fail");
787 goto fin;719 goto fin;
788 }720 }
@@ -796,62 +728,36 @@ eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
796 goto fin;728 goto fin;
797729
798 /* k */730 /* k */
799 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));731 crypto_bignum_to_bin(data->k, cruft, prime_len, prime_len);
800 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);732 eap_pwd_h_update(hash, cruft, prime_len);
801 BN_bn2bin(data->k, cruft + offset);
802 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
803733
804 /* peer element: x, y */734 /* peer element: x, y */
805 if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,735 if (crypto_ec_point_to_bin(data->grp->group, data->peer_element, cruft,
806 data->peer_element, x, y,736 cruft + prime_len) < 0) {
807 data->bnctx)) {
808 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "737 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
809 "assignment fail");738 "assignment fail");
810 goto fin;739 goto fin;
811 }740 }
812 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));741 eap_pwd_h_update(hash, cruft, prime_len * 2);
813 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
814 BN_bn2bin(x, cruft + offset);
815 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
816 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
817 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
818 BN_bn2bin(y, cruft + offset);
819 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
820742
821 /* peer scalar */743 /* peer scalar */
822 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));744 crypto_bignum_to_bin(data->peer_scalar, cruft, order_len, order_len);
823 offset = BN_num_bytes(data->grp->order) -745 eap_pwd_h_update(hash, cruft, order_len);
824 BN_num_bytes(data->peer_scalar);
825 BN_bn2bin(data->peer_scalar, cruft + offset);
826 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
827746
828 /* server element: x, y */747 /* server element: x, y */
829 if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,748 if (crypto_ec_point_to_bin(data->grp->group, data->my_element, cruft,
830 data->my_element, x, y,749 cruft + prime_len) < 0) {
831 data->bnctx)) {
832 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "750 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
833 "assignment fail");751 "assignment fail");
834 goto fin;752 goto fin;
835 }753 }
836754 eap_pwd_h_update(hash, cruft, prime_len * 2);
837 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
838 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
839 BN_bn2bin(x, cruft + offset);
840 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
841 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
842 offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
843 BN_bn2bin(y, cruft + offset);
844 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
845755
846 /* server scalar */756 /* server scalar */
847 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));757 crypto_bignum_to_bin(data->my_scalar, cruft, order_len, order_len);
848 offset = BN_num_bytes(data->grp->order) -758 eap_pwd_h_update(hash, cruft, order_len);
849 BN_num_bytes(data->my_scalar);
850 BN_bn2bin(data->my_scalar, cruft + offset);
851 eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
852759
853 /* ciphersuite */760 /* ciphersuite */
854 os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
855 eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));761 eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));
856762
857 /* all done */763 /* all done */
@@ -865,7 +771,7 @@ eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
865 }771 }
866772
867 wpa_printf(MSG_DEBUG, "EAP-pwd (server): confirm verified");773 wpa_printf(MSG_DEBUG, "EAP-pwd (server): confirm verified");
868 if (compute_keys(data->grp, data->bnctx, data->k,774 if (compute_keys(data->grp, data->k,
869 data->peer_scalar, data->my_scalar, conf,775 data->peer_scalar, data->my_scalar, conf,
870 data->my_confirm, &cs, data->msk, data->emsk,776 data->my_confirm, &cs, data->msk, data->emsk,
871 data->session_id) < 0)777 data->session_id) < 0)
@@ -874,9 +780,7 @@ eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
874 eap_pwd_state(data, SUCCESS);780 eap_pwd_state(data, SUCCESS);
875781
876fin:782fin:
877 bin_clear_free(cruft, BN_num_bytes(data->grp->prime));783 bin_clear_free(cruft, prime_len * 2);
878 BN_clear_free(x);
879 BN_clear_free(y);
880}784}
881785
882786
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index f8a11ea..7d20b98 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -2004,6 +2004,17 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
20042004
2005 if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) &&2005 if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) &&
2006 (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {2006 (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
2007 /*
2008 * Only decrypt the Key Data field if the frame's authenticity
2009 * was verified. When using AES-SIV (FILS), the MIC flag is not
2010 * set, so this check should only be performed if mic_len != 0
2011 * which is the case in this code branch.
2012 */
2013 if (!(key_info & WPA_KEY_INFO_MIC)) {
2014 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2015 "WPA: Ignore EAPOL-Key with encrypted but unauthenticated data");
2016 goto out;
2017 }
2007 if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data,2018 if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data,
2008 &key_data_len))2019 &key_data_len))
2009 goto out;2020 goto out;
diff --git a/src/utils/common.c b/src/utils/common.c
index 5fd795f..66668b0 100644
--- a/src/utils/common.c
+++ b/src/utils/common.c
@@ -671,6 +671,29 @@ int is_hex(const u8 *data, size_t len)
671}671}
672672
673673
674int has_ctrl_char(const u8 *data, size_t len)
675{
676 size_t i;
677
678 for (i = 0; i < len; i++) {
679 if (data[i] < 32 || data[i] == 127)
680 return 1;
681 }
682 return 0;
683}
684
685
686int has_newline(const char *str)
687{
688 while (*str) {
689 if (*str == '\n' || *str == '\r')
690 return 1;
691 str++;
692 }
693 return 0;
694}
695
696
674size_t merge_byte_arrays(u8 *res, size_t res_len,697size_t merge_byte_arrays(u8 *res, size_t res_len,
675 const u8 *src1, size_t src1_len,698 const u8 *src1, size_t src1_len,
676 const u8 *src2, size_t src2_len)699 const u8 *src2, size_t src2_len)
diff --git a/src/utils/common.h b/src/utils/common.h
index 576e8e7..a5a3bdf 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -501,6 +501,8 @@ const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len);
501501
502char * wpa_config_parse_string(const char *value, size_t *len);502char * wpa_config_parse_string(const char *value, size_t *len);
503int is_hex(const u8 *data, size_t len);503int is_hex(const u8 *data, size_t len);
504int has_ctrl_char(const u8 *data, size_t len);
505int has_newline(const char *str);
504size_t merge_byte_arrays(u8 *res, size_t res_len,506size_t merge_byte_arrays(u8 *res, size_t res_len,
505 const u8 *src1, size_t src1_len,507 const u8 *src1, size_t src1_len,
506 const u8 *src2, size_t src2_len);508 const u8 *src2, size_t src2_len);
diff --git a/src/utils/const_time.h b/src/utils/const_time.h
507new file mode 100644509new file mode 100644
index 0000000..ab8f611
--- /dev/null
+++ b/src/utils/const_time.h
@@ -0,0 +1,191 @@
1/*
2 * Helper functions for constant time operations
3 * Copyright (c) 2019, The Linux Foundation
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 *
8 * These helper functions can be used to implement logic that needs to minimize
9 * externally visible differences in execution path by avoiding use of branches,
10 * avoiding early termination or other time differences, and forcing same memory
11 * access pattern regardless of values.
12 */
13
14#ifndef CONST_TIME_H
15#define CONST_TIME_H
16
17
18#if defined(__clang__)
19#define NO_UBSAN_UINT_OVERFLOW \
20 __attribute__((no_sanitize("unsigned-integer-overflow")))
21#else
22#define NO_UBSAN_UINT_OVERFLOW
23#endif
24
25
26/**
27 * const_time_fill_msb - Fill all bits with MSB value
28 * @val: Input value
29 * Returns: Value with all the bits set to the MSB of the input val
30 */
31static inline unsigned int const_time_fill_msb(unsigned int val)
32{
33 /* Move the MSB to LSB and multiple by -1 to fill in all bits. */
34 return (val >> (sizeof(val) * 8 - 1)) * ~0U;
35}
36
37
38/* Returns: -1 if val is zero; 0 if val is not zero */
39static inline unsigned int const_time_is_zero(unsigned int val)
40 NO_UBSAN_UINT_OVERFLOW
41{
42 /* Set MSB to 1 for 0 and fill rest of bits with the MSB value */
43 return const_time_fill_msb(~val & (val - 1));
44}
45
46
47/* Returns: -1 if a == b; 0 if a != b */
48static inline unsigned int const_time_eq(unsigned int a, unsigned int b)
49{
50 return const_time_is_zero(a ^ b);
51}
52
53
54/* Returns: -1 if a == b; 0 if a != b */
55static inline u8 const_time_eq_u8(unsigned int a, unsigned int b)
56{
57 return (u8) const_time_eq(a, b);
58}
59
60
61/**
62 * const_time_eq_bin - Constant time memory comparison
63 * @a: First buffer to compare
64 * @b: Second buffer to compare
65 * @len: Number of octets to compare
66 * Returns: -1 if buffers are equal, 0 if not
67 *
68 * This function is meant for comparing passwords or hash values where
69 * difference in execution time or memory access pattern could provide external
70 * observer information about the location of the difference in the memory
71 * buffers. The return value does not behave like memcmp(), i.e.,
72 * const_time_eq_bin() cannot be used to sort items into a defined order. Unlike
73 * memcmp(), the execution time of const_time_eq_bin() does not depend on the
74 * contents of the compared memory buffers, but only on the total compared
75 * length.
76 */
77static inline unsigned int const_time_eq_bin(const void *a, const void *b,
78 size_t len)
79{
80 const u8 *aa = a;
81 const u8 *bb = b;
82 size_t i;
83 u8 res = 0;
84
85 for (i = 0; i < len; i++)
86 res |= aa[i] ^ bb[i];
87
88 return const_time_is_zero(res);
89}
90
91
92/**
93 * const_time_select - Constant time unsigned int selection
94 * @mask: 0 (false) or -1 (true) to identify which value to select
95 * @true_val: Value to select for the true case
96 * @false_val: Value to select for the false case
97 * Returns: true_val if mask == -1, false_val if mask == 0
98 */
99static inline unsigned int const_time_select(unsigned int mask,
100 unsigned int true_val,
101 unsigned int false_val)
102{
103 return (mask & true_val) | (~mask & false_val);
104}
105
106
107/**
108 * const_time_select_int - Constant time int selection
109 * @mask: 0 (false) or -1 (true) to identify which value to select
110 * @true_val: Value to select for the true case
111 * @false_val: Value to select for the false case
112 * Returns: true_val if mask == -1, false_val if mask == 0
113 */
114static inline int const_time_select_int(unsigned int mask, int true_val,
115 int false_val)
116{
117 return (int) const_time_select(mask, (unsigned int) true_val,
118 (unsigned int) false_val);
119}
120
121
122/**
123 * const_time_select_u8 - Constant time u8 selection
124 * @mask: 0 (false) or -1 (true) to identify which value to select
125 * @true_val: Value to select for the true case
126 * @false_val: Value to select for the false case
127 * Returns: true_val if mask == -1, false_val if mask == 0
128 */
129static inline u8 const_time_select_u8(u8 mask, u8 true_val, u8 false_val)
130{
131 return (u8) const_time_select(mask, true_val, false_val);
132}
133
134
135/**
136 * const_time_select_s8 - Constant time s8 selection
137 * @mask: 0 (false) or -1 (true) to identify which value to select
138 * @true_val: Value to select for the true case
139 * @false_val: Value to select for the false case
140 * Returns: true_val if mask == -1, false_val if mask == 0
141 */
142static inline s8 const_time_select_s8(u8 mask, s8 true_val, s8 false_val)
143{
144 return (s8) const_time_select(mask, (unsigned int) true_val,
145 (unsigned int) false_val);
146}
147
148
149/**
150 * const_time_select_bin - Constant time binary buffer selection copy
151 * @mask: 0 (false) or -1 (true) to identify which value to copy
152 * @true_val: Buffer to copy for the true case
153 * @false_val: Buffer to copy for the false case
154 * @len: Number of octets to copy
155 * @dst: Destination buffer for the copy
156 *
157 * This function copies the specified buffer into the destination buffer using
158 * operations with identical memory access pattern regardless of which buffer
159 * is being copied.
160 */
161static inline void const_time_select_bin(u8 mask, const u8 *true_val,
162 const u8 *false_val, size_t len,
163 u8 *dst)
164{
165 size_t i;
166
167 for (i = 0; i < len; i++)
168 dst[i] = const_time_select_u8(mask, true_val[i], false_val[i]);
169}
170
171
172static inline int const_time_memcmp(const void *a, const void *b, size_t len)
173{
174 const u8 *aa = a;
175 const u8 *bb = b;
176 int diff, res = 0;
177 unsigned int mask;
178
179 if (len == 0)
180 return 0;
181 do {
182 len--;
183 diff = (int) aa[len] - (int) bb[len];
184 mask = const_time_is_zero((unsigned int) diff);
185 res = const_time_select_int(mask, res, diff);
186 } while (len);
187
188 return res;
189}
190
191#endif /* CONST_TIME_H */
diff --git a/src/wps/wps.h b/src/wps/wps.h
index 0a7f65d..c10dc4f 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -826,7 +826,7 @@ int wps_build_credential_wrap(struct wpabuf *msg,
826826
827unsigned int wps_pin_checksum(unsigned int pin);827unsigned int wps_pin_checksum(unsigned int pin);
828unsigned int wps_pin_valid(unsigned int pin);828unsigned int wps_pin_valid(unsigned int pin);
829unsigned int wps_generate_pin(void);829int wps_generate_pin(unsigned int *pin);
830int wps_pin_str_valid(const char *pin);830int wps_pin_str_valid(const char *pin);
831void wps_free_pending_msgs(struct upnp_pending_message *msgs);831void wps_free_pending_msgs(struct upnp_pending_message *msgs);
832832
diff --git a/src/wps/wps_attr_process.c b/src/wps/wps_attr_process.c
index eadb22f..e8c4579 100644
--- a/src/wps/wps_attr_process.c
+++ b/src/wps/wps_attr_process.c
@@ -229,6 +229,16 @@ static int wps_workaround_cred_key(struct wps_credential *cred)
229 cred->key_len--;229 cred->key_len--;
230#endif /* CONFIG_WPS_STRICT */230#endif /* CONFIG_WPS_STRICT */
231 }231 }
232
233
234 if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) &&
235 (cred->key_len < 8 || has_ctrl_char(cred->key, cred->key_len))) {
236 wpa_printf(MSG_INFO, "WPS: Reject credential with invalid WPA/WPA2-Personal passphrase");
237 wpa_hexdump_ascii_key(MSG_INFO, "WPS: Network Key",
238 cred->key, cred->key_len);
239 return -1;
240 }
241
232 return 0;242 return 0;
233}243}
234244
diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c
index c1ede6a..ca11901 100644
--- a/src/wps/wps_common.c
+++ b/src/wps/wps_common.c
@@ -235,20 +235,18 @@ unsigned int wps_pin_valid(unsigned int pin)
235 * wps_generate_pin - Generate a random PIN235 * wps_generate_pin - Generate a random PIN
236 * Returns: Eight digit PIN (i.e., including the checksum digit)236 * Returns: Eight digit PIN (i.e., including the checksum digit)
237 */237 */
238unsigned int wps_generate_pin(void)238int wps_generate_pin(unsigned int *pin)
239{239{
240 unsigned int val;240 unsigned int val;
241241
242 /* Generate seven random digits for the PIN */242 /* Generate seven random digits for the PIN */
243 if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) {243 if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0)
244 struct os_time now;244 return -1;
245 os_get_time(&now);
246 val = os_random() ^ now.sec ^ now.usec;
247 }
248 val %= 10000000;245 val %= 10000000;
249246
250 /* Append checksum digit */247 /* Append checksum digit */
251 return val * 10 + wps_pin_checksum(val);248 *pin = val * 10 + wps_pin_checksum(val);
249 return 0;
252}250}
253251
254252
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 579582b..cb66e99 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -626,6 +626,7 @@ OBJS += src/eap_peer/eap_pwd.c src/eap_common/eap_pwd_common.c
626OBJS_h += src/eap_server/eap_server_pwd.c626OBJS_h += src/eap_server/eap_server_pwd.c
627CONFIG_IEEE8021X_EAPOL=y627CONFIG_IEEE8021X_EAPOL=y
628NEED_SHA256=y628NEED_SHA256=y
629NEED_ECC=y
629endif630endif
630631
631ifdef CONFIG_EAP_EKE632ifdef CONFIG_EAP_EKE
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index d9a11be..a2d6619 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -630,6 +630,7 @@ OBJS += ../src/eap_peer/eap_pwd.o ../src/eap_common/eap_pwd_common.o
630OBJS_h += ../src/eap_server/eap_server_pwd.o630OBJS_h += ../src/eap_server/eap_server_pwd.o
631CONFIG_IEEE8021X_EAPOL=y631CONFIG_IEEE8021X_EAPOL=y
632NEED_SHA256=y632NEED_SHA256=y
633NEED_ECC=y
633endif634endif
634635
635ifdef CONFIG_EAP_EKE636ifdef CONFIG_EAP_EKE
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 7ecf7a8..96a1d9a 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -836,7 +836,10 @@ int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
836 return -1;836 return -1;
837837
838 if (pin == NULL) {838 if (pin == NULL) {
839 unsigned int rpin = wps_generate_pin();839 unsigned int rpin;
840
841 if (wps_generate_pin(&rpin) < 0)
842 return -1;
840 ret_len = os_snprintf(buf, buflen, "%08d", rpin);843 ret_len = os_snprintf(buf, buflen, "%08d", rpin);
841 if (os_snprintf_error(buflen, ret_len))844 if (os_snprintf_error(buflen, ret_len))
842 return -1;845 return -1;
@@ -902,7 +905,8 @@ const char * wpas_wps_ap_pin_random(struct wpa_supplicant *wpa_s, int timeout)
902 if (wpa_s->ap_iface == NULL)905 if (wpa_s->ap_iface == NULL)
903 return NULL;906 return NULL;
904 hapd = wpa_s->ap_iface->bss[0];907 hapd = wpa_s->ap_iface->bss[0];
905 pin = wps_generate_pin();908 if (wps_generate_pin(&pin) < 0)
909 return NULL;
906 os_snprintf(pin_txt, sizeof(pin_txt), "%08u", pin);910 os_snprintf(pin_txt, sizeof(pin_txt), "%08u", pin);
907 os_free(hapd->conf->ap_pin);911 os_free(hapd->conf->ap_pin);
908 hapd->conf->ap_pin = os_strdup(pin_txt);912 hapd->conf->ap_pin = os_strdup(pin_txt);
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 8e6cd20..e095cf7 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -455,6 +455,12 @@ static int wpa_config_parse_psk(const struct parse_data *data,
455 }455 }
456 wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",456 wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
457 (u8 *) value, len);457 (u8 *) value, len);
458 if (has_ctrl_char((u8 *) value, len)) {
459 wpa_printf(MSG_ERROR,
460 "Line %d: Invalid passphrase character",
461 line);
462 return -1;
463 }
458 if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&464 if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
459 os_memcmp(ssid->passphrase, value, len) == 0)465 os_memcmp(ssid->passphrase, value, len) == 0)
460 return 0;466 return 0;
@@ -2586,8 +2592,19 @@ char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
25862592
2587 for (i = 0; i < NUM_SSID_FIELDS; i++) {2593 for (i = 0; i < NUM_SSID_FIELDS; i++) {
2588 const struct parse_data *field = &ssid_fields[i];2594 const struct parse_data *field = &ssid_fields[i];
2589 if (os_strcmp(var, field->name) == 0)2595 if (os_strcmp(var, field->name) == 0) {
2590 return field->writer(field, ssid);2596 char *ret = field->writer(field, ssid);
2597
2598 if (ret && has_newline(ret)) {
2599 wpa_printf(MSG_ERROR,
2600 "Found newline in value for %s; not returning it",
2601 var);
2602 os_free(ret);
2603 ret = NULL;
2604 }
2605
2606 return ret;
2607 }
2591 }2608 }
25922609
2593 return NULL;2610 return NULL;
@@ -2772,6 +2789,8 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
27722789
2773 if (os_strcmp(var, "password") == 0 &&2790 if (os_strcmp(var, "password") == 0 &&
2774 os_strncmp(value, "ext:", 4) == 0) {2791 os_strncmp(value, "ext:", 4) == 0) {
2792 if (has_newline(value))
2793 return -1;
2775 str_clear_free(cred->password);2794 str_clear_free(cred->password);
2776 cred->password = os_strdup(value);2795 cred->password = os_strdup(value);
2777 cred->ext_password = 1;2796 cred->ext_password = 1;
@@ -2822,9 +2841,14 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
2822 }2841 }
28232842
2824 val = wpa_config_parse_string(value, &len);2843 val = wpa_config_parse_string(value, &len);
2825 if (val == NULL) {2844 if (val == NULL ||
2845 (os_strcmp(var, "excluded_ssid") != 0 &&
2846 os_strcmp(var, "roaming_consortium") != 0 &&
2847 os_strcmp(var, "required_roaming_consortium") != 0 &&
2848 has_newline(val))) {
2826 wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string "2849 wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string "
2827 "value '%s'.", line, var, value);2850 "value '%s'.", line, var, value);
2851 os_free(val);
2828 return -1;2852 return -1;
2829 }2853 }
28302854
@@ -3625,6 +3649,12 @@ static int wpa_global_config_parse_str(const struct global_parse_data *data,
3625 return -1;3649 return -1;
3626 }3650 }
36273651
3652 if (has_newline(pos)) {
3653 wpa_printf(MSG_ERROR, "Line %d: invalid %s value with newline",
3654 line, data->name);
3655 return -1;
3656 }
3657
3628 tmp = os_strdup(pos);3658 tmp = os_strdup(pos);
3629 if (tmp == NULL)3659 if (tmp == NULL)
3630 return -1;3660 return -1;
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 79280af..d030ef7 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -893,7 +893,8 @@ static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
893 if (os_strcmp(cmd, "any") == 0)893 if (os_strcmp(cmd, "any") == 0)
894 _bssid = NULL;894 _bssid = NULL;
895 else if (os_strcmp(cmd, "get") == 0) {895 else if (os_strcmp(cmd, "get") == 0) {
896 ret = wps_generate_pin();896 if (wps_generate_pin((unsigned int *) &ret) < 0)
897 return -1;
897 goto done;898 goto done;
898 } else if (hwaddr_aton(cmd, bssid)) {899 } else if (hwaddr_aton(cmd, bssid)) {
899 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",900 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index b200ca0..511bc9d 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -3671,7 +3671,13 @@ static void wpas_prov_disc_req(void *ctx, const u8 *peer, u16 config_methods,
3671 params[sizeof(params) - 1] = '\0';3671 params[sizeof(params) - 1] = '\0';
36723672
3673 if (config_methods & WPS_CONFIG_DISPLAY) {3673 if (config_methods & WPS_CONFIG_DISPLAY) {
3674 generated_pin = wps_generate_pin();3674 if (wps_generate_pin(&generated_pin) < 0) {
3675 wpa_printf(MSG_DEBUG, "P2P: Could not generate PIN");
3676 wpas_notify_p2p_provision_discovery(
3677 wpa_s, peer, 0 /* response */,
3678 P2P_PROV_DISC_INFO_UNAVAILABLE, 0, 0);
3679 return;
3680 }
3675 wpas_prov_disc_local_display(wpa_s, peer, params,3681 wpas_prov_disc_local_display(wpa_s, peer, params,
3676 generated_pin);3682 generated_pin);
3677 } else if (config_methods & WPS_CONFIG_KEYPAD)3683 } else if (config_methods & WPS_CONFIG_KEYPAD)
@@ -3716,7 +3722,13 @@ static void wpas_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods)
3716 if (config_methods & WPS_CONFIG_DISPLAY)3722 if (config_methods & WPS_CONFIG_DISPLAY)
3717 wpas_prov_disc_local_keypad(wpa_s, peer, params);3723 wpas_prov_disc_local_keypad(wpa_s, peer, params);
3718 else if (config_methods & WPS_CONFIG_KEYPAD) {3724 else if (config_methods & WPS_CONFIG_KEYPAD) {
3719 generated_pin = wps_generate_pin();3725 if (wps_generate_pin(&generated_pin) < 0) {
3726 wpa_printf(MSG_DEBUG, "P2P: Could not generate PIN");
3727 wpas_notify_p2p_provision_discovery(
3728 wpa_s, peer, 0 /* response */,
3729 P2P_PROV_DISC_INFO_UNAVAILABLE, 0, 0);
3730 return;
3731 }
3720 wpas_prov_disc_local_display(wpa_s, peer, params,3732 wpas_prov_disc_local_display(wpa_s, peer, params,
3721 generated_pin);3733 generated_pin);
3722 } else if (config_methods & WPS_CONFIG_PUSHBUTTON)3734 } else if (config_methods & WPS_CONFIG_PUSHBUTTON)
@@ -6065,7 +6077,8 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
6065 if (pin)6077 if (pin)
6066 os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));6078 os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
6067 else if (wps_method == WPS_PIN_DISPLAY) {6079 else if (wps_method == WPS_PIN_DISPLAY) {
6068 ret = wps_generate_pin();6080 if (wps_generate_pin((unsigned int *) &ret) < 0)
6081 return -1;
6069 res = os_snprintf(wpa_s->p2p_pin, sizeof(wpa_s->p2p_pin),6082 res = os_snprintf(wpa_s->p2p_pin, sizeof(wpa_s->p2p_pin),
6070 "%08d", ret);6083 "%08d", ret);
6071 if (os_snprintf_error(sizeof(wpa_s->p2p_pin), res))6084 if (os_snprintf_error(sizeof(wpa_s->p2p_pin), res))
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index eabe986..7691349 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -1195,7 +1195,10 @@ static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s,
1195 os_snprintf(val, sizeof(val), "\"dev_pw_id=%u%s\"",1195 os_snprintf(val, sizeof(val), "\"dev_pw_id=%u%s\"",
1196 dev_pw_id, hash);1196 dev_pw_id, hash);
1197 } else {1197 } else {
1198 rpin = wps_generate_pin();1198 if (wps_generate_pin(&rpin) < 0) {
1199 wpa_printf(MSG_DEBUG, "WPS: Could not generate PIN");
1200 return -1;
1201 }
1199 os_snprintf(val, sizeof(val), "\"pin=%08d dev_pw_id=%u%s\"",1202 os_snprintf(val, sizeof(val), "\"pin=%08d dev_pw_id=%u%s\"",
1200 rpin, dev_pw_id, hash);1203 rpin, dev_pw_id, hash);
1201 }1204 }

Subscribers

People subscribed via source and target branches

to all changes: