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
1diff --git a/hostapd/Android.mk b/hostapd/Android.mk
2index 6fcefdd..47dcb77 100644
3--- a/hostapd/Android.mk
4+++ b/hostapd/Android.mk
5@@ -382,6 +382,7 @@ ifdef CONFIG_EAP_PWD
6 L_CFLAGS += -DEAP_SERVER_PWD
7 OBJS += src/eap_server/eap_server_pwd.c src/eap_common/eap_pwd_common.c
8 NEED_SHA256=y
9+NEED_ECC=y
10 endif
11
12 ifdef CONFIG_EAP_EKE
13diff --git a/hostapd/Makefile b/hostapd/Makefile
14index eace68c..c6f70cd 100644
15--- a/hostapd/Makefile
16+++ b/hostapd/Makefile
17@@ -377,6 +377,7 @@ ifdef CONFIG_EAP_PWD
18 CFLAGS += -DEAP_SERVER_PWD
19 OBJS += ../src/eap_server/eap_server_pwd.o ../src/eap_common/eap_pwd_common.o
20 NEED_SHA256=y
21+NEED_ECC=y
22 endif
23
24 ifdef CONFIG_EAP_EKE
25diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
26index b0e8b0b..d5ca84d 100644
27--- a/src/ap/wps_hostapd.c
28+++ b/src/ap/wps_hostapd.c
29@@ -1561,7 +1561,8 @@ const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout)
30 unsigned int pin;
31 struct wps_ap_pin_data data;
32
33- pin = wps_generate_pin();
34+ if (wps_generate_pin(&pin) < 0)
35+ return NULL;
36 os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%08u", pin);
37 data.timeout = timeout;
38 hostapd_wps_for_each(hapd, wps_ap_pin_set, &data);
39diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
40index f2d5662..c7cb090 100644
41--- a/src/crypto/crypto.h
42+++ b/src/crypto/crypto.h
43@@ -391,6 +391,13 @@ int __must_check crypto_public_key_decrypt_pkcs1(
44 struct crypto_public_key *key, const u8 *crypt, size_t crypt_len,
45 u8 *plain, size_t *plain_len);
46
47+int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
48+ u8 *pubkey);
49+int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
50+ const u8 *privkey, size_t privkey_len,
51+ const u8 *pubkey, size_t pubkey_len,
52+ u8 *secret, size_t *len);
53+
54 /**
55 * crypto_global_init - Initialize crypto wrapper
56 *
57@@ -503,6 +510,14 @@ int crypto_bignum_to_bin(const struct crypto_bignum *a,
58 u8 *buf, size_t buflen, size_t padlen);
59
60 /**
61+ * crypto_bignum_rand - Create a random number in range of modulus
62+ * @r: Bignum; set to a random value
63+ * @m: Bignum; modulus
64+ * Returns: 0 on success, -1 on failure
65+ */
66+int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m);
67+
68+/**
69 * crypto_bignum_add - c = a + b
70 * @a: Bignum
71 * @b: Bignum
72@@ -584,6 +599,16 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a,
73 struct crypto_bignum *d);
74
75 /**
76+ * crypto_bignum_rshift - r = a >> n
77+ * @a: Bignum
78+ * @n: Number of bits
79+ * @r: Bignum; used to store the result of a >> n
80+ * Returns: 0 on success, -1 on failure
81+ */
82+int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
83+ struct crypto_bignum *r);
84+
85+/**
86 * crypto_bignum_cmp - Compare two bignums
87 * @a: Bignum
88 * @b: Bignum
89@@ -614,6 +639,22 @@ int crypto_bignum_is_zero(const struct crypto_bignum *a);
90 int crypto_bignum_is_one(const struct crypto_bignum *a);
91
92 /**
93+ * crypto_bignum_is_odd - Is the given bignum odd
94+ * @a: Bignum
95+ * Returns: 1 if @a is odd or 0 if not
96+ */
97+int crypto_bignum_is_odd(const struct crypto_bignum *a);
98+
99+/**
100+ * crypto_bignum_legendre - Compute the Legendre symbol (a/p)
101+ * @a: Bignum
102+ * @p: Bignum
103+ * Returns: Legendre symbol -1,0,1 on success; -2 on calculation failure
104+ */
105+int crypto_bignum_legendre(const struct crypto_bignum *a,
106+ const struct crypto_bignum *p);
107+
108+/**
109 * struct crypto_ec - Elliptic curve context
110 *
111 * Internal data structure for EC implementation. The contents is specific
112@@ -636,6 +677,14 @@ struct crypto_ec * crypto_ec_init(int group);
113 void crypto_ec_deinit(struct crypto_ec *e);
114
115 /**
116+ * crypto_ec_cofactor - Set the cofactor into the big number
117+ * @e: EC context from crypto_ec_init()
118+ * @cofactor: Cofactor of curve.
119+ * Returns: 0 on success, -1 on failure
120+ */
121+int crypto_ec_cofactor(struct crypto_ec *e, struct crypto_bignum *cofactor);
122+
123+/**
124 * crypto_ec_prime_len - Get length of the prime in octets
125 * @e: EC context from crypto_ec_init()
126 * Returns: Length of the prime defining the group
127@@ -650,6 +699,13 @@ size_t crypto_ec_prime_len(struct crypto_ec *e);
128 size_t crypto_ec_prime_len_bits(struct crypto_ec *e);
129
130 /**
131+ * crypto_ec_order_len - Get length of the order in octets
132+ * @e: EC context from crypto_ec_init()
133+ * Returns: Length of the order defining the group
134+ */
135+size_t crypto_ec_order_len(struct crypto_ec *e);
136+
137+/**
138 * crypto_ec_get_prime - Get prime defining an EC group
139 * @e: EC context from crypto_ec_init()
140 * Returns: Prime (bignum) defining the group
141@@ -686,6 +742,16 @@ struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e);
142 void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear);
143
144 /**
145+ * crypto_ec_point_x - Copies the x-ordinate point into big number
146+ * @e: EC context from crypto_ec_init()
147+ * @p: EC point data
148+ * @x: Big number to set to the copy of x-ordinate
149+ * Returns: 0 on success, -1 on failure
150+ */
151+int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p,
152+ struct crypto_bignum *x);
153+
154+/**
155 * crypto_ec_point_to_bin - Write EC point value as binary data
156 * @e: EC context from crypto_ec_init()
157 * @p: EC point data from crypto_ec_point_init()
158@@ -758,6 +824,16 @@ int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
159 const struct crypto_bignum *x, int y_bit);
160
161 /**
162+ * crypto_ec_point_compute_y_sqr - Compute y^2 = x^3 + ax + b
163+ * @e: EC context from crypto_ec_init()
164+ * @x: x coordinate
165+ * Returns: y^2 on success, %NULL failure
166+ */
167+struct crypto_bignum *
168+crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
169+ const struct crypto_bignum *x);
170+
171+/**
172 * crypto_ec_point_is_at_infinity - Check whether EC point is neutral element
173 * @e: EC context from crypto_ec_init()
174 * @p: EC point
175@@ -776,4 +852,15 @@ int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
176 int crypto_ec_point_is_on_curve(struct crypto_ec *e,
177 const struct crypto_ec_point *p);
178
179+/**
180+ * crypto_ec_point_cmp - Compare two EC points
181+ * @e: EC context from crypto_ec_init()
182+ * @a: EC point
183+ * @b: EC point
184+ * Returns: 0 on equal, non-zero otherwise
185+ */
186+int crypto_ec_point_cmp(const struct crypto_ec *e,
187+ const struct crypto_ec_point *a,
188+ const struct crypto_ec_point *b);
189+
190 #endif /* CRYPTO_H */
191diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
192index f158ef4..0b57a6a 100644
193--- a/src/crypto/crypto_openssl.c
194+++ b/src/crypto/crypto_openssl.c
195@@ -24,6 +24,7 @@
196 #endif /* CONFIG_ECC */
197
198 #include "common.h"
199+#include "utils/const_time.h"
200 #include "wpabuf.h"
201 #include "dh_group5.h"
202 #include "sha1.h"
203@@ -346,7 +347,8 @@ int crypto_mod_exp(const u8 *base, size_t base_len,
204 bn_result == NULL)
205 goto error;
206
207- if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1)
208+ if (BN_mod_exp_mont_consttime(bn_result, bn_base, bn_exp, bn_modulus,
209+ ctx, NULL) != 1)
210 goto error;
211
212 *result_len = BN_bn2bin(bn_result, result);
213@@ -920,6 +922,12 @@ int crypto_bignum_to_bin(const struct crypto_bignum *a,
214 }
215
216
217+int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
218+{
219+ return BN_rand_range((BIGNUM *) r, (const BIGNUM *) m) == 1 ? 0 : -1;
220+}
221+
222+
223 int crypto_bignum_add(const struct crypto_bignum *a,
224 const struct crypto_bignum *b,
225 struct crypto_bignum *c)
226@@ -958,8 +966,9 @@ int crypto_bignum_exptmod(const struct crypto_bignum *a,
227 bnctx = BN_CTX_new();
228 if (bnctx == NULL)
229 return -1;
230- res = BN_mod_exp((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,
231- (const BIGNUM *) c, bnctx);
232+ res = BN_mod_exp_mont_consttime((BIGNUM *) d, (const BIGNUM *) a,
233+ (const BIGNUM *) b, (const BIGNUM *) c,
234+ bnctx, NULL);
235 BN_CTX_free(bnctx);
236
237 return res ? 0 : -1;
238@@ -976,6 +985,11 @@ int crypto_bignum_inverse(const struct crypto_bignum *a,
239 bnctx = BN_CTX_new();
240 if (bnctx == NULL)
241 return -1;
242+#ifdef OPENSSL_IS_BORINGSSL
243+ /* TODO: use BN_mod_inverse_blinded() ? */
244+#else /* OPENSSL_IS_BORINGSSL */
245+ BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME);
246+#endif /* OPENSSL_IS_BORINGSSL */
247 res = BN_mod_inverse((BIGNUM *) c, (const BIGNUM *) a,
248 (const BIGNUM *) b, bnctx);
249 BN_CTX_free(bnctx);
250@@ -1004,6 +1018,9 @@ int crypto_bignum_div(const struct crypto_bignum *a,
251 bnctx = BN_CTX_new();
252 if (bnctx == NULL)
253 return -1;
254+#ifndef OPENSSL_IS_BORINGSSL
255+ BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME);
256+#endif /* OPENSSL_IS_BORINGSSL */
257 res = BN_div((BIGNUM *) c, NULL, (const BIGNUM *) a,
258 (const BIGNUM *) b, bnctx);
259 BN_CTX_free(bnctx);
260@@ -1032,6 +1049,15 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a,
261 }
262
263
264+int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
265+ struct crypto_bignum *r)
266+{
267+ /* Note: BN_rshift() does not modify the first argument even though it
268+ * has not been marked const. */
269+ return BN_rshift((BIGNUM *) a, (BIGNUM *) r, n) == 1 ? 0 : -1;
270+}
271+
272+
273 int crypto_bignum_cmp(const struct crypto_bignum *a,
274 const struct crypto_bignum *b)
275 {
276@@ -1057,6 +1083,50 @@ int crypto_bignum_is_one(const struct crypto_bignum *a)
277 }
278
279
280+int crypto_bignum_is_odd(const struct crypto_bignum *a)
281+{
282+ return BN_is_odd((const BIGNUM *) a);
283+}
284+
285+
286+int crypto_bignum_legendre(const struct crypto_bignum *a,
287+ const struct crypto_bignum *p)
288+{
289+ BN_CTX *bnctx;
290+ BIGNUM *exp = NULL, *tmp = NULL;
291+ int res = -2;
292+ unsigned int mask;
293+
294+ bnctx = BN_CTX_new();
295+ if (bnctx == NULL)
296+ return -2;
297+
298+ exp = BN_new();
299+ tmp = BN_new();
300+ if (!exp || !tmp ||
301+ /* exp = (p-1) / 2 */
302+ !BN_sub(exp, (const BIGNUM *) p, BN_value_one()) ||
303+ !BN_rshift1(exp, exp) ||
304+ !BN_mod_exp_mont_consttime(tmp, (const BIGNUM *) a, exp,
305+ (const BIGNUM *) p, bnctx, NULL))
306+ goto fail;
307+
308+ /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need to use
309+ * constant time selection to avoid branches here. */
310+ res = -1;
311+ mask = const_time_eq(BN_is_word(tmp, 1), 1);
312+ res = const_time_select_int(mask, 1, res);
313+ mask = const_time_eq(BN_is_zero(tmp), 1);
314+ res = const_time_select_int(mask, 0, res);
315+
316+fail:
317+ BN_clear_free(tmp);
318+ BN_clear_free(exp);
319+ BN_CTX_free(bnctx);
320+ return res;
321+}
322+
323+
324 #ifdef CONFIG_ECC
325
326 struct crypto_ec {
327@@ -1064,6 +1134,8 @@ struct crypto_ec {
328 BN_CTX *bnctx;
329 BIGNUM *prime;
330 BIGNUM *order;
331+ BIGNUM *a;
332+ BIGNUM *b;
333 };
334
335 struct crypto_ec * crypto_ec_init(int group)
336@@ -1100,9 +1172,11 @@ struct crypto_ec * crypto_ec_init(int group)
337 e->group = EC_GROUP_new_by_curve_name(nid);
338 e->prime = BN_new();
339 e->order = BN_new();
340+ e->a = BN_new();
341+ e->b = BN_new();
342 if (e->group == NULL || e->bnctx == NULL || e->prime == NULL ||
343- e->order == NULL ||
344- !EC_GROUP_get_curve_GFp(e->group, e->prime, NULL, NULL, e->bnctx) ||
345+ e->order == NULL || e->a == NULL || e->b == NULL ||
346+ !EC_GROUP_get_curve_GFp(e->group, e->prime, e->a, e->b, e->bnctx) ||
347 !EC_GROUP_get_order(e->group, e->order, e->bnctx)) {
348 crypto_ec_deinit(e);
349 e = NULL;
350@@ -1116,6 +1190,8 @@ void crypto_ec_deinit(struct crypto_ec *e)
351 {
352 if (e == NULL)
353 return;
354+ BN_clear_free(e->b);
355+ BN_clear_free(e->a);
356 BN_clear_free(e->order);
357 BN_clear_free(e->prime);
358 EC_GROUP_free(e->group);
359@@ -1124,6 +1200,13 @@ void crypto_ec_deinit(struct crypto_ec *e)
360 }
361
362
363+int crypto_ec_cofactor(struct crypto_ec *e, struct crypto_bignum *cofactor)
364+{
365+ return EC_GROUP_get_cofactor(e->group, (BIGNUM *) cofactor,
366+ e->bnctx) == 0 ? -1 : 0;
367+}
368+
369+
370 struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e)
371 {
372 if (e == NULL)
373@@ -1144,6 +1227,12 @@ size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
374 }
375
376
377+size_t crypto_ec_order_len(struct crypto_ec *e)
378+{
379+ return BN_num_bytes(e->order);
380+}
381+
382+
383 const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e)
384 {
385 return (const struct crypto_bignum *) e->prime;
386@@ -1165,6 +1254,16 @@ void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
387 }
388
389
390+int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p,
391+ struct crypto_bignum *x)
392+{
393+ return EC_POINT_get_affine_coordinates_GFp(e->group,
394+ (const EC_POINT *) p,
395+ (BIGNUM *) x, NULL,
396+ e->bnctx) == 1 ? 0 : -1;
397+}
398+
399+
400 int crypto_ec_point_to_bin(struct crypto_ec *e,
401 const struct crypto_ec_point *point, u8 *x, u8 *y)
402 {
403@@ -1263,6 +1362,33 @@ int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
404 }
405
406
407+struct crypto_bignum *
408+crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
409+ const struct crypto_bignum *x)
410+{
411+ BIGNUM *tmp, *tmp2, *y_sqr = NULL;
412+
413+ tmp = BN_new();
414+ tmp2 = BN_new();
415+
416+ /* y^2 = x^3 + ax + b */
417+ if (tmp && tmp2 &&
418+ BN_mod_sqr(tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
419+ BN_mod_mul(tmp, tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
420+ BN_mod_mul(tmp2, e->a, (const BIGNUM *) x, e->prime, e->bnctx) &&
421+ BN_mod_add_quick(tmp2, tmp2, tmp, e->prime) &&
422+ BN_mod_add_quick(tmp2, tmp2, e->b, e->prime)) {
423+ y_sqr = tmp2;
424+ tmp2 = NULL;
425+ }
426+
427+ BN_clear_free(tmp);
428+ BN_clear_free(tmp2);
429+
430+ return (struct crypto_bignum *) y_sqr;
431+}
432+
433+
434 int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
435 const struct crypto_ec_point *p)
436 {
437@@ -1276,4 +1402,13 @@ int crypto_ec_point_is_on_curve(struct crypto_ec *e,
438 return EC_POINT_is_on_curve(e->group, (const EC_POINT *) p, e->bnctx);
439 }
440
441+
442+int crypto_ec_point_cmp(const struct crypto_ec *e,
443+ const struct crypto_ec_point *a,
444+ const struct crypto_ec_point *b)
445+{
446+ return EC_POINT_cmp(e->group, (const EC_POINT *) a,
447+ (const EC_POINT *) b, e->bnctx);
448+}
449+
450 #endif /* CONFIG_ECC */
451diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
452index 631c363..cace4a4 100644
453--- a/src/eap_common/eap_pwd_common.c
454+++ b/src/eap_common/eap_pwd_common.c
455@@ -8,11 +8,15 @@
456
457 #include "includes.h"
458 #include "common.h"
459+#include "utils/const_time.h"
460 #include "crypto/sha256.h"
461 #include "crypto/crypto.h"
462 #include "eap_defs.h"
463 #include "eap_pwd_common.h"
464
465+#define MAX_ECC_PRIME_LEN 66
466+
467+
468 /* The random function H(x) = HMAC-SHA256(0^32, x) */
469 struct crypto_hash * eap_pwd_h_init(void)
470 {
471@@ -81,6 +85,36 @@ static int eap_pwd_kdf(const u8 *key, size_t keylen, const u8 *label,
472 }
473
474
475+EAP_PWD_group * get_eap_pwd_group(u16 num)
476+{
477+ EAP_PWD_group *grp;
478+
479+ grp = os_zalloc(sizeof(EAP_PWD_group));
480+ if (!grp)
481+ return NULL;
482+ grp->group = crypto_ec_init(num);
483+ if (!grp->group) {
484+ wpa_printf(MSG_INFO, "EAP-pwd: unable to create EC group");
485+ os_free(grp);
486+ return NULL;
487+ }
488+
489+ grp->group_num = num;
490+ wpa_printf(MSG_INFO, "EAP-pwd: provisioned group %d", num);
491+
492+ return grp;
493+}
494+
495+
496+static void buf_shift_right(u8 *buf, size_t len, size_t bits)
497+{
498+ size_t i;
499+ for (i = len - 1; i > 0; i--)
500+ buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits);
501+ buf[0] >>= bits;
502+}
503+
504+
505 /*
506 * compute a "random" secret point on an elliptic curve based
507 * on the password and identities.
508@@ -90,85 +124,84 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
509 u8 *id_server, int id_server_len,
510 u8 *id_peer, int id_peer_len, u8 *token)
511 {
512- BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL;
513+ struct crypto_bignum *qr = NULL, *qnr = NULL, *one = NULL;
514+ struct crypto_bignum *qr_or_qnr = NULL;
515+ u8 qr_bin[MAX_ECC_PRIME_LEN];
516+ u8 qnr_bin[MAX_ECC_PRIME_LEN];
517+ u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN];
518+ u8 x_bin[MAX_ECC_PRIME_LEN];
519+ struct crypto_bignum *tmp1 = NULL, *tmp2 = NULL, *pm1 = NULL;
520 struct crypto_hash *hash;
521 unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr;
522- int nid, is_odd, ret = 0;
523- size_t primebytelen, primebitlen;
524-
525- switch (num) { /* from IANA registry for IKE D-H groups */
526- case 19:
527- nid = NID_X9_62_prime256v1;
528- break;
529- case 20:
530- nid = NID_secp384r1;
531- break;
532- case 21:
533- nid = NID_secp521r1;
534- break;
535-#ifndef OPENSSL_IS_BORINGSSL
536- case 25:
537- nid = NID_X9_62_prime192v1;
538- break;
539-#endif /* OPENSSL_IS_BORINGSSL */
540- case 26:
541- nid = NID_secp224r1;
542- break;
543- default:
544- wpa_printf(MSG_INFO, "EAP-pwd: unsupported group %d", num);
545+ int ret = 0, check, res;
546+ u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
547+ * mask */
548+ size_t primebytelen = 0, primebitlen;
549+ struct crypto_bignum *x_candidate = NULL, *cofactor = NULL;
550+ const struct crypto_bignum *prime;
551+ u8 mask, found_ctr = 0, is_odd = 0;
552+
553+ if (grp->pwe)
554 return -1;
555- }
556
557- grp->pwe = NULL;
558- grp->order = NULL;
559- grp->prime = NULL;
560+ os_memset(x_bin, 0, sizeof(x_bin));
561
562- if ((grp->group = EC_GROUP_new_by_curve_name(nid)) == NULL) {
563- wpa_printf(MSG_INFO, "EAP-pwd: unable to create EC_GROUP");
564- goto fail;
565- }
566-
567- if (((rnd = BN_new()) == NULL) ||
568- ((cofactor = BN_new()) == NULL) ||
569- ((grp->pwe = EC_POINT_new(grp->group)) == NULL) ||
570- ((grp->order = BN_new()) == NULL) ||
571- ((grp->prime = BN_new()) == NULL) ||
572- ((x_candidate = BN_new()) == NULL)) {
573+ prime = crypto_ec_get_prime(grp->group);
574+ cofactor = crypto_bignum_init();
575+ grp->pwe = crypto_ec_point_init(grp->group);
576+ tmp1 = crypto_bignum_init();
577+ pm1 = crypto_bignum_init();
578+ one = crypto_bignum_init_set((const u8 *) "\x01", 1);
579+ if (!cofactor || !grp->pwe || !tmp1 || !pm1 || !one) {
580 wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums");
581 goto fail;
582 }
583
584- if (!EC_GROUP_get_curve_GFp(grp->group, grp->prime, NULL, NULL, NULL))
585- {
586- wpa_printf(MSG_INFO, "EAP-pwd: unable to get prime for GFp "
587- "curve");
588- goto fail;
589- }
590- if (!EC_GROUP_get_order(grp->group, grp->order, NULL)) {
591- wpa_printf(MSG_INFO, "EAP-pwd: unable to get order for curve");
592- goto fail;
593- }
594- if (!EC_GROUP_get_cofactor(grp->group, cofactor, NULL)) {
595+ if (crypto_ec_cofactor(grp->group, cofactor) < 0) {
596 wpa_printf(MSG_INFO, "EAP-pwd: unable to get cofactor for "
597 "curve");
598 goto fail;
599 }
600- primebitlen = BN_num_bits(grp->prime);
601- primebytelen = BN_num_bytes(grp->prime);
602+ primebitlen = crypto_ec_prime_len_bits(grp->group);
603+ primebytelen = crypto_ec_prime_len(grp->group);
604 if ((prfbuf = os_malloc(primebytelen)) == NULL) {
605 wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf "
606 "buffer");
607 goto fail;
608 }
609- os_memset(prfbuf, 0, primebytelen);
610- ctr = 0;
611- while (1) {
612- if (ctr > 30) {
613- wpa_printf(MSG_INFO, "EAP-pwd: unable to find random "
614- "point on curve for group %d, something's "
615- "fishy", num);
616+ if (crypto_bignum_sub(prime, one, pm1) < 0)
617+ goto fail;
618+
619+ /* get a random quadratic residue and nonresidue */
620+ while (!qr || !qnr) {
621+ if (crypto_bignum_rand(tmp1, prime) < 0)
622 goto fail;
623+ res = crypto_bignum_legendre(tmp1, prime);
624+ if (!qr && res == 1) {
625+ qr = tmp1;
626+ tmp1 = crypto_bignum_init();
627+ } else if (!qnr && res == -1) {
628+ qnr = tmp1;
629+ tmp1 = crypto_bignum_init();
630 }
631+ if (!tmp1)
632+ goto fail;
633+ }
634+ if (crypto_bignum_to_bin(qr, qr_bin, sizeof(qr_bin),
635+ primebytelen) < 0 ||
636+ crypto_bignum_to_bin(qnr, qnr_bin, sizeof(qnr_bin),
637+ primebytelen) < 0)
638+ goto fail;
639+
640+ os_memset(prfbuf, 0, primebytelen);
641+ ctr = 0;
642+
643+ /*
644+ * Run through the hunting-and-pecking loop 40 times to mask the time
645+ * necessary to find PWE. The odds of PWE not being found in 40 loops is
646+ * roughly 1 in 1 trillion.
647+ */
648+ while (ctr < 40) {
649 ctr++;
650
651 /*
652@@ -186,114 +219,170 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
653 eap_pwd_h_update(hash, &ctr, sizeof(ctr));
654 eap_pwd_h_final(hash, pwe_digest);
655
656- BN_bin2bn(pwe_digest, SHA256_MAC_LEN, rnd);
657-
658+ is_odd = const_time_select_u8(
659+ found, is_odd, pwe_digest[SHA256_MAC_LEN - 1] & 0x01);
660 if (eap_pwd_kdf(pwe_digest, SHA256_MAC_LEN,
661 (u8 *) "EAP-pwd Hunting And Pecking",
662 os_strlen("EAP-pwd Hunting And Pecking"),
663 prfbuf, primebitlen) < 0)
664 goto fail;
665-
666- BN_bin2bn(prfbuf, primebytelen, x_candidate);
667-
668- /*
669- * eap_pwd_kdf() returns a string of bits 0..primebitlen but
670- * BN_bin2bn will treat that string of bits as a big endian
671- * number. If the primebitlen is not an even multiple of 8
672- * then excessive bits-- those _after_ primebitlen-- so now
673- * we have to shift right the amount we masked off.
674- */
675 if (primebitlen % 8)
676- BN_rshift(x_candidate, x_candidate,
677- (8 - (primebitlen % 8)));
678+ buf_shift_right(prfbuf, primebytelen,
679+ 8 - primebitlen % 8);
680+
681+ crypto_bignum_deinit(x_candidate, 1);
682+ x_candidate = crypto_bignum_init_set(prfbuf, primebytelen);
683+ if (!x_candidate) {
684+ wpa_printf(MSG_INFO,
685+ "EAP-pwd: unable to create x_candidate");
686+ goto fail;
687+ }
688
689- if (BN_ucmp(x_candidate, grp->prime) >= 0)
690+ if (crypto_bignum_cmp(x_candidate, prime) >= 0)
691 continue;
692
693- wpa_hexdump(MSG_DEBUG, "EAP-pwd: x_candidate",
694- prfbuf, primebytelen);
695+ wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: x_candidate",
696+ prfbuf, primebytelen);
697+ const_time_select_bin(found, x_bin, prfbuf, primebytelen,
698+ x_bin);
699
700 /*
701- * need to unambiguously identify the solution, if there is
702- * one...
703+ * compute y^2 using the equation of the curve
704+ *
705+ * y^2 = x^3 + ax + b
706 */
707- if (BN_is_odd(rnd))
708- is_odd = 1;
709- else
710- is_odd = 0;
711+ crypto_bignum_deinit(tmp2, 1);
712+ tmp2 = crypto_ec_point_compute_y_sqr(grp->group, x_candidate);
713+ if (!tmp2)
714+ goto fail;
715
716 /*
717- * solve the quadratic equation, if it's not solvable then we
718- * don't have a point
719+ * mask tmp2 so doing legendre won't leak timing info
720+ *
721+ * tmp1 is a random number between 1 and p-1
722 */
723- if (!EC_POINT_set_compressed_coordinates_GFp(grp->group,
724- grp->pwe,
725- x_candidate,
726- is_odd, NULL))
727- continue;
728+ if (crypto_bignum_rand(tmp1, pm1) < 0 ||
729+ crypto_bignum_mulmod(tmp2, tmp1, prime, tmp2) < 0 ||
730+ crypto_bignum_mulmod(tmp2, tmp1, prime, tmp2) < 0)
731+ goto fail;
732+
733 /*
734- * If there's a solution to the equation then the point must be
735- * on the curve so why check again explicitly? OpenSSL code
736- * says this is required by X9.62. We're not X9.62 but it can't
737- * hurt just to be sure.
738+ * Now tmp2 (y^2) is masked, all values between 1 and p-1
739+ * are equally probable. Multiplying by r^2 does not change
740+ * whether or not tmp2 is a quadratic residue, just masks it.
741+ *
742+ * Flip a coin, multiply by the random quadratic residue or the
743+ * random quadratic nonresidue and record heads or tails.
744 */
745- if (!EC_POINT_is_on_curve(grp->group, grp->pwe, NULL)) {
746- wpa_printf(MSG_INFO, "EAP-pwd: point is not on curve");
747- continue;
748- }
749+ mask = const_time_eq_u8(crypto_bignum_is_odd(tmp1), 1);
750+ check = const_time_select_s8(mask, 1, -1);
751+ const_time_select_bin(mask, qr_bin, qnr_bin, primebytelen,
752+ qr_or_qnr_bin);
753+ crypto_bignum_deinit(qr_or_qnr, 1);
754+ qr_or_qnr = crypto_bignum_init_set(qr_or_qnr_bin, primebytelen);
755+ if (!qr_or_qnr ||
756+ crypto_bignum_mulmod(tmp2, qr_or_qnr, prime, tmp2) < 0)
757+ goto fail;
758
759- if (BN_cmp(cofactor, BN_value_one())) {
760- /* make sure the point is not in a small sub-group */
761- if (!EC_POINT_mul(grp->group, grp->pwe, NULL, grp->pwe,
762- cofactor, NULL)) {
763- wpa_printf(MSG_INFO, "EAP-pwd: cannot "
764- "multiply generator by order");
765- continue;
766- }
767- if (EC_POINT_is_at_infinity(grp->group, grp->pwe)) {
768- wpa_printf(MSG_INFO, "EAP-pwd: point is at "
769- "infinity");
770- continue;
771- }
772+ /*
773+ * Now it's safe to do legendre, if check is 1 then it's
774+ * a straightforward test (multiplying by qr does not
775+ * change result), if check is -1 then it's the opposite test
776+ * (multiplying a qr by qnr would make a qnr).
777+ */
778+ res = crypto_bignum_legendre(tmp2, prime);
779+ if (res == -2)
780+ goto fail;
781+ mask = const_time_eq(res, check);
782+ found_ctr = const_time_select_u8(found, found_ctr, ctr);
783+ found |= mask;
784+ }
785+ if (found == 0) {
786+ wpa_printf(MSG_INFO,
787+ "EAP-pwd: unable to find random point on curve for group %d, something's fishy",
788+ num);
789+ goto fail;
790+ }
791+
792+ /*
793+ * We know x_candidate is a quadratic residue so set it here.
794+ */
795+ crypto_bignum_deinit(x_candidate, 1);
796+ x_candidate = crypto_bignum_init_set(x_bin, primebytelen);
797+ if (!x_candidate ||
798+ crypto_ec_point_solve_y_coord(grp->group, grp->pwe, x_candidate,
799+ is_odd) != 0) {
800+ wpa_printf(MSG_INFO, "EAP-pwd: Could not solve for y");
801+ goto fail;
802+ }
803+
804+ /*
805+ * If there's a solution to the equation then the point must be on the
806+ * curve so why check again explicitly? OpenSSL code says this is
807+ * required by X9.62. We're not X9.62 but it can't hurt just to be sure.
808+ */
809+ if (!crypto_ec_point_is_on_curve(grp->group, grp->pwe)) {
810+ wpa_printf(MSG_INFO, "EAP-pwd: point is not on curve");
811+ goto fail;
812+ }
813+
814+ if (!crypto_bignum_is_one(cofactor)) {
815+ /* make sure the point is not in a small sub-group */
816+ if (crypto_ec_point_mul(grp->group, grp->pwe, cofactor,
817+ grp->pwe) != 0) {
818+ wpa_printf(MSG_INFO,
819+ "EAP-pwd: cannot multiply generator by order");
820+ goto fail;
821+ }
822+ if (crypto_ec_point_is_at_infinity(grp->group, grp->pwe)) {
823+ wpa_printf(MSG_INFO, "EAP-pwd: point is at infinity");
824+ goto fail;
825 }
826- /* if we got here then we have a new generator. */
827- break;
828 }
829- wpa_printf(MSG_DEBUG, "EAP-pwd: found a PWE in %d tries", ctr);
830- grp->group_num = num;
831+ wpa_printf(MSG_DEBUG, "EAP-pwd: found a PWE in %02d tries", found_ctr);
832+
833 if (0) {
834 fail:
835- EC_GROUP_free(grp->group);
836- grp->group = NULL;
837- EC_POINT_clear_free(grp->pwe);
838+ crypto_ec_point_deinit(grp->pwe, 1);
839 grp->pwe = NULL;
840- BN_clear_free(grp->order);
841- grp->order = NULL;
842- BN_clear_free(grp->prime);
843- grp->prime = NULL;
844 ret = 1;
845 }
846 /* cleanliness and order.... */
847- BN_clear_free(cofactor);
848- BN_clear_free(x_candidate);
849- BN_clear_free(rnd);
850- os_free(prfbuf);
851+ crypto_bignum_deinit(cofactor, 1);
852+ crypto_bignum_deinit(x_candidate, 1);
853+ crypto_bignum_deinit(pm1, 0);
854+ crypto_bignum_deinit(tmp1, 1);
855+ crypto_bignum_deinit(tmp2, 1);
856+ crypto_bignum_deinit(qr, 1);
857+ crypto_bignum_deinit(qnr, 1);
858+ crypto_bignum_deinit(qr_or_qnr, 1);
859+ crypto_bignum_deinit(one, 0);
860+ bin_clear_free(prfbuf, primebytelen);
861+ os_memset(qr_bin, 0, sizeof(qr_bin));
862+ os_memset(qnr_bin, 0, sizeof(qnr_bin));
863+ os_memset(qr_or_qnr_bin, 0, sizeof(qr_or_qnr_bin));
864+ os_memset(pwe_digest, 0, sizeof(pwe_digest));
865
866 return ret;
867 }
868
869
870-int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, BIGNUM *k,
871- BIGNUM *peer_scalar, BIGNUM *server_scalar,
872- u8 *confirm_peer, u8 *confirm_server,
873- u32 *ciphersuite, u8 *msk, u8 *emsk, u8 *session_id)
874+int compute_keys(EAP_PWD_group *grp, const struct crypto_bignum *k,
875+ const struct crypto_bignum *peer_scalar,
876+ const struct crypto_bignum *server_scalar,
877+ const u8 *confirm_peer, const u8 *confirm_server,
878+ const u32 *ciphersuite, u8 *msk, u8 *emsk, u8 *session_id)
879 {
880 struct crypto_hash *hash;
881 u8 mk[SHA256_MAC_LEN], *cruft;
882 u8 msk_emsk[EAP_MSK_LEN + EAP_EMSK_LEN];
883- int offset;
884+ size_t prime_len, order_len;
885+
886+ prime_len = crypto_ec_prime_len(grp->group);
887+ order_len = crypto_ec_order_len(grp->group);
888
889- if ((cruft = os_malloc(BN_num_bytes(grp->prime))) == NULL)
890+ cruft = os_malloc(prime_len);
891+ if (!cruft)
892 return -1;
893
894 /*
895@@ -306,15 +395,11 @@ int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, BIGNUM *k,
896 os_free(cruft);
897 return -1;
898 }
899- eap_pwd_h_update(hash, (u8 *) ciphersuite, sizeof(u32));
900- offset = BN_num_bytes(grp->order) - BN_num_bytes(peer_scalar);
901- os_memset(cruft, 0, BN_num_bytes(grp->prime));
902- BN_bn2bin(peer_scalar, cruft + offset);
903- eap_pwd_h_update(hash, cruft, BN_num_bytes(grp->order));
904- offset = BN_num_bytes(grp->order) - BN_num_bytes(server_scalar);
905- os_memset(cruft, 0, BN_num_bytes(grp->prime));
906- BN_bn2bin(server_scalar, cruft + offset);
907- eap_pwd_h_update(hash, cruft, BN_num_bytes(grp->order));
908+ eap_pwd_h_update(hash, (const u8 *) ciphersuite, sizeof(u32));
909+ crypto_bignum_to_bin(peer_scalar, cruft, order_len, order_len);
910+ eap_pwd_h_update(hash, cruft, order_len);
911+ crypto_bignum_to_bin(server_scalar, cruft, order_len, order_len);
912+ eap_pwd_h_update(hash, cruft, order_len);
913 eap_pwd_h_final(hash, &session_id[1]);
914
915 /* then compute MK = H(k | confirm-peer | confirm-server) */
916@@ -323,10 +408,8 @@ int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, BIGNUM *k,
917 os_free(cruft);
918 return -1;
919 }
920- offset = BN_num_bytes(grp->prime) - BN_num_bytes(k);
921- os_memset(cruft, 0, BN_num_bytes(grp->prime));
922- BN_bn2bin(k, cruft + offset);
923- eap_pwd_h_update(hash, cruft, BN_num_bytes(grp->prime));
924+ crypto_bignum_to_bin(k, cruft, prime_len, prime_len);
925+ eap_pwd_h_update(hash, cruft, prime_len);
926 os_free(cruft);
927 eap_pwd_h_update(hash, confirm_peer, SHA256_MAC_LEN);
928 eap_pwd_h_update(hash, confirm_server, SHA256_MAC_LEN);
929@@ -344,3 +427,109 @@ int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, BIGNUM *k,
930
931 return 1;
932 }
933+
934+
935+static int eap_pwd_element_coord_ok(const struct crypto_bignum *prime,
936+ const u8 *buf, size_t len)
937+{
938+ struct crypto_bignum *val;
939+ int ok = 1;
940+
941+ val = crypto_bignum_init_set(buf, len);
942+ if (!val || crypto_bignum_is_zero(val) ||
943+ crypto_bignum_cmp(val, prime) >= 0)
944+ ok = 0;
945+ crypto_bignum_deinit(val, 0);
946+ return ok;
947+}
948+
949+
950+struct crypto_ec_point * eap_pwd_get_element(EAP_PWD_group *group,
951+ const u8 *buf)
952+{
953+ struct crypto_ec_point *element;
954+ const struct crypto_bignum *prime;
955+ size_t prime_len;
956+ struct crypto_bignum *cofactor = NULL;
957+
958+ prime = crypto_ec_get_prime(group->group);
959+ prime_len = crypto_ec_prime_len(group->group);
960+
961+ /* RFC 5931, 2.8.5.2.2: 0 < x,y < p */
962+ if (!eap_pwd_element_coord_ok(prime, buf, prime_len) ||
963+ !eap_pwd_element_coord_ok(prime, buf + prime_len, prime_len)) {
964+ wpa_printf(MSG_INFO, "EAP-pwd: Invalid coordinate in element");
965+ return NULL;
966+ }
967+
968+ element = crypto_ec_point_from_bin(group->group, buf);
969+ if (!element) {
970+ wpa_printf(MSG_INFO, "EAP-pwd: EC point from element failed");
971+ return NULL;
972+ }
973+
974+ /* RFC 5931, 2.8.5.2.2: on curve and not the point at infinity */
975+ if (!crypto_ec_point_is_on_curve(group->group, element) ||
976+ crypto_ec_point_is_at_infinity(group->group, element)) {
977+ wpa_printf(MSG_INFO, "EAP-pwd: Invalid element");
978+ goto fail;
979+ }
980+
981+ cofactor = crypto_bignum_init();
982+ if (!cofactor || crypto_ec_cofactor(group->group, cofactor) < 0) {
983+ wpa_printf(MSG_INFO,
984+ "EAP-pwd: Unable to get cofactor for curve");
985+ goto fail;
986+ }
987+
988+ if (!crypto_bignum_is_one(cofactor)) {
989+ struct crypto_ec_point *point;
990+ int ok = 1;
991+
992+ /* check to ensure peer's element is not in a small sub-group */
993+ point = crypto_ec_point_init(group->group);
994+ if (!point ||
995+ crypto_ec_point_mul(group->group, element,
996+ cofactor, point) != 0 ||
997+ crypto_ec_point_is_at_infinity(group->group, point))
998+ ok = 0;
999+ crypto_ec_point_deinit(point, 0);
1000+
1001+ if (!ok) {
1002+ wpa_printf(MSG_INFO,
1003+ "EAP-pwd: Small sub-group check on peer element failed");
1004+ goto fail;
1005+ }
1006+ }
1007+
1008+out:
1009+ crypto_bignum_deinit(cofactor, 0);
1010+ return element;
1011+fail:
1012+ crypto_ec_point_deinit(element, 0);
1013+ element = NULL;
1014+ goto out;
1015+}
1016+
1017+
1018+struct crypto_bignum * eap_pwd_get_scalar(EAP_PWD_group *group, const u8 *buf)
1019+{
1020+ struct crypto_bignum *scalar;
1021+ const struct crypto_bignum *order;
1022+ size_t order_len;
1023+
1024+ order = crypto_ec_get_order(group->group);
1025+ order_len = crypto_ec_order_len(group->group);
1026+
1027+ /* RFC 5931, 2.8.5.2: 1 < scalar < r */
1028+ scalar = crypto_bignum_init_set(buf, order_len);
1029+ if (!scalar || crypto_bignum_is_zero(scalar) ||
1030+ crypto_bignum_is_one(scalar) ||
1031+ crypto_bignum_cmp(scalar, order) >= 0) {
1032+ wpa_printf(MSG_INFO, "EAP-pwd: received scalar is invalid");
1033+ crypto_bignum_deinit(scalar, 0);
1034+ scalar = NULL;
1035+ }
1036+
1037+ return scalar;
1038+}
1039diff --git a/src/eap_common/eap_pwd_common.h b/src/eap_common/eap_pwd_common.h
1040index c54c441..e61b4ba 100644
1041--- a/src/eap_common/eap_pwd_common.h
1042+++ b/src/eap_common/eap_pwd_common.h
1043@@ -9,20 +9,14 @@
1044 #ifndef EAP_PWD_COMMON_H
1045 #define EAP_PWD_COMMON_H
1046
1047-#include <openssl/bn.h>
1048-#include <openssl/ec.h>
1049-#include <openssl/evp.h>
1050-
1051 /*
1052 * definition of a finite cyclic group
1053 * TODO: support one based on a prime field
1054 */
1055 typedef struct group_definition_ {
1056 u16 group_num;
1057- EC_GROUP *group;
1058- EC_POINT *pwe;
1059- BIGNUM *order;
1060- BIGNUM *prime;
1061+ struct crypto_ec *group;
1062+ struct crypto_ec_point *pwe;
1063 } EAP_PWD_group;
1064
1065 /*
1066@@ -56,12 +50,19 @@ struct eap_pwd_id {
1067 } STRUCT_PACKED;
1068
1069 /* common routines */
1070+EAP_PWD_group * get_eap_pwd_group(u16 num);
1071 int compute_password_element(EAP_PWD_group *, u16, u8 *, int, u8 *, int, u8 *,
1072 int, u8 *);
1073-int compute_keys(EAP_PWD_group *, BN_CTX *, BIGNUM *, BIGNUM *, BIGNUM *,
1074- u8 *, u8 *, u32 *, u8 *, u8 *, u8 *);
1075+int compute_keys(EAP_PWD_group *grp, const struct crypto_bignum *k,
1076+ const struct crypto_bignum *peer_scalar,
1077+ const struct crypto_bignum *server_scalar,
1078+ const u8 *confirm_peer, const u8 *confirm_server,
1079+ const u32 *ciphersuite, u8 *msk, u8 *emsk, u8 *session_id);
1080 struct crypto_hash * eap_pwd_h_init(void);
1081 void eap_pwd_h_update(struct crypto_hash *hash, const u8 *data, size_t len);
1082 void eap_pwd_h_final(struct crypto_hash *hash, u8 *digest);
1083+struct crypto_ec_point * eap_pwd_get_element(EAP_PWD_group *group,
1084+ const u8 *buf);
1085+struct crypto_bignum * eap_pwd_get_scalar(EAP_PWD_group *group, const u8 *buf);
1086
1087 #endif /* EAP_PWD_COMMON_H */
1088diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
1089index 8eecf8d..a0dd00a 100644
1090--- a/src/eap_peer/eap_pwd.c
1091+++ b/src/eap_peer/eap_pwd.c
1092@@ -10,6 +10,7 @@
1093
1094 #include "common.h"
1095 #include "crypto/sha256.h"
1096+#include "crypto/crypto.h"
1097 #include "eap_peer/eap_i.h"
1098 #include "eap_common/eap_pwd_common.h"
1099
1100@@ -34,18 +35,16 @@ struct eap_pwd_data {
1101 size_t out_frag_pos;
1102 size_t mtu;
1103
1104- BIGNUM *k;
1105- BIGNUM *private_value;
1106- BIGNUM *server_scalar;
1107- BIGNUM *my_scalar;
1108- EC_POINT *my_element;
1109- EC_POINT *server_element;
1110+ struct crypto_bignum *k;
1111+ struct crypto_bignum *private_value;
1112+ struct crypto_bignum *server_scalar;
1113+ struct crypto_bignum *my_scalar;
1114+ struct crypto_ec_point *my_element;
1115+ struct crypto_ec_point *server_element;
1116
1117 u8 msk[EAP_MSK_LEN];
1118 u8 emsk[EAP_EMSK_LEN];
1119 u8 session_id[1 + SHA256_MAC_LEN];
1120-
1121- BN_CTX *bnctx;
1122 };
1123
1124
1125@@ -104,15 +103,8 @@ static void * eap_pwd_init(struct eap_sm *sm)
1126 return NULL;
1127 }
1128
1129- if ((data->bnctx = BN_CTX_new()) == NULL) {
1130- wpa_printf(MSG_INFO, "EAP-PWD: bn context allocation fail");
1131- os_free(data);
1132- return NULL;
1133- }
1134-
1135 if ((data->id_peer = os_malloc(identity_len)) == NULL) {
1136 wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail");
1137- BN_CTX_free(data->bnctx);
1138 os_free(data);
1139 return NULL;
1140 }
1141@@ -122,7 +114,6 @@ static void * eap_pwd_init(struct eap_sm *sm)
1142
1143 if ((data->password = os_malloc(password_len)) == NULL) {
1144 wpa_printf(MSG_INFO, "EAP-PWD: memory allocation psk fail");
1145- BN_CTX_free(data->bnctx);
1146 bin_clear_free(data->id_peer, data->id_peer_len);
1147 os_free(data);
1148 return NULL;
1149@@ -148,21 +139,18 @@ static void eap_pwd_deinit(struct eap_sm *sm, void *priv)
1150 {
1151 struct eap_pwd_data *data = priv;
1152
1153- BN_clear_free(data->private_value);
1154- BN_clear_free(data->server_scalar);
1155- BN_clear_free(data->my_scalar);
1156- BN_clear_free(data->k);
1157- BN_CTX_free(data->bnctx);
1158- EC_POINT_clear_free(data->my_element);
1159- EC_POINT_clear_free(data->server_element);
1160+ crypto_bignum_deinit(data->private_value, 1);
1161+ crypto_bignum_deinit(data->server_scalar, 1);
1162+ crypto_bignum_deinit(data->my_scalar, 1);
1163+ crypto_bignum_deinit(data->k, 1);
1164+ crypto_ec_point_deinit(data->my_element, 1);
1165+ crypto_ec_point_deinit(data->server_element, 1);
1166 bin_clear_free(data->id_peer, data->id_peer_len);
1167 bin_clear_free(data->id_server, data->id_server_len);
1168 bin_clear_free(data->password, data->password_len);
1169 if (data->grp) {
1170- EC_GROUP_free(data->grp->group);
1171- EC_POINT_clear_free(data->grp->pwe);
1172- BN_clear_free(data->grp->order);
1173- BN_clear_free(data->grp->prime);
1174+ crypto_ec_deinit(data->grp->group);
1175+ crypto_ec_point_deinit(data->grp->pwe, 1);
1176 os_free(data->grp);
1177 }
1178 wpabuf_free(data->inbuf);
1179@@ -252,7 +240,7 @@ eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
1180 wpa_hexdump_ascii(MSG_INFO, "EAP-PWD (peer): server sent id of",
1181 data->id_server, data->id_server_len);
1182
1183- data->grp = os_zalloc(sizeof(EAP_PWD_group));
1184+ data->grp = get_eap_pwd_group(data->group_num);
1185 if (data->grp == NULL) {
1186 wpa_printf(MSG_INFO, "EAP-PWD: failed to allocate memory for "
1187 "group");
1188@@ -272,7 +260,7 @@ eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
1189 }
1190
1191 wpa_printf(MSG_DEBUG, "EAP-PWD (peer): computed %d bit PWE...",
1192- BN_num_bits(data->grp->prime));
1193+ (int) crypto_ec_prime_len_bits(data->grp->group));
1194
1195 data->outbuf = wpabuf_alloc(sizeof(struct eap_pwd_id) +
1196 data->id_peer_len);
1197@@ -297,10 +285,10 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
1198 const struct wpabuf *reqData,
1199 const u8 *payload, size_t payload_len)
1200 {
1201- EC_POINT *K = NULL, *point = NULL;
1202- BIGNUM *mask = NULL, *x = NULL, *y = NULL, *cofactor = NULL;
1203- u16 offset;
1204- u8 *ptr, *scalar = NULL, *element = NULL;
1205+ struct crypto_ec_point *K = NULL;
1206+ struct crypto_bignum *mask = NULL, *cofactor = NULL;
1207+ const u8 *ptr;
1208+ u8 *scalar = NULL, *element = NULL;
1209 size_t prime_len, order_len;
1210
1211 if (data->state != PWD_Commit_Req) {
1212@@ -308,8 +296,8 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
1213 goto fin;
1214 }
1215
1216- prime_len = BN_num_bytes(data->grp->prime);
1217- order_len = BN_num_bytes(data->grp->order);
1218+ prime_len = crypto_ec_prime_len(data->grp->group);
1219+ order_len = crypto_ec_order_len(data->grp->group);
1220
1221 if (payload_len != 2 * prime_len + order_len) {
1222 wpa_printf(MSG_INFO,
1223@@ -319,110 +307,90 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
1224 goto fin;
1225 }
1226
1227- if (((data->private_value = BN_new()) == NULL) ||
1228- ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) ||
1229- ((cofactor = BN_new()) == NULL) ||
1230- ((data->my_scalar = BN_new()) == NULL) ||
1231- ((mask = BN_new()) == NULL)) {
1232+ data->private_value = crypto_bignum_init();
1233+ data->my_element = crypto_ec_point_init(data->grp->group);
1234+ cofactor = crypto_bignum_init();
1235+ data->my_scalar = crypto_bignum_init();
1236+ mask = crypto_bignum_init();
1237+ if (!data->private_value || !data->my_element || !cofactor ||
1238+ !data->my_scalar || !mask) {
1239 wpa_printf(MSG_INFO, "EAP-PWD (peer): scalar allocation fail");
1240 goto fin;
1241 }
1242
1243- if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) {
1244+ if (crypto_ec_cofactor(data->grp->group, cofactor) < 0) {
1245 wpa_printf(MSG_INFO, "EAP-pwd (peer): unable to get cofactor "
1246 "for curve");
1247 goto fin;
1248 }
1249
1250- if (BN_rand_range(data->private_value, data->grp->order) != 1 ||
1251- BN_rand_range(mask, data->grp->order) != 1 ||
1252- BN_add(data->my_scalar, data->private_value, mask) != 1 ||
1253- BN_mod(data->my_scalar, data->my_scalar, data->grp->order,
1254- data->bnctx) != 1) {
1255+ if (crypto_bignum_rand(data->private_value,
1256+ crypto_ec_get_order(data->grp->group)) < 0 ||
1257+ crypto_bignum_rand(mask,
1258+ crypto_ec_get_order(data->grp->group)) < 0 ||
1259+ crypto_bignum_add(data->private_value, mask,
1260+ data->my_scalar) < 0 ||
1261+ crypto_bignum_mod(data->my_scalar,
1262+ crypto_ec_get_order(data->grp->group),
1263+ data->my_scalar) < 0) {
1264 wpa_printf(MSG_INFO,
1265 "EAP-pwd (peer): unable to get randomness");
1266 goto fin;
1267 }
1268
1269- if (!EC_POINT_mul(data->grp->group, data->my_element, NULL,
1270- data->grp->pwe, mask, data->bnctx)) {
1271+ if (crypto_ec_point_mul(data->grp->group, data->grp->pwe, mask,
1272+ data->my_element) < 0) {
1273 wpa_printf(MSG_INFO, "EAP-PWD (peer): element allocation "
1274 "fail");
1275 eap_pwd_state(data, FAILURE);
1276 goto fin;
1277 }
1278
1279- if (!EC_POINT_invert(data->grp->group, data->my_element, data->bnctx))
1280- {
1281+ if (crypto_ec_point_invert(data->grp->group, data->my_element) < 0) {
1282 wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail");
1283 goto fin;
1284 }
1285- BN_clear_free(mask);
1286-
1287- if (((x = BN_new()) == NULL) ||
1288- ((y = BN_new()) == NULL)) {
1289- wpa_printf(MSG_INFO, "EAP-PWD (peer): point allocation fail");
1290- goto fin;
1291- }
1292
1293 /* process the request */
1294- if (((data->server_scalar = BN_new()) == NULL) ||
1295- ((data->k = BN_new()) == NULL) ||
1296- ((K = EC_POINT_new(data->grp->group)) == NULL) ||
1297- ((point = EC_POINT_new(data->grp->group)) == NULL) ||
1298- ((data->server_element = EC_POINT_new(data->grp->group)) == NULL))
1299- {
1300+ data->k = crypto_bignum_init();
1301+ K = crypto_ec_point_init(data->grp->group);
1302+ if (!data->k || !K) {
1303 wpa_printf(MSG_INFO, "EAP-PWD (peer): peer data allocation "
1304 "fail");
1305 goto fin;
1306 }
1307
1308 /* element, x then y, followed by scalar */
1309- ptr = (u8 *) payload;
1310- BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x);
1311- ptr += BN_num_bytes(data->grp->prime);
1312- BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y);
1313- ptr += BN_num_bytes(data->grp->prime);
1314- BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->server_scalar);
1315- if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group,
1316- data->server_element, x, y,
1317- data->bnctx)) {
1318+ ptr = payload;
1319+ data->server_element = eap_pwd_get_element(data->grp, ptr);
1320+ if (!data->server_element) {
1321 wpa_printf(MSG_INFO, "EAP-PWD (peer): setting peer element "
1322 "fail");
1323 goto fin;
1324 }
1325-
1326- /* check to ensure server's element is not in a small sub-group */
1327- if (BN_cmp(cofactor, BN_value_one())) {
1328- if (!EC_POINT_mul(data->grp->group, point, NULL,
1329- data->server_element, cofactor, NULL)) {
1330- wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply "
1331- "server element by order!\n");
1332- goto fin;
1333- }
1334- if (EC_POINT_is_at_infinity(data->grp->group, point)) {
1335- wpa_printf(MSG_INFO, "EAP-PWD (peer): server element "
1336- "is at infinity!\n");
1337- goto fin;
1338- }
1339+ ptr += prime_len * 2;
1340+ data->server_scalar = eap_pwd_get_scalar(data->grp, ptr);
1341+ if (!data->server_scalar) {
1342+ wpa_printf(MSG_INFO,
1343+ "EAP-PWD (peer): setting peer scalar fail");
1344+ goto fin;
1345 }
1346
1347 /* compute the shared key, k */
1348- if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe,
1349- data->server_scalar, data->bnctx)) ||
1350- (!EC_POINT_add(data->grp->group, K, K, data->server_element,
1351- data->bnctx)) ||
1352- (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value,
1353- data->bnctx))) {
1354+ if (crypto_ec_point_mul(data->grp->group, data->grp->pwe,
1355+ data->server_scalar, K) < 0 ||
1356+ crypto_ec_point_add(data->grp->group, K, data->server_element,
1357+ K) < 0 ||
1358+ crypto_ec_point_mul(data->grp->group, K, data->private_value,
1359+ K) < 0) {
1360 wpa_printf(MSG_INFO, "EAP-PWD (peer): computing shared key "
1361 "fail");
1362 goto fin;
1363 }
1364
1365 /* ensure that the shared key isn't in a small sub-group */
1366- if (BN_cmp(cofactor, BN_value_one())) {
1367- if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor,
1368- NULL)) {
1369+ if (!crypto_bignum_is_one(cofactor)) {
1370+ if (crypto_ec_point_mul(data->grp->group, K, cofactor, K) < 0) {
1371 wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply "
1372 "shared key point by order");
1373 goto fin;
1374@@ -435,30 +403,22 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
1375 * never going to happen it is a simple and safe check "just to be
1376 * sure" so let's be safe.
1377 */
1378- if (EC_POINT_is_at_infinity(data->grp->group, K)) {
1379+ if (crypto_ec_point_is_at_infinity(data->grp->group, K)) {
1380 wpa_printf(MSG_INFO, "EAP-PWD (peer): shared key point is at "
1381 "infinity!\n");
1382 goto fin;
1383 }
1384
1385- if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k,
1386- NULL, data->bnctx)) {
1387+ if (crypto_ec_point_x(data->grp->group, K, data->k) < 0) {
1388 wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to extract "
1389 "shared secret from point");
1390 goto fin;
1391 }
1392
1393 /* now do the response */
1394- if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
1395- data->my_element, x, y,
1396- data->bnctx)) {
1397- wpa_printf(MSG_INFO, "EAP-PWD (peer): point assignment fail");
1398- goto fin;
1399- }
1400-
1401- if (((scalar = os_malloc(BN_num_bytes(data->grp->order))) == NULL) ||
1402- ((element = os_malloc(BN_num_bytes(data->grp->prime) * 2)) ==
1403- NULL)) {
1404+ scalar = os_zalloc(order_len);
1405+ element = os_zalloc(prime_len * 2);
1406+ if (!scalar || !element) {
1407 wpa_printf(MSG_INFO, "EAP-PWD (peer): data allocation fail");
1408 goto fin;
1409 }
1410@@ -468,35 +428,27 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
1411 * sufficiently smaller than the prime or order might need pre-pending
1412 * with zeros.
1413 */
1414- os_memset(scalar, 0, BN_num_bytes(data->grp->order));
1415- os_memset(element, 0, BN_num_bytes(data->grp->prime) * 2);
1416- offset = BN_num_bytes(data->grp->order) -
1417- BN_num_bytes(data->my_scalar);
1418- BN_bn2bin(data->my_scalar, scalar + offset);
1419-
1420- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
1421- BN_bn2bin(x, element + offset);
1422- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
1423- BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset);
1424-
1425- data->outbuf = wpabuf_alloc(BN_num_bytes(data->grp->order) +
1426- 2 * BN_num_bytes(data->grp->prime));
1427+ crypto_bignum_to_bin(data->my_scalar, scalar, order_len, order_len);
1428+ if (crypto_ec_point_to_bin(data->grp->group, data->my_element, element,
1429+ element + prime_len) != 0) {
1430+ wpa_printf(MSG_INFO, "EAP-PWD (peer): point assignment fail");
1431+ goto fin;
1432+ }
1433+
1434+ data->outbuf = wpabuf_alloc(order_len + 2 * prime_len);
1435 if (data->outbuf == NULL)
1436 goto fin;
1437
1438 /* we send the element as (x,y) follwed by the scalar */
1439- wpabuf_put_data(data->outbuf, element,
1440- 2 * BN_num_bytes(data->grp->prime));
1441- wpabuf_put_data(data->outbuf, scalar, BN_num_bytes(data->grp->order));
1442+ wpabuf_put_data(data->outbuf, element, 2 * prime_len);
1443+ wpabuf_put_data(data->outbuf, scalar, order_len);
1444
1445 fin:
1446 os_free(scalar);
1447 os_free(element);
1448- BN_clear_free(x);
1449- BN_clear_free(y);
1450- BN_clear_free(cofactor);
1451- EC_POINT_clear_free(K);
1452- EC_POINT_clear_free(point);
1453+ crypto_bignum_deinit(mask, 1);
1454+ crypto_bignum_deinit(cofactor, 1);
1455+ crypto_ec_point_deinit(K, 1);
1456 if (data->outbuf == NULL)
1457 eap_pwd_state(data, FAILURE);
1458 else
1459@@ -510,12 +462,11 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
1460 const struct wpabuf *reqData,
1461 const u8 *payload, size_t payload_len)
1462 {
1463- BIGNUM *x = NULL, *y = NULL;
1464 struct crypto_hash *hash;
1465 u32 cs;
1466 u16 grp;
1467 u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
1468- int offset;
1469+ size_t prime_len = 0, order_len = 0;
1470
1471 if (data->state != PWD_Confirm_Req) {
1472 ret->ignore = TRUE;
1473@@ -529,6 +480,9 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
1474 goto fin;
1475 }
1476
1477+ prime_len = crypto_ec_prime_len(data->grp->group);
1478+ order_len = crypto_ec_order_len(data->grp->group);
1479+
1480 /*
1481 * first build up the ciphersuite which is group | random_function |
1482 * prf
1483@@ -541,9 +495,9 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
1484 ptr += sizeof(u8);
1485 *ptr = EAP_PWD_DEFAULT_PRF;
1486
1487- /* each component of the cruft will be at most as big as the prime */
1488- if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||
1489- ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {
1490+ /* each component of the point will be at most as big as the prime */
1491+ cruft = os_malloc(prime_len * 2);
1492+ if (!cruft) {
1493 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm allocation "
1494 "fail");
1495 goto fin;
1496@@ -561,59 +515,34 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
1497 * zero the memory each time because this is mod prime math and some
1498 * value may start with a few zeros and the previous one did not.
1499 */
1500- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1501- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);
1502- BN_bn2bin(data->k, cruft + offset);
1503- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1504+ crypto_bignum_to_bin(data->k, cruft, prime_len, prime_len);
1505+ eap_pwd_h_update(hash, cruft, prime_len);
1506
1507 /* server element: x, y */
1508- if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
1509- data->server_element, x, y,
1510- data->bnctx)) {
1511+ if (crypto_ec_point_to_bin(data->grp->group, data->server_element,
1512+ cruft, cruft + prime_len) != 0) {
1513 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
1514 "assignment fail");
1515 goto fin;
1516 }
1517- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1518- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
1519- BN_bn2bin(x, cruft + offset);
1520- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1521- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1522- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
1523- BN_bn2bin(y, cruft + offset);
1524- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1525+ eap_pwd_h_update(hash, cruft, prime_len * 2);
1526
1527 /* server scalar */
1528- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1529- offset = BN_num_bytes(data->grp->order) -
1530- BN_num_bytes(data->server_scalar);
1531- BN_bn2bin(data->server_scalar, cruft + offset);
1532- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
1533+ crypto_bignum_to_bin(data->server_scalar, cruft, order_len, order_len);
1534+ eap_pwd_h_update(hash, cruft, order_len);
1535
1536 /* my element: x, y */
1537- if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
1538- data->my_element, x, y,
1539- data->bnctx)) {
1540+ if (crypto_ec_point_to_bin(data->grp->group, data->my_element, cruft,
1541+ cruft + prime_len) != 0) {
1542 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
1543 "assignment fail");
1544 goto fin;
1545 }
1546-
1547- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1548- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
1549- BN_bn2bin(x, cruft + offset);
1550- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1551- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1552- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
1553- BN_bn2bin(y, cruft + offset);
1554- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1555+ eap_pwd_h_update(hash, cruft, prime_len * 2);
1556
1557 /* my scalar */
1558- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1559- offset = BN_num_bytes(data->grp->order) -
1560- BN_num_bytes(data->my_scalar);
1561- BN_bn2bin(data->my_scalar, cruft + offset);
1562- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
1563+ crypto_bignum_to_bin(data->my_scalar, cruft, order_len, order_len);
1564+ eap_pwd_h_update(hash, cruft, order_len);
1565
1566 /* the ciphersuite */
1567 eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));
1568@@ -639,58 +568,34 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
1569 goto fin;
1570
1571 /* k */
1572- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1573- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);
1574- BN_bn2bin(data->k, cruft + offset);
1575- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1576+ crypto_bignum_to_bin(data->k, cruft, prime_len, prime_len);
1577+ eap_pwd_h_update(hash, cruft, prime_len);
1578
1579 /* my element */
1580- if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
1581- data->my_element, x, y,
1582- data->bnctx)) {
1583+ if (crypto_ec_point_to_bin(data->grp->group, data->my_element, cruft,
1584+ cruft + prime_len) != 0) {
1585 wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point "
1586 "assignment fail");
1587 goto fin;
1588 }
1589- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1590- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
1591- BN_bn2bin(x, cruft + offset);
1592- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1593- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1594- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
1595- BN_bn2bin(y, cruft + offset);
1596- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1597+ eap_pwd_h_update(hash, cruft, prime_len * 2);
1598
1599 /* my scalar */
1600- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1601- offset = BN_num_bytes(data->grp->order) -
1602- BN_num_bytes(data->my_scalar);
1603- BN_bn2bin(data->my_scalar, cruft + offset);
1604- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
1605+ crypto_bignum_to_bin(data->my_scalar, cruft, order_len, order_len);
1606+ eap_pwd_h_update(hash, cruft, order_len);
1607
1608 /* server element: x, y */
1609- if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
1610- data->server_element, x, y,
1611- data->bnctx)) {
1612+ if (crypto_ec_point_to_bin(data->grp->group, data->server_element,
1613+ cruft, cruft + prime_len) != 0) {
1614 wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point "
1615 "assignment fail");
1616 goto fin;
1617 }
1618- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1619- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
1620- BN_bn2bin(x, cruft + offset);
1621- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1622- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1623- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
1624- BN_bn2bin(y, cruft + offset);
1625- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1626+ eap_pwd_h_update(hash, cruft, prime_len * 2);
1627
1628 /* server scalar */
1629- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1630- offset = BN_num_bytes(data->grp->order) -
1631- BN_num_bytes(data->server_scalar);
1632- BN_bn2bin(data->server_scalar, cruft + offset);
1633- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
1634+ crypto_bignum_to_bin(data->server_scalar, cruft, order_len, order_len);
1635+ eap_pwd_h_update(hash, cruft, order_len);
1636
1637 /* the ciphersuite */
1638 eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));
1639@@ -698,7 +603,7 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
1640 /* all done */
1641 eap_pwd_h_final(hash, conf);
1642
1643- if (compute_keys(data->grp, data->bnctx, data->k,
1644+ if (compute_keys(data->grp, data->k,
1645 data->my_scalar, data->server_scalar, conf, ptr,
1646 &cs, data->msk, data->emsk, data->session_id) < 0) {
1647 wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute MSK | "
1648@@ -713,10 +618,7 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
1649 wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN);
1650
1651 fin:
1652- if (data->grp)
1653- bin_clear_free(cruft, BN_num_bytes(data->grp->prime));
1654- BN_clear_free(x);
1655- BN_clear_free(y);
1656+ bin_clear_free(cruft, prime_len * 2);
1657 if (data->outbuf == NULL) {
1658 ret->methodState = METHOD_DONE;
1659 ret->decision = DECISION_FAIL;
1660@@ -843,6 +745,13 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret,
1661 * buffer and ACK the fragment
1662 */
1663 if (EAP_PWD_GET_MORE_BIT(lm_exch) || data->in_frag_pos) {
1664+ if (!data->inbuf) {
1665+ wpa_printf(MSG_DEBUG,
1666+ "EAP-pwd: No buffer for reassembly");
1667+ ret->methodState = METHOD_DONE;
1668+ ret->decision = DECISION_FAIL;
1669+ return NULL;
1670+ }
1671 data->in_frag_pos += len;
1672 if (data->in_frag_pos > wpabuf_size(data->inbuf)) {
1673 wpa_printf(MSG_INFO, "EAP-pwd: Buffer overflow attack "
1674@@ -869,7 +778,7 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret,
1675 /*
1676 * we're buffering and this is the last fragment
1677 */
1678- if (data->in_frag_pos) {
1679+ if (data->in_frag_pos && data->inbuf) {
1680 wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",
1681 (int) len);
1682 pos = wpabuf_head_u8(data->inbuf);
1683diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c
1684index f57649b..853ad27 100644
1685--- a/src/eap_server/eap_server_pwd.c
1686+++ b/src/eap_server/eap_server_pwd.c
1687@@ -10,6 +10,7 @@
1688
1689 #include "common.h"
1690 #include "crypto/sha256.h"
1691+#include "crypto/crypto.h"
1692 #include "eap_server/eap_i.h"
1693 #include "eap_common/eap_pwd_common.h"
1694
1695@@ -34,20 +35,18 @@ struct eap_pwd_data {
1696 size_t out_frag_pos;
1697 size_t mtu;
1698
1699- BIGNUM *k;
1700- BIGNUM *private_value;
1701- BIGNUM *peer_scalar;
1702- BIGNUM *my_scalar;
1703- EC_POINT *my_element;
1704- EC_POINT *peer_element;
1705+ struct crypto_bignum *k;
1706+ struct crypto_bignum *private_value;
1707+ struct crypto_bignum *peer_scalar;
1708+ struct crypto_bignum *my_scalar;
1709+ struct crypto_ec_point *my_element;
1710+ struct crypto_ec_point *peer_element;
1711
1712 u8 my_confirm[SHA256_MAC_LEN];
1713
1714 u8 msk[EAP_MSK_LEN];
1715 u8 emsk[EAP_EMSK_LEN];
1716 u8 session_id[1 + SHA256_MAC_LEN];
1717-
1718- BN_CTX *bnctx;
1719 };
1720
1721
1722@@ -113,15 +112,6 @@ static void * eap_pwd_init(struct eap_sm *sm)
1723 data->password_len = sm->user->password_len;
1724 os_memcpy(data->password, sm->user->password, data->password_len);
1725
1726- data->bnctx = BN_CTX_new();
1727- if (data->bnctx == NULL) {
1728- wpa_printf(MSG_INFO, "EAP-PWD: bn context allocation fail");
1729- bin_clear_free(data->password, data->password_len);
1730- bin_clear_free(data->id_server, data->id_server_len);
1731- os_free(data);
1732- return NULL;
1733- }
1734-
1735 data->in_frag_pos = data->out_frag_pos = 0;
1736 data->inbuf = data->outbuf = NULL;
1737 /* use default MTU from RFC 5931 if not configured otherwise */
1738@@ -135,21 +125,18 @@ static void eap_pwd_reset(struct eap_sm *sm, void *priv)
1739 {
1740 struct eap_pwd_data *data = priv;
1741
1742- BN_clear_free(data->private_value);
1743- BN_clear_free(data->peer_scalar);
1744- BN_clear_free(data->my_scalar);
1745- BN_clear_free(data->k);
1746- BN_CTX_free(data->bnctx);
1747- EC_POINT_clear_free(data->my_element);
1748- EC_POINT_clear_free(data->peer_element);
1749+ crypto_bignum_deinit(data->private_value, 1);
1750+ crypto_bignum_deinit(data->peer_scalar, 1);
1751+ crypto_bignum_deinit(data->my_scalar, 1);
1752+ crypto_bignum_deinit(data->k, 1);
1753+ crypto_ec_point_deinit(data->my_element, 1);
1754+ crypto_ec_point_deinit(data->peer_element, 1);
1755 bin_clear_free(data->id_peer, data->id_peer_len);
1756 bin_clear_free(data->id_server, data->id_server_len);
1757 bin_clear_free(data->password, data->password_len);
1758 if (data->grp) {
1759- EC_GROUP_free(data->grp->group);
1760- EC_POINT_clear_free(data->grp->pwe);
1761- BN_clear_free(data->grp->order);
1762- BN_clear_free(data->grp->prime);
1763+ crypto_ec_deinit(data->grp->group);
1764+ crypto_ec_point_deinit(data->grp->pwe, 1);
1765 os_free(data->grp);
1766 }
1767 wpabuf_free(data->inbuf);
1768@@ -189,9 +176,9 @@ static void eap_pwd_build_id_req(struct eap_sm *sm, struct eap_pwd_data *data,
1769 static void eap_pwd_build_commit_req(struct eap_sm *sm,
1770 struct eap_pwd_data *data, u8 id)
1771 {
1772- BIGNUM *mask = NULL, *x = NULL, *y = NULL;
1773+ struct crypto_bignum *mask = NULL;
1774 u8 *scalar = NULL, *element = NULL;
1775- u16 offset;
1776+ size_t prime_len, order_len;
1777
1778 wpa_printf(MSG_DEBUG, "EAP-pwd: Commit/Request");
1779 /*
1780@@ -201,93 +188,75 @@ static void eap_pwd_build_commit_req(struct eap_sm *sm,
1781 if (data->out_frag_pos)
1782 return;
1783
1784- if (((data->private_value = BN_new()) == NULL) ||
1785- ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) ||
1786- ((data->my_scalar = BN_new()) == NULL) ||
1787- ((mask = BN_new()) == NULL)) {
1788+ prime_len = crypto_ec_prime_len(data->grp->group);
1789+ order_len = crypto_ec_order_len(data->grp->group);
1790+
1791+ data->private_value = crypto_bignum_init();
1792+ data->my_element = crypto_ec_point_init(data->grp->group);
1793+ data->my_scalar = crypto_bignum_init();
1794+ mask = crypto_bignum_init();
1795+ if (!data->private_value || !data->my_element || !data->my_scalar ||
1796+ !mask) {
1797 wpa_printf(MSG_INFO, "EAP-PWD (server): scalar allocation "
1798 "fail");
1799 goto fin;
1800 }
1801
1802- if (BN_rand_range(data->private_value, data->grp->order) != 1 ||
1803- BN_rand_range(mask, data->grp->order) != 1 ||
1804- BN_add(data->my_scalar, data->private_value, mask) != 1 ||
1805- BN_mod(data->my_scalar, data->my_scalar, data->grp->order,
1806- data->bnctx) != 1) {
1807+ if (crypto_bignum_rand(data->private_value,
1808+ crypto_ec_get_order(data->grp->group)) < 0 ||
1809+ crypto_bignum_rand(mask,
1810+ crypto_ec_get_order(data->grp->group)) < 0 ||
1811+ crypto_bignum_add(data->private_value, mask, data->my_scalar) < 0 ||
1812+ crypto_bignum_mod(data->my_scalar,
1813+ crypto_ec_get_order(data->grp->group),
1814+ data->my_scalar) < 0) {
1815 wpa_printf(MSG_INFO,
1816 "EAP-pwd (server): unable to get randomness");
1817 goto fin;
1818 }
1819
1820- if (!EC_POINT_mul(data->grp->group, data->my_element, NULL,
1821- data->grp->pwe, mask, data->bnctx)) {
1822+ if (crypto_ec_point_mul(data->grp->group, data->grp->pwe, mask,
1823+ data->my_element) < 0) {
1824 wpa_printf(MSG_INFO, "EAP-PWD (server): element allocation "
1825 "fail");
1826 eap_pwd_state(data, FAILURE);
1827 goto fin;
1828 }
1829
1830- if (!EC_POINT_invert(data->grp->group, data->my_element, data->bnctx))
1831- {
1832+ if (crypto_ec_point_invert(data->grp->group, data->my_element) < 0) {
1833 wpa_printf(MSG_INFO, "EAP-PWD (server): element inversion "
1834 "fail");
1835 goto fin;
1836 }
1837- BN_clear_free(mask);
1838
1839- if (((x = BN_new()) == NULL) ||
1840- ((y = BN_new()) == NULL)) {
1841- wpa_printf(MSG_INFO, "EAP-PWD (server): point allocation "
1842- "fail");
1843+ scalar = os_malloc(order_len);
1844+ element = os_malloc(prime_len * 2);
1845+ if (!scalar || !element) {
1846+ wpa_printf(MSG_INFO, "EAP-PWD (server): data allocation fail");
1847 goto fin;
1848 }
1849- if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
1850- data->my_element, x, y,
1851- data->bnctx)) {
1852+
1853+ if (crypto_ec_point_to_bin(data->grp->group, data->my_element, element,
1854+ element + prime_len) < 0) {
1855 wpa_printf(MSG_INFO, "EAP-PWD (server): point assignment "
1856 "fail");
1857 goto fin;
1858 }
1859
1860- if (((scalar = os_malloc(BN_num_bytes(data->grp->order))) == NULL) ||
1861- ((element = os_malloc(BN_num_bytes(data->grp->prime) * 2)) ==
1862- NULL)) {
1863- wpa_printf(MSG_INFO, "EAP-PWD (server): data allocation fail");
1864- goto fin;
1865- }
1866+ crypto_bignum_to_bin(data->my_scalar, scalar, order_len, order_len);
1867
1868- /*
1869- * bignums occupy as little memory as possible so one that is
1870- * sufficiently smaller than the prime or order might need pre-pending
1871- * with zeros.
1872- */
1873- os_memset(scalar, 0, BN_num_bytes(data->grp->order));
1874- os_memset(element, 0, BN_num_bytes(data->grp->prime) * 2);
1875- offset = BN_num_bytes(data->grp->order) -
1876- BN_num_bytes(data->my_scalar);
1877- BN_bn2bin(data->my_scalar, scalar + offset);
1878-
1879- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
1880- BN_bn2bin(x, element + offset);
1881- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
1882- BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset);
1883-
1884- data->outbuf = wpabuf_alloc(2 * BN_num_bytes(data->grp->prime) +
1885- BN_num_bytes(data->grp->order));
1886+ data->outbuf = wpabuf_alloc(2 * prime_len + order_len);
1887 if (data->outbuf == NULL)
1888 goto fin;
1889
1890 /* We send the element as (x,y) followed by the scalar */
1891- wpabuf_put_data(data->outbuf, element,
1892- 2 * BN_num_bytes(data->grp->prime));
1893- wpabuf_put_data(data->outbuf, scalar, BN_num_bytes(data->grp->order));
1894+ wpabuf_put_data(data->outbuf, element, 2 * prime_len);
1895+ wpabuf_put_data(data->outbuf, scalar, order_len);
1896
1897 fin:
1898+ crypto_bignum_deinit(mask, 1);
1899 os_free(scalar);
1900 os_free(element);
1901- BN_clear_free(x);
1902- BN_clear_free(y);
1903 if (data->outbuf == NULL)
1904 eap_pwd_state(data, FAILURE);
1905 }
1906@@ -296,11 +265,10 @@ fin:
1907 static void eap_pwd_build_confirm_req(struct eap_sm *sm,
1908 struct eap_pwd_data *data, u8 id)
1909 {
1910- BIGNUM *x = NULL, *y = NULL;
1911 struct crypto_hash *hash;
1912 u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
1913 u16 grp;
1914- int offset;
1915+ size_t prime_len, order_len;
1916
1917 wpa_printf(MSG_DEBUG, "EAP-pwd: Confirm/Request");
1918 /*
1919@@ -310,9 +278,12 @@ static void eap_pwd_build_confirm_req(struct eap_sm *sm,
1920 if (data->out_frag_pos)
1921 return;
1922
1923+ prime_len = crypto_ec_prime_len(data->grp->group);
1924+ order_len = crypto_ec_order_len(data->grp->group);
1925+
1926 /* Each component of the cruft will be at most as big as the prime */
1927- if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||
1928- ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {
1929+ cruft = os_malloc(prime_len * 2);
1930+ if (!cruft) {
1931 wpa_printf(MSG_INFO, "EAP-PWD (server): debug allocation "
1932 "fail");
1933 goto fin;
1934@@ -332,64 +303,38 @@ static void eap_pwd_build_confirm_req(struct eap_sm *sm,
1935 *
1936 * First is k
1937 */
1938- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1939- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);
1940- BN_bn2bin(data->k, cruft + offset);
1941- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1942+ crypto_bignum_to_bin(data->k, cruft, prime_len, prime_len);
1943+ eap_pwd_h_update(hash, cruft, prime_len);
1944
1945 /* server element: x, y */
1946- if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
1947- data->my_element, x, y,
1948- data->bnctx)) {
1949+ if (crypto_ec_point_to_bin(data->grp->group, data->my_element, cruft,
1950+ cruft + prime_len) < 0) {
1951 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
1952 "assignment fail");
1953 goto fin;
1954 }
1955-
1956- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1957- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
1958- BN_bn2bin(x, cruft + offset);
1959- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1960- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1961- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
1962- BN_bn2bin(y, cruft + offset);
1963- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1964+ eap_pwd_h_update(hash, cruft, prime_len * 2);
1965
1966 /* server scalar */
1967- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1968- offset = BN_num_bytes(data->grp->order) -
1969- BN_num_bytes(data->my_scalar);
1970- BN_bn2bin(data->my_scalar, cruft + offset);
1971- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
1972+ crypto_bignum_to_bin(data->my_scalar, cruft, order_len, order_len);
1973+ eap_pwd_h_update(hash, cruft, order_len);
1974
1975 /* peer element: x, y */
1976- if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
1977- data->peer_element, x, y,
1978- data->bnctx)) {
1979+ if (crypto_ec_point_to_bin(data->grp->group, data->peer_element, cruft,
1980+ cruft + prime_len) < 0) {
1981 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
1982 "assignment fail");
1983 goto fin;
1984 }
1985-
1986- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1987- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
1988- BN_bn2bin(x, cruft + offset);
1989- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1990- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1991- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
1992- BN_bn2bin(y, cruft + offset);
1993- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
1994+ eap_pwd_h_update(hash, cruft, prime_len * 2);
1995
1996 /* peer scalar */
1997- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
1998- offset = BN_num_bytes(data->grp->order) -
1999- BN_num_bytes(data->peer_scalar);
2000- BN_bn2bin(data->peer_scalar, cruft + offset);
2001- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
2002+ crypto_bignum_to_bin(data->peer_scalar, cruft, order_len, order_len);
2003+ eap_pwd_h_update(hash, cruft, order_len);
2004
2005 /* ciphersuite */
2006 grp = htons(data->group_num);
2007- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
2008+ os_memset(cruft, 0, prime_len);
2009 ptr = cruft;
2010 os_memcpy(ptr, &grp, sizeof(u16));
2011 ptr += sizeof(u16);
2012@@ -410,9 +355,7 @@ static void eap_pwd_build_confirm_req(struct eap_sm *sm,
2013 wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN);
2014
2015 fin:
2016- bin_clear_free(cruft, BN_num_bytes(data->grp->prime));
2017- BN_clear_free(x);
2018- BN_clear_free(y);
2019+ bin_clear_free(cruft, prime_len * 2);
2020 if (data->outbuf == NULL)
2021 eap_pwd_state(data, FAILURE);
2022 }
2023@@ -604,7 +547,7 @@ static void eap_pwd_process_id_resp(struct eap_sm *sm,
2024 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PWD (server): peer sent id of",
2025 data->id_peer, data->id_peer_len);
2026
2027- data->grp = os_zalloc(sizeof(EAP_PWD_group));
2028+ data->grp = get_eap_pwd_group(data->group_num);
2029 if (data->grp == NULL) {
2030 wpa_printf(MSG_INFO, "EAP-PWD: failed to allocate memory for "
2031 "group");
2032@@ -620,7 +563,7 @@ static void eap_pwd_process_id_resp(struct eap_sm *sm,
2033 return;
2034 }
2035 wpa_printf(MSG_DEBUG, "EAP-PWD (server): computed %d bit PWE...",
2036- BN_num_bits(data->grp->prime));
2037+ (int) crypto_ec_prime_len_bits(data->grp->group));
2038
2039 eap_pwd_state(data, PWD_Commit_Req);
2040 }
2041@@ -630,16 +573,16 @@ static void
2042 eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
2043 const u8 *payload, size_t payload_len)
2044 {
2045- u8 *ptr;
2046- BIGNUM *x = NULL, *y = NULL, *cofactor = NULL;
2047- EC_POINT *K = NULL, *point = NULL;
2048+ const u8 *ptr;
2049+ struct crypto_bignum *cofactor = NULL;
2050+ struct crypto_ec_point *K = NULL;
2051 int res = 0;
2052 size_t prime_len, order_len;
2053
2054 wpa_printf(MSG_DEBUG, "EAP-pwd: Received commit response");
2055
2056- prime_len = BN_num_bytes(data->grp->prime);
2057- order_len = BN_num_bytes(data->grp->order);
2058+ prime_len = crypto_ec_prime_len(data->grp->group);
2059+ order_len = crypto_ec_order_len(data->grp->group);
2060
2061 if (payload_len != 2 * prime_len + order_len) {
2062 wpa_printf(MSG_INFO,
2063@@ -649,71 +592,62 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
2064 goto fin;
2065 }
2066
2067- if (((data->peer_scalar = BN_new()) == NULL) ||
2068- ((data->k = BN_new()) == NULL) ||
2069- ((cofactor = BN_new()) == NULL) ||
2070- ((x = BN_new()) == NULL) ||
2071- ((y = BN_new()) == NULL) ||
2072- ((point = EC_POINT_new(data->grp->group)) == NULL) ||
2073- ((K = EC_POINT_new(data->grp->group)) == NULL) ||
2074- ((data->peer_element = EC_POINT_new(data->grp->group)) == NULL)) {
2075+ data->k = crypto_bignum_init();
2076+ cofactor = crypto_bignum_init();
2077+ K = crypto_ec_point_init(data->grp->group);
2078+ if (!data->k || !cofactor || !K) {
2079 wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation "
2080 "fail");
2081 goto fin;
2082 }
2083
2084- if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) {
2085+ if (crypto_ec_cofactor(data->grp->group, cofactor) < 0) {
2086 wpa_printf(MSG_INFO, "EAP-PWD (server): unable to get "
2087 "cofactor for curve");
2088 goto fin;
2089 }
2090
2091 /* element, x then y, followed by scalar */
2092- ptr = (u8 *) payload;
2093- BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x);
2094- ptr += BN_num_bytes(data->grp->prime);
2095- BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y);
2096- ptr += BN_num_bytes(data->grp->prime);
2097- BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->peer_scalar);
2098- if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group,
2099- data->peer_element, x, y,
2100- data->bnctx)) {
2101+ ptr = payload;
2102+ data->peer_element = eap_pwd_get_element(data->grp, ptr);
2103+ if (!data->peer_element) {
2104 wpa_printf(MSG_INFO, "EAP-PWD (server): setting peer element "
2105 "fail");
2106 goto fin;
2107 }
2108+ ptr += prime_len * 2;
2109+ data->peer_scalar = eap_pwd_get_scalar(data->grp, ptr);
2110+ if (!data->peer_scalar) {
2111+ wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation "
2112+ "fail");
2113+ goto fin;
2114+ }
2115
2116- /* check to ensure peer's element is not in a small sub-group */
2117- if (BN_cmp(cofactor, BN_value_one())) {
2118- if (!EC_POINT_mul(data->grp->group, point, NULL,
2119- data->peer_element, cofactor, NULL)) {
2120- wpa_printf(MSG_INFO, "EAP-PWD (server): cannot "
2121- "multiply peer element by order");
2122- goto fin;
2123- }
2124- if (EC_POINT_is_at_infinity(data->grp->group, point)) {
2125- wpa_printf(MSG_INFO, "EAP-PWD (server): peer element "
2126- "is at infinity!\n");
2127- goto fin;
2128- }
2129+ /* detect reflection attacks */
2130+ if (crypto_bignum_cmp(data->my_scalar, data->peer_scalar) == 0 ||
2131+ crypto_ec_point_cmp(data->grp->group, data->my_element,
2132+ data->peer_element) == 0) {
2133+ wpa_printf(MSG_INFO,
2134+ "EAP-PWD (server): detected reflection attack!");
2135+ goto fin;
2136 }
2137
2138 /* compute the shared key, k */
2139- if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe,
2140- data->peer_scalar, data->bnctx)) ||
2141- (!EC_POINT_add(data->grp->group, K, K, data->peer_element,
2142- data->bnctx)) ||
2143- (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value,
2144- data->bnctx))) {
2145+ if ((crypto_ec_point_mul(data->grp->group, data->grp->pwe,
2146+ data->peer_scalar, K) < 0) ||
2147+ (crypto_ec_point_add(data->grp->group, K, data->peer_element,
2148+ K) < 0) ||
2149+ (crypto_ec_point_mul(data->grp->group, K, data->private_value,
2150+ K) < 0)) {
2151 wpa_printf(MSG_INFO, "EAP-PWD (server): computing shared key "
2152 "fail");
2153 goto fin;
2154 }
2155
2156 /* ensure that the shared key isn't in a small sub-group */
2157- if (BN_cmp(cofactor, BN_value_one())) {
2158- if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor,
2159- NULL)) {
2160+ if (!crypto_bignum_is_one(cofactor)) {
2161+ if (crypto_ec_point_mul(data->grp->group, K, cofactor,
2162+ K) != 0) {
2163 wpa_printf(MSG_INFO, "EAP-PWD (server): cannot "
2164 "multiply shared key point by order!\n");
2165 goto fin;
2166@@ -726,13 +660,12 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
2167 * never going to happen it is a simple and safe check "just to be
2168 * sure" so let's be safe.
2169 */
2170- if (EC_POINT_is_at_infinity(data->grp->group, K)) {
2171+ if (crypto_ec_point_is_at_infinity(data->grp->group, K)) {
2172 wpa_printf(MSG_INFO, "EAP-PWD (server): shared key point is "
2173 "at infinity");
2174 goto fin;
2175 }
2176- if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k,
2177- NULL, data->bnctx)) {
2178+ if (crypto_ec_point_x(data->grp->group, K, data->k)) {
2179 wpa_printf(MSG_INFO, "EAP-PWD (server): unable to extract "
2180 "shared secret from secret point");
2181 goto fin;
2182@@ -740,11 +673,8 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
2183 res = 1;
2184
2185 fin:
2186- EC_POINT_clear_free(K);
2187- EC_POINT_clear_free(point);
2188- BN_clear_free(cofactor);
2189- BN_clear_free(x);
2190- BN_clear_free(y);
2191+ crypto_ec_point_deinit(K, 1);
2192+ crypto_bignum_deinit(cofactor, 1);
2193
2194 if (res)
2195 eap_pwd_state(data, PWD_Confirm_Req);
2196@@ -757,12 +687,14 @@ static void
2197 eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
2198 const u8 *payload, size_t payload_len)
2199 {
2200- BIGNUM *x = NULL, *y = NULL;
2201 struct crypto_hash *hash;
2202 u32 cs;
2203 u16 grp;
2204 u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
2205- int offset;
2206+ size_t prime_len, order_len;
2207+
2208+ prime_len = crypto_ec_prime_len(data->grp->group);
2209+ order_len = crypto_ec_order_len(data->grp->group);
2210
2211 if (payload_len != SHA256_MAC_LEN) {
2212 wpa_printf(MSG_INFO,
2213@@ -781,8 +713,8 @@ eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
2214 *ptr = EAP_PWD_DEFAULT_PRF;
2215
2216 /* each component of the cruft will be at most as big as the prime */
2217- if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||
2218- ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {
2219+ cruft = os_malloc(prime_len * 2);
2220+ if (!cruft) {
2221 wpa_printf(MSG_INFO, "EAP-PWD (peer): allocation fail");
2222 goto fin;
2223 }
2224@@ -796,62 +728,36 @@ eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
2225 goto fin;
2226
2227 /* k */
2228- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
2229- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);
2230- BN_bn2bin(data->k, cruft + offset);
2231- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
2232+ crypto_bignum_to_bin(data->k, cruft, prime_len, prime_len);
2233+ eap_pwd_h_update(hash, cruft, prime_len);
2234
2235 /* peer element: x, y */
2236- if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
2237- data->peer_element, x, y,
2238- data->bnctx)) {
2239+ if (crypto_ec_point_to_bin(data->grp->group, data->peer_element, cruft,
2240+ cruft + prime_len) < 0) {
2241 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
2242 "assignment fail");
2243 goto fin;
2244 }
2245- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
2246- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
2247- BN_bn2bin(x, cruft + offset);
2248- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
2249- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
2250- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
2251- BN_bn2bin(y, cruft + offset);
2252- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
2253+ eap_pwd_h_update(hash, cruft, prime_len * 2);
2254
2255 /* peer scalar */
2256- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
2257- offset = BN_num_bytes(data->grp->order) -
2258- BN_num_bytes(data->peer_scalar);
2259- BN_bn2bin(data->peer_scalar, cruft + offset);
2260- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
2261+ crypto_bignum_to_bin(data->peer_scalar, cruft, order_len, order_len);
2262+ eap_pwd_h_update(hash, cruft, order_len);
2263
2264 /* server element: x, y */
2265- if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
2266- data->my_element, x, y,
2267- data->bnctx)) {
2268+ if (crypto_ec_point_to_bin(data->grp->group, data->my_element, cruft,
2269+ cruft + prime_len) < 0) {
2270 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
2271 "assignment fail");
2272 goto fin;
2273 }
2274-
2275- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
2276- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
2277- BN_bn2bin(x, cruft + offset);
2278- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
2279- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
2280- offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
2281- BN_bn2bin(y, cruft + offset);
2282- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
2283+ eap_pwd_h_update(hash, cruft, prime_len * 2);
2284
2285 /* server scalar */
2286- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
2287- offset = BN_num_bytes(data->grp->order) -
2288- BN_num_bytes(data->my_scalar);
2289- BN_bn2bin(data->my_scalar, cruft + offset);
2290- eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
2291+ crypto_bignum_to_bin(data->my_scalar, cruft, order_len, order_len);
2292+ eap_pwd_h_update(hash, cruft, order_len);
2293
2294 /* ciphersuite */
2295- os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
2296 eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));
2297
2298 /* all done */
2299@@ -865,7 +771,7 @@ eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
2300 }
2301
2302 wpa_printf(MSG_DEBUG, "EAP-pwd (server): confirm verified");
2303- if (compute_keys(data->grp, data->bnctx, data->k,
2304+ if (compute_keys(data->grp, data->k,
2305 data->peer_scalar, data->my_scalar, conf,
2306 data->my_confirm, &cs, data->msk, data->emsk,
2307 data->session_id) < 0)
2308@@ -874,9 +780,7 @@ eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
2309 eap_pwd_state(data, SUCCESS);
2310
2311 fin:
2312- bin_clear_free(cruft, BN_num_bytes(data->grp->prime));
2313- BN_clear_free(x);
2314- BN_clear_free(y);
2315+ bin_clear_free(cruft, prime_len * 2);
2316 }
2317
2318
2319diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
2320index f8a11ea..7d20b98 100644
2321--- a/src/rsn_supp/wpa.c
2322+++ b/src/rsn_supp/wpa.c
2323@@ -2004,6 +2004,17 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
2324
2325 if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) &&
2326 (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
2327+ /*
2328+ * Only decrypt the Key Data field if the frame's authenticity
2329+ * was verified. When using AES-SIV (FILS), the MIC flag is not
2330+ * set, so this check should only be performed if mic_len != 0
2331+ * which is the case in this code branch.
2332+ */
2333+ if (!(key_info & WPA_KEY_INFO_MIC)) {
2334+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2335+ "WPA: Ignore EAPOL-Key with encrypted but unauthenticated data");
2336+ goto out;
2337+ }
2338 if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data,
2339 &key_data_len))
2340 goto out;
2341diff --git a/src/utils/common.c b/src/utils/common.c
2342index 5fd795f..66668b0 100644
2343--- a/src/utils/common.c
2344+++ b/src/utils/common.c
2345@@ -671,6 +671,29 @@ int is_hex(const u8 *data, size_t len)
2346 }
2347
2348
2349+int has_ctrl_char(const u8 *data, size_t len)
2350+{
2351+ size_t i;
2352+
2353+ for (i = 0; i < len; i++) {
2354+ if (data[i] < 32 || data[i] == 127)
2355+ return 1;
2356+ }
2357+ return 0;
2358+}
2359+
2360+
2361+int has_newline(const char *str)
2362+{
2363+ while (*str) {
2364+ if (*str == '\n' || *str == '\r')
2365+ return 1;
2366+ str++;
2367+ }
2368+ return 0;
2369+}
2370+
2371+
2372 size_t merge_byte_arrays(u8 *res, size_t res_len,
2373 const u8 *src1, size_t src1_len,
2374 const u8 *src2, size_t src2_len)
2375diff --git a/src/utils/common.h b/src/utils/common.h
2376index 576e8e7..a5a3bdf 100644
2377--- a/src/utils/common.h
2378+++ b/src/utils/common.h
2379@@ -501,6 +501,8 @@ const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len);
2380
2381 char * wpa_config_parse_string(const char *value, size_t *len);
2382 int is_hex(const u8 *data, size_t len);
2383+int has_ctrl_char(const u8 *data, size_t len);
2384+int has_newline(const char *str);
2385 size_t merge_byte_arrays(u8 *res, size_t res_len,
2386 const u8 *src1, size_t src1_len,
2387 const u8 *src2, size_t src2_len);
2388diff --git a/src/utils/const_time.h b/src/utils/const_time.h
2389new file mode 100644
2390index 0000000..ab8f611
2391--- /dev/null
2392+++ b/src/utils/const_time.h
2393@@ -0,0 +1,191 @@
2394+/*
2395+ * Helper functions for constant time operations
2396+ * Copyright (c) 2019, The Linux Foundation
2397+ *
2398+ * This software may be distributed under the terms of the BSD license.
2399+ * See README for more details.
2400+ *
2401+ * These helper functions can be used to implement logic that needs to minimize
2402+ * externally visible differences in execution path by avoiding use of branches,
2403+ * avoiding early termination or other time differences, and forcing same memory
2404+ * access pattern regardless of values.
2405+ */
2406+
2407+#ifndef CONST_TIME_H
2408+#define CONST_TIME_H
2409+
2410+
2411+#if defined(__clang__)
2412+#define NO_UBSAN_UINT_OVERFLOW \
2413+ __attribute__((no_sanitize("unsigned-integer-overflow")))
2414+#else
2415+#define NO_UBSAN_UINT_OVERFLOW
2416+#endif
2417+
2418+
2419+/**
2420+ * const_time_fill_msb - Fill all bits with MSB value
2421+ * @val: Input value
2422+ * Returns: Value with all the bits set to the MSB of the input val
2423+ */
2424+static inline unsigned int const_time_fill_msb(unsigned int val)
2425+{
2426+ /* Move the MSB to LSB and multiple by -1 to fill in all bits. */
2427+ return (val >> (sizeof(val) * 8 - 1)) * ~0U;
2428+}
2429+
2430+
2431+/* Returns: -1 if val is zero; 0 if val is not zero */
2432+static inline unsigned int const_time_is_zero(unsigned int val)
2433+ NO_UBSAN_UINT_OVERFLOW
2434+{
2435+ /* Set MSB to 1 for 0 and fill rest of bits with the MSB value */
2436+ return const_time_fill_msb(~val & (val - 1));
2437+}
2438+
2439+
2440+/* Returns: -1 if a == b; 0 if a != b */
2441+static inline unsigned int const_time_eq(unsigned int a, unsigned int b)
2442+{
2443+ return const_time_is_zero(a ^ b);
2444+}
2445+
2446+
2447+/* Returns: -1 if a == b; 0 if a != b */
2448+static inline u8 const_time_eq_u8(unsigned int a, unsigned int b)
2449+{
2450+ return (u8) const_time_eq(a, b);
2451+}
2452+
2453+
2454+/**
2455+ * const_time_eq_bin - Constant time memory comparison
2456+ * @a: First buffer to compare
2457+ * @b: Second buffer to compare
2458+ * @len: Number of octets to compare
2459+ * Returns: -1 if buffers are equal, 0 if not
2460+ *
2461+ * This function is meant for comparing passwords or hash values where
2462+ * difference in execution time or memory access pattern could provide external
2463+ * observer information about the location of the difference in the memory
2464+ * buffers. The return value does not behave like memcmp(), i.e.,
2465+ * const_time_eq_bin() cannot be used to sort items into a defined order. Unlike
2466+ * memcmp(), the execution time of const_time_eq_bin() does not depend on the
2467+ * contents of the compared memory buffers, but only on the total compared
2468+ * length.
2469+ */
2470+static inline unsigned int const_time_eq_bin(const void *a, const void *b,
2471+ size_t len)
2472+{
2473+ const u8 *aa = a;
2474+ const u8 *bb = b;
2475+ size_t i;
2476+ u8 res = 0;
2477+
2478+ for (i = 0; i < len; i++)
2479+ res |= aa[i] ^ bb[i];
2480+
2481+ return const_time_is_zero(res);
2482+}
2483+
2484+
2485+/**
2486+ * const_time_select - Constant time unsigned int selection
2487+ * @mask: 0 (false) or -1 (true) to identify which value to select
2488+ * @true_val: Value to select for the true case
2489+ * @false_val: Value to select for the false case
2490+ * Returns: true_val if mask == -1, false_val if mask == 0
2491+ */
2492+static inline unsigned int const_time_select(unsigned int mask,
2493+ unsigned int true_val,
2494+ unsigned int false_val)
2495+{
2496+ return (mask & true_val) | (~mask & false_val);
2497+}
2498+
2499+
2500+/**
2501+ * const_time_select_int - Constant time int selection
2502+ * @mask: 0 (false) or -1 (true) to identify which value to select
2503+ * @true_val: Value to select for the true case
2504+ * @false_val: Value to select for the false case
2505+ * Returns: true_val if mask == -1, false_val if mask == 0
2506+ */
2507+static inline int const_time_select_int(unsigned int mask, int true_val,
2508+ int false_val)
2509+{
2510+ return (int) const_time_select(mask, (unsigned int) true_val,
2511+ (unsigned int) false_val);
2512+}
2513+
2514+
2515+/**
2516+ * const_time_select_u8 - Constant time u8 selection
2517+ * @mask: 0 (false) or -1 (true) to identify which value to select
2518+ * @true_val: Value to select for the true case
2519+ * @false_val: Value to select for the false case
2520+ * Returns: true_val if mask == -1, false_val if mask == 0
2521+ */
2522+static inline u8 const_time_select_u8(u8 mask, u8 true_val, u8 false_val)
2523+{
2524+ return (u8) const_time_select(mask, true_val, false_val);
2525+}
2526+
2527+
2528+/**
2529+ * const_time_select_s8 - Constant time s8 selection
2530+ * @mask: 0 (false) or -1 (true) to identify which value to select
2531+ * @true_val: Value to select for the true case
2532+ * @false_val: Value to select for the false case
2533+ * Returns: true_val if mask == -1, false_val if mask == 0
2534+ */
2535+static inline s8 const_time_select_s8(u8 mask, s8 true_val, s8 false_val)
2536+{
2537+ return (s8) const_time_select(mask, (unsigned int) true_val,
2538+ (unsigned int) false_val);
2539+}
2540+
2541+
2542+/**
2543+ * const_time_select_bin - Constant time binary buffer selection copy
2544+ * @mask: 0 (false) or -1 (true) to identify which value to copy
2545+ * @true_val: Buffer to copy for the true case
2546+ * @false_val: Buffer to copy for the false case
2547+ * @len: Number of octets to copy
2548+ * @dst: Destination buffer for the copy
2549+ *
2550+ * This function copies the specified buffer into the destination buffer using
2551+ * operations with identical memory access pattern regardless of which buffer
2552+ * is being copied.
2553+ */
2554+static inline void const_time_select_bin(u8 mask, const u8 *true_val,
2555+ const u8 *false_val, size_t len,
2556+ u8 *dst)
2557+{
2558+ size_t i;
2559+
2560+ for (i = 0; i < len; i++)
2561+ dst[i] = const_time_select_u8(mask, true_val[i], false_val[i]);
2562+}
2563+
2564+
2565+static inline int const_time_memcmp(const void *a, const void *b, size_t len)
2566+{
2567+ const u8 *aa = a;
2568+ const u8 *bb = b;
2569+ int diff, res = 0;
2570+ unsigned int mask;
2571+
2572+ if (len == 0)
2573+ return 0;
2574+ do {
2575+ len--;
2576+ diff = (int) aa[len] - (int) bb[len];
2577+ mask = const_time_is_zero((unsigned int) diff);
2578+ res = const_time_select_int(mask, res, diff);
2579+ } while (len);
2580+
2581+ return res;
2582+}
2583+
2584+#endif /* CONST_TIME_H */
2585diff --git a/src/wps/wps.h b/src/wps/wps.h
2586index 0a7f65d..c10dc4f 100644
2587--- a/src/wps/wps.h
2588+++ b/src/wps/wps.h
2589@@ -826,7 +826,7 @@ int wps_build_credential_wrap(struct wpabuf *msg,
2590
2591 unsigned int wps_pin_checksum(unsigned int pin);
2592 unsigned int wps_pin_valid(unsigned int pin);
2593-unsigned int wps_generate_pin(void);
2594+int wps_generate_pin(unsigned int *pin);
2595 int wps_pin_str_valid(const char *pin);
2596 void wps_free_pending_msgs(struct upnp_pending_message *msgs);
2597
2598diff --git a/src/wps/wps_attr_process.c b/src/wps/wps_attr_process.c
2599index eadb22f..e8c4579 100644
2600--- a/src/wps/wps_attr_process.c
2601+++ b/src/wps/wps_attr_process.c
2602@@ -229,6 +229,16 @@ static int wps_workaround_cred_key(struct wps_credential *cred)
2603 cred->key_len--;
2604 #endif /* CONFIG_WPS_STRICT */
2605 }
2606+
2607+
2608+ if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) &&
2609+ (cred->key_len < 8 || has_ctrl_char(cred->key, cred->key_len))) {
2610+ wpa_printf(MSG_INFO, "WPS: Reject credential with invalid WPA/WPA2-Personal passphrase");
2611+ wpa_hexdump_ascii_key(MSG_INFO, "WPS: Network Key",
2612+ cred->key, cred->key_len);
2613+ return -1;
2614+ }
2615+
2616 return 0;
2617 }
2618
2619diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c
2620index c1ede6a..ca11901 100644
2621--- a/src/wps/wps_common.c
2622+++ b/src/wps/wps_common.c
2623@@ -235,20 +235,18 @@ unsigned int wps_pin_valid(unsigned int pin)
2624 * wps_generate_pin - Generate a random PIN
2625 * Returns: Eight digit PIN (i.e., including the checksum digit)
2626 */
2627-unsigned int wps_generate_pin(void)
2628+int wps_generate_pin(unsigned int *pin)
2629 {
2630 unsigned int val;
2631
2632 /* Generate seven random digits for the PIN */
2633- if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) {
2634- struct os_time now;
2635- os_get_time(&now);
2636- val = os_random() ^ now.sec ^ now.usec;
2637- }
2638+ if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0)
2639+ return -1;
2640 val %= 10000000;
2641
2642 /* Append checksum digit */
2643- return val * 10 + wps_pin_checksum(val);
2644+ *pin = val * 10 + wps_pin_checksum(val);
2645+ return 0;
2646 }
2647
2648
2649diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
2650index 579582b..cb66e99 100644
2651--- a/wpa_supplicant/Android.mk
2652+++ b/wpa_supplicant/Android.mk
2653@@ -626,6 +626,7 @@ OBJS += src/eap_peer/eap_pwd.c src/eap_common/eap_pwd_common.c
2654 OBJS_h += src/eap_server/eap_server_pwd.c
2655 CONFIG_IEEE8021X_EAPOL=y
2656 NEED_SHA256=y
2657+NEED_ECC=y
2658 endif
2659
2660 ifdef CONFIG_EAP_EKE
2661diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
2662index d9a11be..a2d6619 100644
2663--- a/wpa_supplicant/Makefile
2664+++ b/wpa_supplicant/Makefile
2665@@ -630,6 +630,7 @@ OBJS += ../src/eap_peer/eap_pwd.o ../src/eap_common/eap_pwd_common.o
2666 OBJS_h += ../src/eap_server/eap_server_pwd.o
2667 CONFIG_IEEE8021X_EAPOL=y
2668 NEED_SHA256=y
2669+NEED_ECC=y
2670 endif
2671
2672 ifdef CONFIG_EAP_EKE
2673diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
2674index 7ecf7a8..96a1d9a 100644
2675--- a/wpa_supplicant/ap.c
2676+++ b/wpa_supplicant/ap.c
2677@@ -836,7 +836,10 @@ int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
2678 return -1;
2679
2680 if (pin == NULL) {
2681- unsigned int rpin = wps_generate_pin();
2682+ unsigned int rpin;
2683+
2684+ if (wps_generate_pin(&rpin) < 0)
2685+ return -1;
2686 ret_len = os_snprintf(buf, buflen, "%08d", rpin);
2687 if (os_snprintf_error(buflen, ret_len))
2688 return -1;
2689@@ -902,7 +905,8 @@ const char * wpas_wps_ap_pin_random(struct wpa_supplicant *wpa_s, int timeout)
2690 if (wpa_s->ap_iface == NULL)
2691 return NULL;
2692 hapd = wpa_s->ap_iface->bss[0];
2693- pin = wps_generate_pin();
2694+ if (wps_generate_pin(&pin) < 0)
2695+ return NULL;
2696 os_snprintf(pin_txt, sizeof(pin_txt), "%08u", pin);
2697 os_free(hapd->conf->ap_pin);
2698 hapd->conf->ap_pin = os_strdup(pin_txt);
2699diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
2700index 8e6cd20..e095cf7 100644
2701--- a/wpa_supplicant/config.c
2702+++ b/wpa_supplicant/config.c
2703@@ -455,6 +455,12 @@ static int wpa_config_parse_psk(const struct parse_data *data,
2704 }
2705 wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
2706 (u8 *) value, len);
2707+ if (has_ctrl_char((u8 *) value, len)) {
2708+ wpa_printf(MSG_ERROR,
2709+ "Line %d: Invalid passphrase character",
2710+ line);
2711+ return -1;
2712+ }
2713 if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
2714 os_memcmp(ssid->passphrase, value, len) == 0)
2715 return 0;
2716@@ -2586,8 +2592,19 @@ char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
2717
2718 for (i = 0; i < NUM_SSID_FIELDS; i++) {
2719 const struct parse_data *field = &ssid_fields[i];
2720- if (os_strcmp(var, field->name) == 0)
2721- return field->writer(field, ssid);
2722+ if (os_strcmp(var, field->name) == 0) {
2723+ char *ret = field->writer(field, ssid);
2724+
2725+ if (ret && has_newline(ret)) {
2726+ wpa_printf(MSG_ERROR,
2727+ "Found newline in value for %s; not returning it",
2728+ var);
2729+ os_free(ret);
2730+ ret = NULL;
2731+ }
2732+
2733+ return ret;
2734+ }
2735 }
2736
2737 return NULL;
2738@@ -2772,6 +2789,8 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
2739
2740 if (os_strcmp(var, "password") == 0 &&
2741 os_strncmp(value, "ext:", 4) == 0) {
2742+ if (has_newline(value))
2743+ return -1;
2744 str_clear_free(cred->password);
2745 cred->password = os_strdup(value);
2746 cred->ext_password = 1;
2747@@ -2822,9 +2841,14 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
2748 }
2749
2750 val = wpa_config_parse_string(value, &len);
2751- if (val == NULL) {
2752+ if (val == NULL ||
2753+ (os_strcmp(var, "excluded_ssid") != 0 &&
2754+ os_strcmp(var, "roaming_consortium") != 0 &&
2755+ os_strcmp(var, "required_roaming_consortium") != 0 &&
2756+ has_newline(val))) {
2757 wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string "
2758 "value '%s'.", line, var, value);
2759+ os_free(val);
2760 return -1;
2761 }
2762
2763@@ -3625,6 +3649,12 @@ static int wpa_global_config_parse_str(const struct global_parse_data *data,
2764 return -1;
2765 }
2766
2767+ if (has_newline(pos)) {
2768+ wpa_printf(MSG_ERROR, "Line %d: invalid %s value with newline",
2769+ line, data->name);
2770+ return -1;
2771+ }
2772+
2773 tmp = os_strdup(pos);
2774 if (tmp == NULL)
2775 return -1;
2776diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
2777index 79280af..d030ef7 100644
2778--- a/wpa_supplicant/ctrl_iface.c
2779+++ b/wpa_supplicant/ctrl_iface.c
2780@@ -893,7 +893,8 @@ static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
2781 if (os_strcmp(cmd, "any") == 0)
2782 _bssid = NULL;
2783 else if (os_strcmp(cmd, "get") == 0) {
2784- ret = wps_generate_pin();
2785+ if (wps_generate_pin((unsigned int *) &ret) < 0)
2786+ return -1;
2787 goto done;
2788 } else if (hwaddr_aton(cmd, bssid)) {
2789 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
2790diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
2791index b200ca0..511bc9d 100644
2792--- a/wpa_supplicant/p2p_supplicant.c
2793+++ b/wpa_supplicant/p2p_supplicant.c
2794@@ -3671,7 +3671,13 @@ static void wpas_prov_disc_req(void *ctx, const u8 *peer, u16 config_methods,
2795 params[sizeof(params) - 1] = '\0';
2796
2797 if (config_methods & WPS_CONFIG_DISPLAY) {
2798- generated_pin = wps_generate_pin();
2799+ if (wps_generate_pin(&generated_pin) < 0) {
2800+ wpa_printf(MSG_DEBUG, "P2P: Could not generate PIN");
2801+ wpas_notify_p2p_provision_discovery(
2802+ wpa_s, peer, 0 /* response */,
2803+ P2P_PROV_DISC_INFO_UNAVAILABLE, 0, 0);
2804+ return;
2805+ }
2806 wpas_prov_disc_local_display(wpa_s, peer, params,
2807 generated_pin);
2808 } else if (config_methods & WPS_CONFIG_KEYPAD)
2809@@ -3716,7 +3722,13 @@ static void wpas_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods)
2810 if (config_methods & WPS_CONFIG_DISPLAY)
2811 wpas_prov_disc_local_keypad(wpa_s, peer, params);
2812 else if (config_methods & WPS_CONFIG_KEYPAD) {
2813- generated_pin = wps_generate_pin();
2814+ if (wps_generate_pin(&generated_pin) < 0) {
2815+ wpa_printf(MSG_DEBUG, "P2P: Could not generate PIN");
2816+ wpas_notify_p2p_provision_discovery(
2817+ wpa_s, peer, 0 /* response */,
2818+ P2P_PROV_DISC_INFO_UNAVAILABLE, 0, 0);
2819+ return;
2820+ }
2821 wpas_prov_disc_local_display(wpa_s, peer, params,
2822 generated_pin);
2823 } else if (config_methods & WPS_CONFIG_PUSHBUTTON)
2824@@ -6065,7 +6077,8 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
2825 if (pin)
2826 os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
2827 else if (wps_method == WPS_PIN_DISPLAY) {
2828- ret = wps_generate_pin();
2829+ if (wps_generate_pin((unsigned int *) &ret) < 0)
2830+ return -1;
2831 res = os_snprintf(wpa_s->p2p_pin, sizeof(wpa_s->p2p_pin),
2832 "%08d", ret);
2833 if (os_snprintf_error(sizeof(wpa_s->p2p_pin), res))
2834diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
2835index eabe986..7691349 100644
2836--- a/wpa_supplicant/wps_supplicant.c
2837+++ b/wpa_supplicant/wps_supplicant.c
2838@@ -1195,7 +1195,10 @@ static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s,
2839 os_snprintf(val, sizeof(val), "\"dev_pw_id=%u%s\"",
2840 dev_pw_id, hash);
2841 } else {
2842- rpin = wps_generate_pin();
2843+ if (wps_generate_pin(&rpin) < 0) {
2844+ wpa_printf(MSG_DEBUG, "WPS: Could not generate PIN");
2845+ return -1;
2846+ }
2847 os_snprintf(val, sizeof(val), "\"pin=%08d dev_pw_id=%u%s\"",
2848 rpin, dev_pw_id, hash);
2849 }

Subscribers

People subscribed via source and target branches

to all changes: