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