Line data Source code
1 : /*
2 : * EAP server/peer: EAP-EKE shared routines
3 : * Copyright (c) 2011-2013, Jouni Malinen <j@w1.fi>
4 : *
5 : * This software may be distributed under the terms of the BSD license.
6 : * See README for more details.
7 : */
8 :
9 : #include "includes.h"
10 :
11 : #include "common.h"
12 : #include "crypto/aes.h"
13 : #include "crypto/aes_wrap.h"
14 : #include "crypto/crypto.h"
15 : #include "crypto/dh_groups.h"
16 : #include "crypto/random.h"
17 : #include "crypto/sha1.h"
18 : #include "crypto/sha256.h"
19 : #include "eap_common/eap_defs.h"
20 : #include "eap_eke_common.h"
21 :
22 :
23 1557 : static int eap_eke_dh_len(u8 group)
24 : {
25 1557 : switch (group) {
26 : case EAP_EKE_DHGROUP_EKE_2:
27 4 : return 128;
28 : case EAP_EKE_DHGROUP_EKE_5:
29 0 : return 192;
30 : case EAP_EKE_DHGROUP_EKE_14:
31 1215 : return 256;
32 : case EAP_EKE_DHGROUP_EKE_15:
33 4 : return 384;
34 : case EAP_EKE_DHGROUP_EKE_16:
35 334 : return 512;
36 : }
37 :
38 0 : return -1;
39 : }
40 :
41 :
42 807 : static int eap_eke_dhcomp_len(u8 dhgroup, u8 encr)
43 : {
44 : int dhlen;
45 :
46 807 : dhlen = eap_eke_dh_len(dhgroup);
47 807 : if (dhlen < 0 || encr != EAP_EKE_ENCR_AES128_CBC)
48 0 : return -1;
49 807 : return AES_BLOCK_SIZE + dhlen;
50 : }
51 :
52 :
53 1494 : static const struct dh_group * eap_eke_dh_group(u8 group)
54 : {
55 1494 : switch (group) {
56 : case EAP_EKE_DHGROUP_EKE_2:
57 4 : return dh_groups_get(2);
58 : case EAP_EKE_DHGROUP_EKE_5:
59 0 : return dh_groups_get(5);
60 : case EAP_EKE_DHGROUP_EKE_14:
61 1209 : return dh_groups_get(14);
62 : case EAP_EKE_DHGROUP_EKE_15:
63 4 : return dh_groups_get(15);
64 : case EAP_EKE_DHGROUP_EKE_16:
65 277 : return dh_groups_get(16);
66 : }
67 :
68 0 : return NULL;
69 : }
70 :
71 :
72 760 : static int eap_eke_dh_generator(u8 group)
73 : {
74 760 : switch (group) {
75 : case EAP_EKE_DHGROUP_EKE_2:
76 2 : return 5;
77 : case EAP_EKE_DHGROUP_EKE_5:
78 0 : return 31;
79 : case EAP_EKE_DHGROUP_EKE_14:
80 605 : return 11;
81 : case EAP_EKE_DHGROUP_EKE_15:
82 2 : return 5;
83 : case EAP_EKE_DHGROUP_EKE_16:
84 151 : return 5;
85 : }
86 :
87 0 : return -1;
88 : }
89 :
90 :
91 807 : static int eap_eke_pnonce_len(u8 mac)
92 : {
93 : int mac_len;
94 :
95 807 : if (mac == EAP_EKE_MAC_HMAC_SHA1)
96 610 : mac_len = SHA1_MAC_LEN;
97 197 : else if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
98 197 : mac_len = SHA256_MAC_LEN;
99 : else
100 0 : return -1;
101 :
102 807 : return AES_BLOCK_SIZE + 16 + mac_len;
103 : }
104 :
105 :
106 807 : static int eap_eke_pnonce_ps_len(u8 mac)
107 : {
108 : int mac_len;
109 :
110 807 : if (mac == EAP_EKE_MAC_HMAC_SHA1)
111 610 : mac_len = SHA1_MAC_LEN;
112 197 : else if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
113 197 : mac_len = SHA256_MAC_LEN;
114 : else
115 0 : return -1;
116 :
117 807 : return AES_BLOCK_SIZE + 2 * 16 + mac_len;
118 : }
119 :
120 :
121 1614 : static int eap_eke_prf_len(u8 prf)
122 : {
123 1614 : if (prf == EAP_EKE_PRF_HMAC_SHA1)
124 1220 : return 20;
125 394 : if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
126 394 : return 32;
127 0 : return -1;
128 : }
129 :
130 :
131 807 : static int eap_eke_nonce_len(u8 prf)
132 : {
133 : int prf_len;
134 :
135 807 : prf_len = eap_eke_prf_len(prf);
136 807 : if (prf_len < 0)
137 0 : return -1;
138 :
139 807 : if (prf_len > 2 * 16)
140 0 : return (prf_len + 1) / 2;
141 :
142 807 : return 16;
143 : }
144 :
145 :
146 807 : static int eap_eke_auth_len(u8 prf)
147 : {
148 807 : switch (prf) {
149 : case EAP_EKE_PRF_HMAC_SHA1:
150 610 : return SHA1_MAC_LEN;
151 : case EAP_EKE_PRF_HMAC_SHA2_256:
152 197 : return SHA256_MAC_LEN;
153 : }
154 :
155 0 : return -1;
156 : }
157 :
158 :
159 760 : int eap_eke_dh_init(u8 group, u8 *ret_priv, u8 *ret_pub)
160 : {
161 : int generator;
162 : u8 gen;
163 : const struct dh_group *dh;
164 : size_t pub_len, i;
165 :
166 760 : generator = eap_eke_dh_generator(group);
167 760 : dh = eap_eke_dh_group(group);
168 760 : if (generator < 0 || generator > 255 || !dh)
169 0 : return -1;
170 760 : gen = generator;
171 :
172 : /* x = random number 2 .. p-1 */
173 760 : if (random_get_bytes(ret_priv, dh->prime_len))
174 3 : return -1;
175 757 : if (os_memcmp(ret_priv, dh->prime, dh->prime_len) > 0) {
176 : /* Make sure private value is smaller than prime */
177 0 : ret_priv[0] = 0;
178 : }
179 757 : for (i = 0; i < dh->prime_len - 1; i++) {
180 757 : if (ret_priv[i])
181 757 : break;
182 : }
183 757 : if (i == dh->prime_len - 1 && (ret_priv[i] == 0 || ret_priv[i] == 1))
184 0 : return -1;
185 757 : wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: DH private value",
186 : ret_priv, dh->prime_len);
187 :
188 : /* y = g ^ x (mod p) */
189 757 : pub_len = dh->prime_len;
190 757 : if (crypto_mod_exp(&gen, 1, ret_priv, dh->prime_len,
191 : dh->prime, dh->prime_len, ret_pub, &pub_len) < 0)
192 0 : return -1;
193 757 : if (pub_len < dh->prime_len) {
194 8 : size_t pad = dh->prime_len - pub_len;
195 8 : os_memmove(ret_pub + pad, ret_pub, pub_len);
196 8 : os_memset(ret_pub, 0, pad);
197 : }
198 :
199 757 : wpa_hexdump(MSG_DEBUG, "EAP-EKE: DH public value",
200 : ret_pub, dh->prime_len);
201 :
202 757 : return 0;
203 : }
204 :
205 :
206 2830 : static int eap_eke_prf(u8 prf, const u8 *key, size_t key_len, const u8 *data,
207 : size_t data_len, const u8 *data2, size_t data2_len,
208 : u8 *res)
209 : {
210 : const u8 *addr[2];
211 : size_t len[2];
212 2830 : size_t num_elem = 1;
213 :
214 2830 : addr[0] = data;
215 2830 : len[0] = data_len;
216 2830 : if (data2) {
217 1327 : num_elem++;
218 1327 : addr[1] = data2;
219 1327 : len[1] = data2_len;
220 : }
221 :
222 2830 : if (prf == EAP_EKE_PRF_HMAC_SHA1)
223 2414 : return hmac_sha1_vector(key, key_len, num_elem, addr, len, res);
224 416 : if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
225 416 : return hmac_sha256_vector(key, key_len, num_elem, addr, len,
226 : res);
227 0 : return -1;
228 : }
229 :
230 :
231 2414 : static int eap_eke_prf_hmac_sha1(const u8 *key, size_t key_len, const u8 *data,
232 : size_t data_len, u8 *res, size_t len)
233 : {
234 : u8 hash[SHA1_MAC_LEN];
235 : u8 idx;
236 : const u8 *addr[3];
237 : size_t vlen[3];
238 : int ret;
239 :
240 2414 : idx = 0;
241 2414 : addr[0] = hash;
242 2414 : vlen[0] = SHA1_MAC_LEN;
243 2414 : addr[1] = data;
244 2414 : vlen[1] = data_len;
245 2414 : addr[2] = &idx;
246 2414 : vlen[2] = 1;
247 :
248 11457 : while (len > 0) {
249 6630 : idx++;
250 6630 : if (idx == 1)
251 2414 : ret = hmac_sha1_vector(key, key_len, 2, &addr[1],
252 : &vlen[1], hash);
253 : else
254 4216 : ret = hmac_sha1_vector(key, key_len, 3, addr, vlen,
255 : hash);
256 6630 : if (ret < 0)
257 1 : return -1;
258 6629 : if (len > SHA1_MAC_LEN) {
259 4216 : os_memcpy(res, hash, SHA1_MAC_LEN);
260 4216 : res += SHA1_MAC_LEN;
261 4216 : len -= SHA1_MAC_LEN;
262 : } else {
263 2413 : os_memcpy(res, hash, len);
264 2413 : len = 0;
265 : }
266 : }
267 :
268 2413 : return 0;
269 : }
270 :
271 :
272 405 : static int eap_eke_prf_hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
273 : size_t data_len, u8 *res, size_t len)
274 : {
275 : u8 hash[SHA256_MAC_LEN];
276 : u8 idx;
277 : const u8 *addr[3];
278 : size_t vlen[3];
279 : int ret;
280 :
281 405 : idx = 0;
282 405 : addr[0] = hash;
283 405 : vlen[0] = SHA256_MAC_LEN;
284 405 : addr[1] = data;
285 405 : vlen[1] = data_len;
286 405 : addr[2] = &idx;
287 405 : vlen[2] = 1;
288 :
289 1441 : while (len > 0) {
290 649 : idx++;
291 649 : if (idx == 1)
292 405 : ret = hmac_sha256_vector(key, key_len, 2, &addr[1],
293 : &vlen[1], hash);
294 : else
295 244 : ret = hmac_sha256_vector(key, key_len, 3, addr, vlen,
296 : hash);
297 649 : if (ret < 0)
298 18 : return -1;
299 631 : if (len > SHA256_MAC_LEN) {
300 244 : os_memcpy(res, hash, SHA256_MAC_LEN);
301 244 : res += SHA256_MAC_LEN;
302 244 : len -= SHA256_MAC_LEN;
303 : } else {
304 387 : os_memcpy(res, hash, len);
305 387 : len = 0;
306 : }
307 : }
308 :
309 387 : return 0;
310 : }
311 :
312 :
313 2819 : static int eap_eke_prfplus(u8 prf, const u8 *key, size_t key_len,
314 : const u8 *data, size_t data_len, u8 *res, size_t len)
315 : {
316 2819 : if (prf == EAP_EKE_PRF_HMAC_SHA1)
317 2414 : return eap_eke_prf_hmac_sha1(key, key_len, data, data_len, res,
318 : len);
319 405 : if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
320 405 : return eap_eke_prf_hmac_sha256(key, key_len, data, data_len,
321 : res, len);
322 0 : return -1;
323 : }
324 :
325 :
326 771 : int eap_eke_derive_key(struct eap_eke_session *sess,
327 : const u8 *password, size_t password_len,
328 : const u8 *id_s, size_t id_s_len, const u8 *id_p,
329 : size_t id_p_len, u8 *key)
330 : {
331 : u8 zeros[EAP_EKE_MAX_HASH_LEN];
332 : u8 temp[EAP_EKE_MAX_HASH_LEN];
333 771 : size_t key_len = 16; /* Only AES-128-CBC is used here */
334 : u8 *id;
335 :
336 : /* temp = prf(0+, password) */
337 771 : os_memset(zeros, 0, sess->prf_len);
338 771 : if (eap_eke_prf(sess->prf, zeros, sess->prf_len,
339 : password, password_len, NULL, 0, temp) < 0)
340 4 : return -1;
341 767 : wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: temp = prf(0+, password)",
342 767 : temp, sess->prf_len);
343 :
344 : /* key = prf+(temp, ID_S | ID_P) */
345 767 : id = os_malloc(id_s_len + id_p_len);
346 767 : if (id == NULL)
347 2 : return -1;
348 765 : os_memcpy(id, id_s, id_s_len);
349 765 : os_memcpy(id + id_s_len, id_p, id_p_len);
350 765 : wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: ID_S | ID_P",
351 : id, id_s_len + id_p_len);
352 765 : if (eap_eke_prfplus(sess->prf, temp, sess->prf_len,
353 : id, id_s_len + id_p_len, key, key_len) < 0) {
354 4 : os_free(id);
355 4 : return -1;
356 : }
357 761 : os_free(id);
358 761 : wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: key = prf+(temp, ID_S | ID_P)",
359 : key, key_len);
360 :
361 761 : return 0;
362 : }
363 :
364 :
365 750 : int eap_eke_dhcomp(struct eap_eke_session *sess, const u8 *key, const u8 *dhpub,
366 : u8 *ret_dhcomp)
367 : {
368 : u8 pub[EAP_EKE_MAX_DH_LEN];
369 : int dh_len;
370 : u8 iv[AES_BLOCK_SIZE];
371 :
372 750 : dh_len = eap_eke_dh_len(sess->dhgroup);
373 750 : if (dh_len < 0)
374 0 : return -1;
375 :
376 : /*
377 : * DHComponent = Encr(key, y)
378 : *
379 : * All defined DH groups use primes that have length devisible by 16, so
380 : * no need to do extra padding for y (= pub).
381 : */
382 750 : if (sess->encr != EAP_EKE_ENCR_AES128_CBC)
383 0 : return -1;
384 750 : if (random_get_bytes(iv, AES_BLOCK_SIZE))
385 2 : return -1;
386 748 : wpa_hexdump(MSG_DEBUG, "EAP-EKE: IV for Encr(key, y)",
387 : iv, AES_BLOCK_SIZE);
388 748 : os_memcpy(pub, dhpub, dh_len);
389 748 : if (aes_128_cbc_encrypt(key, iv, pub, dh_len) < 0)
390 1 : return -1;
391 747 : os_memcpy(ret_dhcomp, iv, AES_BLOCK_SIZE);
392 747 : os_memcpy(ret_dhcomp + AES_BLOCK_SIZE, pub, dh_len);
393 747 : wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent = Encr(key, y)",
394 747 : ret_dhcomp, AES_BLOCK_SIZE + dh_len);
395 :
396 747 : return 0;
397 : }
398 :
399 :
400 734 : int eap_eke_shared_secret(struct eap_eke_session *sess, const u8 *key,
401 : const u8 *dhpriv, const u8 *peer_dhcomp)
402 : {
403 : u8 zeros[EAP_EKE_MAX_HASH_LEN];
404 : u8 peer_pub[EAP_EKE_MAX_DH_LEN];
405 : u8 modexp[EAP_EKE_MAX_DH_LEN];
406 : size_t len;
407 : const struct dh_group *dh;
408 :
409 734 : dh = eap_eke_dh_group(sess->dhgroup);
410 734 : if (sess->encr != EAP_EKE_ENCR_AES128_CBC || !dh)
411 0 : return -1;
412 :
413 : /* Decrypt peer DHComponent */
414 734 : os_memcpy(peer_pub, peer_dhcomp + AES_BLOCK_SIZE, dh->prime_len);
415 734 : if (aes_128_cbc_decrypt(key, peer_dhcomp, peer_pub, dh->prime_len) < 0) {
416 2 : wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt DHComponent");
417 2 : return -1;
418 : }
419 732 : wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Decrypted peer DH pubkey",
420 : peer_pub, dh->prime_len);
421 :
422 : /* SharedSecret = prf(0+, g ^ (x_s * x_p) (mod p)) */
423 732 : len = dh->prime_len;
424 732 : if (crypto_mod_exp(peer_pub, dh->prime_len, dhpriv, dh->prime_len,
425 : dh->prime, dh->prime_len, modexp, &len) < 0)
426 0 : return -1;
427 732 : if (len < dh->prime_len) {
428 0 : size_t pad = dh->prime_len - len;
429 0 : os_memmove(modexp + pad, modexp, len);
430 0 : os_memset(modexp, 0, pad);
431 : }
432 :
433 732 : os_memset(zeros, 0, sess->auth_len);
434 732 : if (eap_eke_prf(sess->prf, zeros, sess->auth_len, modexp, dh->prime_len,
435 732 : NULL, 0, sess->shared_secret) < 0)
436 2 : return -1;
437 1460 : wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: SharedSecret",
438 1460 : sess->shared_secret, sess->auth_len);
439 :
440 730 : return 0;
441 : }
442 :
443 :
444 730 : int eap_eke_derive_ke_ki(struct eap_eke_session *sess,
445 : const u8 *id_s, size_t id_s_len,
446 : const u8 *id_p, size_t id_p_len)
447 : {
448 : u8 buf[EAP_EKE_MAX_KE_LEN + EAP_EKE_MAX_KI_LEN];
449 : size_t ke_len, ki_len;
450 : u8 *data;
451 : size_t data_len;
452 730 : const char *label = "EAP-EKE Keys";
453 : size_t label_len;
454 :
455 : /*
456 : * Ke | Ki = prf+(SharedSecret, "EAP-EKE Keys" | ID_S | ID_P)
457 : * Ke = encryption key
458 : * Ki = integrity protection key
459 : * Length of each key depends on the selected algorithms.
460 : */
461 :
462 730 : if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
463 730 : ke_len = 16;
464 : else
465 0 : return -1;
466 :
467 730 : if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
468 604 : ki_len = 20;
469 126 : else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
470 126 : ki_len = 32;
471 : else
472 0 : return -1;
473 :
474 730 : label_len = os_strlen(label);
475 730 : data_len = label_len + id_s_len + id_p_len;
476 730 : data = os_malloc(data_len);
477 730 : if (data == NULL)
478 3 : return -1;
479 727 : os_memcpy(data, label, label_len);
480 727 : os_memcpy(data + label_len, id_s, id_s_len);
481 727 : os_memcpy(data + label_len + id_s_len, id_p, id_p_len);
482 727 : if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
483 : data, data_len, buf, ke_len + ki_len) < 0) {
484 4 : os_free(data);
485 4 : return -1;
486 : }
487 :
488 723 : os_memcpy(sess->ke, buf, ke_len);
489 723 : wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ke", sess->ke, ke_len);
490 723 : os_memcpy(sess->ki, buf + ke_len, ki_len);
491 723 : wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ki", sess->ki, ki_len);
492 :
493 723 : os_free(data);
494 723 : return 0;
495 : }
496 :
497 :
498 681 : int eap_eke_derive_ka(struct eap_eke_session *sess,
499 : const u8 *id_s, size_t id_s_len,
500 : const u8 *id_p, size_t id_p_len,
501 : const u8 *nonce_p, const u8 *nonce_s)
502 : {
503 : u8 *data, *pos;
504 : size_t data_len;
505 681 : const char *label = "EAP-EKE Ka";
506 : size_t label_len;
507 :
508 : /*
509 : * Ka = prf+(SharedSecret, "EAP-EKE Ka" | ID_S | ID_P | Nonce_P |
510 : * Nonce_S)
511 : * Ka = authentication key
512 : * Length of the key depends on the selected algorithms.
513 : */
514 :
515 681 : label_len = os_strlen(label);
516 681 : data_len = label_len + id_s_len + id_p_len + 2 * sess->nonce_len;
517 681 : data = os_malloc(data_len);
518 681 : if (data == NULL)
519 2 : return -1;
520 679 : pos = data;
521 679 : os_memcpy(pos, label, label_len);
522 679 : pos += label_len;
523 679 : os_memcpy(pos, id_s, id_s_len);
524 679 : pos += id_s_len;
525 679 : os_memcpy(pos, id_p, id_p_len);
526 679 : pos += id_p_len;
527 679 : os_memcpy(pos, nonce_p, sess->nonce_len);
528 679 : pos += sess->nonce_len;
529 679 : os_memcpy(pos, nonce_s, sess->nonce_len);
530 1358 : if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
531 1358 : data, data_len, sess->ka, sess->prf_len) < 0) {
532 4 : os_free(data);
533 4 : return -1;
534 : }
535 675 : os_free(data);
536 :
537 675 : wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ka", sess->ka, sess->prf_len);
538 :
539 675 : return 0;
540 : }
541 :
542 :
543 650 : int eap_eke_derive_msk(struct eap_eke_session *sess,
544 : const u8 *id_s, size_t id_s_len,
545 : const u8 *id_p, size_t id_p_len,
546 : const u8 *nonce_p, const u8 *nonce_s,
547 : u8 *msk, u8 *emsk)
548 : {
549 : u8 *data, *pos;
550 : size_t data_len;
551 650 : const char *label = "EAP-EKE Exported Keys";
552 : size_t label_len;
553 : u8 buf[EAP_MSK_LEN + EAP_EMSK_LEN];
554 :
555 : /*
556 : * MSK | EMSK = prf+(SharedSecret, "EAP-EKE Exported Keys" | ID_S |
557 : * ID_P | Nonce_P | Nonce_S)
558 : */
559 :
560 650 : label_len = os_strlen(label);
561 650 : data_len = label_len + id_s_len + id_p_len + 2 * sess->nonce_len;
562 650 : data = os_malloc(data_len);
563 650 : if (data == NULL)
564 2 : return -1;
565 648 : pos = data;
566 648 : os_memcpy(pos, label, label_len);
567 648 : pos += label_len;
568 648 : os_memcpy(pos, id_s, id_s_len);
569 648 : pos += id_s_len;
570 648 : os_memcpy(pos, id_p, id_p_len);
571 648 : pos += id_p_len;
572 648 : os_memcpy(pos, nonce_p, sess->nonce_len);
573 648 : pos += sess->nonce_len;
574 648 : os_memcpy(pos, nonce_s, sess->nonce_len);
575 648 : if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
576 : data, data_len, buf, EAP_MSK_LEN + EAP_EMSK_LEN) <
577 : 0) {
578 7 : os_free(data);
579 7 : return -1;
580 : }
581 641 : os_free(data);
582 :
583 641 : os_memcpy(msk, buf, EAP_MSK_LEN);
584 641 : os_memcpy(emsk, buf + EAP_MSK_LEN, EAP_EMSK_LEN);
585 641 : os_memset(buf, 0, sizeof(buf));
586 :
587 641 : wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: MSK", msk, EAP_MSK_LEN);
588 641 : wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: EMSK", msk, EAP_EMSK_LEN);
589 :
590 641 : return 0;
591 : }
592 :
593 :
594 2055 : static int eap_eke_mac(u8 mac, const u8 *key, const u8 *data, size_t data_len,
595 : u8 *res)
596 : {
597 2055 : if (mac == EAP_EKE_MAC_HMAC_SHA1)
598 1809 : return hmac_sha1(key, SHA1_MAC_LEN, data, data_len, res);
599 246 : if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
600 246 : return hmac_sha256(key, SHA256_MAC_LEN, data, data_len, res);
601 0 : return -1;
602 : }
603 :
604 :
605 1041 : int eap_eke_prot(struct eap_eke_session *sess,
606 : const u8 *data, size_t data_len,
607 : u8 *prot, size_t *prot_len)
608 : {
609 : size_t block_size, icv_len, pad;
610 : u8 *pos, *iv, *e;
611 :
612 1041 : if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
613 1041 : block_size = AES_BLOCK_SIZE;
614 : else
615 0 : return -1;
616 :
617 1041 : if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
618 905 : icv_len = SHA1_MAC_LEN;
619 136 : else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
620 136 : icv_len = SHA256_MAC_LEN;
621 : else
622 0 : return -1;
623 :
624 1041 : pad = data_len % block_size;
625 1041 : if (pad)
626 0 : pad = block_size - pad;
627 :
628 1041 : if (*prot_len < block_size + data_len + pad + icv_len) {
629 0 : wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for Prot() data");
630 0 : return -1;
631 : }
632 1041 : pos = prot;
633 :
634 1041 : if (random_get_bytes(pos, block_size))
635 3 : return -1;
636 1038 : iv = pos;
637 1038 : wpa_hexdump(MSG_DEBUG, "EAP-EKE: IV for Prot()", iv, block_size);
638 1038 : pos += block_size;
639 :
640 1038 : e = pos;
641 1038 : os_memcpy(pos, data, data_len);
642 1038 : pos += data_len;
643 1038 : if (pad) {
644 0 : if (random_get_bytes(pos, pad))
645 0 : return -1;
646 0 : pos += pad;
647 : }
648 :
649 2076 : if (aes_128_cbc_encrypt(sess->ke, iv, e, data_len + pad) < 0 ||
650 1038 : eap_eke_mac(sess->mac, sess->ki, e, data_len + pad, pos) < 0)
651 1 : return -1;
652 1037 : pos += icv_len;
653 :
654 1037 : *prot_len = pos - prot;
655 1037 : return 0;
656 : }
657 :
658 :
659 1017 : int eap_eke_decrypt_prot(struct eap_eke_session *sess,
660 : const u8 *prot, size_t prot_len,
661 : u8 *data, size_t *data_len)
662 : {
663 : size_t block_size, icv_len;
664 : u8 icv[EAP_EKE_MAX_HASH_LEN];
665 :
666 1017 : if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
667 1017 : block_size = AES_BLOCK_SIZE;
668 : else
669 0 : return -1;
670 :
671 1017 : if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
672 904 : icv_len = SHA1_MAC_LEN;
673 113 : else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
674 113 : icv_len = SHA256_MAC_LEN;
675 : else
676 0 : return -1;
677 :
678 2034 : if (prot_len < 2 * block_size + icv_len ||
679 1017 : (prot_len - icv_len) % block_size)
680 0 : return -1;
681 :
682 1017 : if (eap_eke_mac(sess->mac, sess->ki, prot + block_size,
683 1017 : prot_len - block_size - icv_len, icv) < 0)
684 5 : return -1;
685 1012 : if (os_memcmp_const(icv, prot + prot_len - icv_len, icv_len) != 0) {
686 3 : wpa_printf(MSG_INFO, "EAP-EKE: ICV mismatch in Prot() data");
687 3 : return -1;
688 : }
689 :
690 1009 : if (*data_len < prot_len - block_size - icv_len) {
691 0 : wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for decrypted Prot() data");
692 0 : return -1;
693 : }
694 :
695 1009 : *data_len = prot_len - block_size - icv_len;
696 1009 : os_memcpy(data, prot + block_size, *data_len);
697 1009 : if (aes_128_cbc_decrypt(sess->ke, prot, data, *data_len) < 0) {
698 1 : wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt Prot() data");
699 1 : return -1;
700 : }
701 1008 : wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Decrypted Prot() data",
702 : data, *data_len);
703 :
704 1008 : return 0;
705 : }
706 :
707 :
708 1327 : int eap_eke_auth(struct eap_eke_session *sess, const char *label,
709 : const struct wpabuf *msgs, u8 *auth)
710 : {
711 1327 : wpa_printf(MSG_DEBUG, "EAP-EKE: Auth(%s)", label);
712 2654 : wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ka for Auth",
713 2654 : sess->ka, sess->auth_len);
714 1327 : wpa_hexdump_buf(MSG_MSGDUMP, "EAP-EKE: Messages for Auth", msgs);
715 2654 : return eap_eke_prf(sess->prf, sess->ka, sess->auth_len,
716 : (const u8 *) label, os_strlen(label),
717 1327 : wpabuf_head(msgs), wpabuf_len(msgs), auth);
718 : }
719 :
720 :
721 807 : int eap_eke_session_init(struct eap_eke_session *sess, u8 dhgroup, u8 encr,
722 : u8 prf, u8 mac)
723 : {
724 807 : sess->dhgroup = dhgroup;
725 807 : sess->encr = encr;
726 807 : sess->prf = prf;
727 807 : sess->mac = mac;
728 :
729 807 : sess->prf_len = eap_eke_prf_len(prf);
730 807 : sess->nonce_len = eap_eke_nonce_len(prf);
731 807 : sess->auth_len = eap_eke_auth_len(prf);
732 807 : sess->dhcomp_len = eap_eke_dhcomp_len(sess->dhgroup, sess->encr);
733 807 : sess->pnonce_len = eap_eke_pnonce_len(sess->mac);
734 807 : sess->pnonce_ps_len = eap_eke_pnonce_ps_len(sess->mac);
735 1614 : if (sess->prf_len < 0 || sess->nonce_len < 0 || sess->auth_len < 0 ||
736 2421 : sess->dhcomp_len < 0 || sess->pnonce_len < 0 ||
737 807 : sess->pnonce_ps_len < 0)
738 0 : return -1;
739 :
740 807 : return 0;
741 : }
742 :
743 :
744 1565 : void eap_eke_session_clean(struct eap_eke_session *sess)
745 : {
746 1565 : os_memset(sess->shared_secret, 0, EAP_EKE_MAX_HASH_LEN);
747 1565 : os_memset(sess->ke, 0, EAP_EKE_MAX_KE_LEN);
748 1565 : os_memset(sess->ki, 0, EAP_EKE_MAX_KI_LEN);
749 1565 : os_memset(sess->ka, 0, EAP_EKE_MAX_KA_LEN);
750 1565 : }
|