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
23static int eap_eke_dh_len(u8 group)
24{
25	switch (group) {
26	case EAP_EKE_DHGROUP_EKE_2:
27		return 128;
28	case EAP_EKE_DHGROUP_EKE_5:
29		return 192;
30	case EAP_EKE_DHGROUP_EKE_14:
31		return 256;
32	case EAP_EKE_DHGROUP_EKE_15:
33		return 384;
34	case EAP_EKE_DHGROUP_EKE_16:
35		return 512;
36	}
37
38	return -1;
39}
40
41
42static int eap_eke_dhcomp_len(u8 dhgroup, u8 encr)
43{
44	int dhlen;
45
46	dhlen = eap_eke_dh_len(dhgroup);
47	if (dhlen < 0 || encr != EAP_EKE_ENCR_AES128_CBC)
48		return -1;
49	return AES_BLOCK_SIZE + dhlen;
50}
51
52
53static const struct dh_group * eap_eke_dh_group(u8 group)
54{
55	switch (group) {
56	case EAP_EKE_DHGROUP_EKE_2:
57		return dh_groups_get(2);
58	case EAP_EKE_DHGROUP_EKE_5:
59		return dh_groups_get(5);
60	case EAP_EKE_DHGROUP_EKE_14:
61		return dh_groups_get(14);
62	case EAP_EKE_DHGROUP_EKE_15:
63		return dh_groups_get(15);
64	case EAP_EKE_DHGROUP_EKE_16:
65		return dh_groups_get(16);
66	}
67
68	return NULL;
69}
70
71
72static int eap_eke_dh_generator(u8 group)
73{
74	switch (group) {
75	case EAP_EKE_DHGROUP_EKE_2:
76		return 5;
77	case EAP_EKE_DHGROUP_EKE_5:
78		return 31;
79	case EAP_EKE_DHGROUP_EKE_14:
80		return 11;
81	case EAP_EKE_DHGROUP_EKE_15:
82		return 5;
83	case EAP_EKE_DHGROUP_EKE_16:
84		return 5;
85	}
86
87	return -1;
88}
89
90
91static int eap_eke_pnonce_len(u8 mac)
92{
93	int mac_len;
94
95	if (mac == EAP_EKE_MAC_HMAC_SHA1)
96		mac_len = SHA1_MAC_LEN;
97	else if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
98		mac_len = SHA256_MAC_LEN;
99	else
100		return -1;
101
102	return AES_BLOCK_SIZE + 16 + mac_len;
103}
104
105
106static int eap_eke_pnonce_ps_len(u8 mac)
107{
108	int mac_len;
109
110	if (mac == EAP_EKE_MAC_HMAC_SHA1)
111		mac_len = SHA1_MAC_LEN;
112	else if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
113		mac_len = SHA256_MAC_LEN;
114	else
115		return -1;
116
117	return AES_BLOCK_SIZE + 2 * 16 + mac_len;
118}
119
120
121static int eap_eke_prf_len(u8 prf)
122{
123	if (prf == EAP_EKE_PRF_HMAC_SHA1)
124		return 20;
125	if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
126		return 32;
127	return -1;
128}
129
130
131static int eap_eke_nonce_len(u8 prf)
132{
133	int prf_len;
134
135	prf_len = eap_eke_prf_len(prf);
136	if (prf_len < 0)
137		return -1;
138
139	if (prf_len > 2 * 16)
140		return (prf_len + 1) / 2;
141
142	return 16;
143}
144
145
146static int eap_eke_auth_len(u8 prf)
147{
148	switch (prf) {
149	case EAP_EKE_PRF_HMAC_SHA1:
150		return SHA1_MAC_LEN;
151	case EAP_EKE_PRF_HMAC_SHA2_256:
152		return SHA256_MAC_LEN;
153	}
154
155	return -1;
156}
157
158
159int 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	generator = eap_eke_dh_generator(group);
167	dh = eap_eke_dh_group(group);
168	if (generator < 0 || generator > 255 || !dh)
169		return -1;
170	gen = generator;
171
172	/* x = random number 2 .. p-1 */
173	if (random_get_bytes(ret_priv, dh->prime_len))
174		return -1;
175	if (os_memcmp(ret_priv, dh->prime, dh->prime_len) > 0) {
176		/* Make sure private value is smaller than prime */
177		ret_priv[0] = 0;
178	}
179	for (i = 0; i < dh->prime_len - 1; i++) {
180		if (ret_priv[i])
181			break;
182	}
183	if (i == dh->prime_len - 1 && (ret_priv[i] == 0 || ret_priv[i] == 1))
184		return -1;
185	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: DH private value",
186			ret_priv, dh->prime_len);
187
188	/* y = g ^ x (mod p) */
189	pub_len = dh->prime_len;
190	if (crypto_mod_exp(&gen, 1, ret_priv, dh->prime_len,
191			   dh->prime, dh->prime_len, ret_pub, &pub_len) < 0)
192		return -1;
193	if (pub_len < dh->prime_len) {
194		size_t pad = dh->prime_len - pub_len;
195		os_memmove(ret_pub + pad, ret_pub, pub_len);
196		os_memset(ret_pub, 0, pad);
197	}
198
199	wpa_hexdump(MSG_DEBUG, "EAP-EKE: DH public value",
200		    ret_pub, dh->prime_len);
201
202	return 0;
203}
204
205
206static 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	size_t num_elem = 1;
213
214	addr[0] = data;
215	len[0] = data_len;
216	if (data2) {
217		num_elem++;
218		addr[1] = data2;
219		len[1] = data2_len;
220	}
221
222	if (prf == EAP_EKE_PRF_HMAC_SHA1)
223		return hmac_sha1_vector(key, key_len, num_elem, addr, len, res);
224	if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
225		return hmac_sha256_vector(key, key_len, num_elem, addr, len,
226					  res);
227	return -1;
228}
229
230
231static 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	idx = 0;
241	addr[0] = hash;
242	vlen[0] = SHA1_MAC_LEN;
243	addr[1] = data;
244	vlen[1] = data_len;
245	addr[2] = &idx;
246	vlen[2] = 1;
247
248	while (len > 0) {
249		idx++;
250		if (idx == 1)
251			ret = hmac_sha1_vector(key, key_len, 2, &addr[1],
252					       &vlen[1], hash);
253		else
254			ret = hmac_sha1_vector(key, key_len, 3, addr, vlen,
255					       hash);
256		if (ret < 0)
257			return -1;
258		if (len > SHA1_MAC_LEN) {
259			os_memcpy(res, hash, SHA1_MAC_LEN);
260			res += SHA1_MAC_LEN;
261			len -= SHA1_MAC_LEN;
262		} else {
263			os_memcpy(res, hash, len);
264			len = 0;
265		}
266	}
267
268	return 0;
269}
270
271
272static 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	idx = 0;
282	addr[0] = hash;
283	vlen[0] = SHA256_MAC_LEN;
284	addr[1] = data;
285	vlen[1] = data_len;
286	addr[2] = &idx;
287	vlen[2] = 1;
288
289	while (len > 0) {
290		idx++;
291		if (idx == 1)
292			ret = hmac_sha256_vector(key, key_len, 2, &addr[1],
293						 &vlen[1], hash);
294		else
295			ret = hmac_sha256_vector(key, key_len, 3, addr, vlen,
296						 hash);
297		if (ret < 0)
298			return -1;
299		if (len > SHA256_MAC_LEN) {
300			os_memcpy(res, hash, SHA256_MAC_LEN);
301			res += SHA256_MAC_LEN;
302			len -= SHA256_MAC_LEN;
303		} else {
304			os_memcpy(res, hash, len);
305			len = 0;
306		}
307	}
308
309	return 0;
310}
311
312
313static 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	if (prf == EAP_EKE_PRF_HMAC_SHA1)
317		return eap_eke_prf_hmac_sha1(key, key_len, data, data_len, res,
318					     len);
319	if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
320		return eap_eke_prf_hmac_sha256(key, key_len, data, data_len,
321					       res, len);
322	return -1;
323}
324
325
326int 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	size_t key_len = 16; /* Only AES-128-CBC is used here */
334	u8 *id;
335
336	/* temp = prf(0+, password) */
337	os_memset(zeros, 0, sess->prf_len);
338	if (eap_eke_prf(sess->prf, zeros, sess->prf_len,
339			password, password_len, NULL, 0, temp) < 0)
340		return -1;
341	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: temp = prf(0+, password)",
342			temp, sess->prf_len);
343
344	/* key = prf+(temp, ID_S | ID_P) */
345	id = os_malloc(id_s_len + id_p_len);
346	if (id == NULL)
347		return -1;
348	os_memcpy(id, id_s, id_s_len);
349	os_memcpy(id + id_s_len, id_p, id_p_len);
350	wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: ID_S | ID_P",
351			  id, id_s_len + id_p_len);
352	if (eap_eke_prfplus(sess->prf, temp, sess->prf_len,
353			    id, id_s_len + id_p_len, key, key_len) < 0) {
354		os_free(id);
355		return -1;
356	}
357	os_free(id);
358	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: key = prf+(temp, ID_S | ID_P)",
359			key, key_len);
360
361	return 0;
362}
363
364
365int 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	dh_len = eap_eke_dh_len(sess->dhgroup);
373	if (dh_len < 0)
374		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	if (sess->encr != EAP_EKE_ENCR_AES128_CBC)
383		return -1;
384	if (random_get_bytes(iv, AES_BLOCK_SIZE))
385		return -1;
386	wpa_hexdump(MSG_DEBUG, "EAP-EKE: IV for Encr(key, y)",
387		    iv, AES_BLOCK_SIZE);
388	os_memcpy(pub, dhpub, dh_len);
389	if (aes_128_cbc_encrypt(key, iv, pub, dh_len) < 0)
390		return -1;
391	os_memcpy(ret_dhcomp, iv, AES_BLOCK_SIZE);
392	os_memcpy(ret_dhcomp + AES_BLOCK_SIZE, pub, dh_len);
393	wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent = Encr(key, y)",
394		    ret_dhcomp, AES_BLOCK_SIZE + dh_len);
395
396	return 0;
397}
398
399
400int 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	dh = eap_eke_dh_group(sess->dhgroup);
410	if (sess->encr != EAP_EKE_ENCR_AES128_CBC || !dh)
411		return -1;
412
413	/* Decrypt peer DHComponent */
414	os_memcpy(peer_pub, peer_dhcomp + AES_BLOCK_SIZE, dh->prime_len);
415	if (aes_128_cbc_decrypt(key, peer_dhcomp, peer_pub, dh->prime_len) < 0) {
416		wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt DHComponent");
417		return -1;
418	}
419	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	len = dh->prime_len;
424	if (crypto_mod_exp(peer_pub, dh->prime_len, dhpriv, dh->prime_len,
425			   dh->prime, dh->prime_len, modexp, &len) < 0)
426		return -1;
427	if (len < dh->prime_len) {
428		size_t pad = dh->prime_len - len;
429		os_memmove(modexp + pad, modexp, len);
430		os_memset(modexp, 0, pad);
431	}
432
433	os_memset(zeros, 0, sess->auth_len);
434	if (eap_eke_prf(sess->prf, zeros, sess->auth_len, modexp, dh->prime_len,
435			NULL, 0, sess->shared_secret) < 0)
436		return -1;
437	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: SharedSecret",
438			sess->shared_secret, sess->auth_len);
439
440	return 0;
441}
442
443
444int 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	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	if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
463		ke_len = 16;
464	else
465		return -1;
466
467	if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
468		ki_len = 20;
469	else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
470		ki_len = 32;
471	else
472		return -1;
473
474	label_len = os_strlen(label);
475	data_len = label_len + id_s_len + id_p_len;
476	data = os_malloc(data_len);
477	if (data == NULL)
478		return -1;
479	os_memcpy(data, label, label_len);
480	os_memcpy(data + label_len, id_s, id_s_len);
481	os_memcpy(data + label_len + id_s_len, id_p, id_p_len);
482	if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
483			    data, data_len, buf, ke_len + ki_len) < 0) {
484		os_free(data);
485		return -1;
486	}
487
488	os_memcpy(sess->ke, buf, ke_len);
489	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ke", sess->ke, ke_len);
490	os_memcpy(sess->ki, buf + ke_len, ki_len);
491	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ki", sess->ki, ki_len);
492
493	os_free(data);
494	return 0;
495}
496
497
498int 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	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	label_len = os_strlen(label);
516	data_len = label_len + id_s_len + id_p_len + 2 * sess->nonce_len;
517	data = os_malloc(data_len);
518	if (data == NULL)
519		return -1;
520	pos = data;
521	os_memcpy(pos, label, label_len);
522	pos += label_len;
523	os_memcpy(pos, id_s, id_s_len);
524	pos += id_s_len;
525	os_memcpy(pos, id_p, id_p_len);
526	pos += id_p_len;
527	os_memcpy(pos, nonce_p, sess->nonce_len);
528	pos += sess->nonce_len;
529	os_memcpy(pos, nonce_s, sess->nonce_len);
530	if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
531			    data, data_len, sess->ka, sess->prf_len) < 0) {
532		os_free(data);
533		return -1;
534	}
535	os_free(data);
536
537	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ka", sess->ka, sess->prf_len);
538
539	return 0;
540}
541
542
543int 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	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	label_len = os_strlen(label);
561	data_len = label_len + id_s_len + id_p_len + 2 * sess->nonce_len;
562	data = os_malloc(data_len);
563	if (data == NULL)
564		return -1;
565	pos = data;
566	os_memcpy(pos, label, label_len);
567	pos += label_len;
568	os_memcpy(pos, id_s, id_s_len);
569	pos += id_s_len;
570	os_memcpy(pos, id_p, id_p_len);
571	pos += id_p_len;
572	os_memcpy(pos, nonce_p, sess->nonce_len);
573	pos += sess->nonce_len;
574	os_memcpy(pos, nonce_s, sess->nonce_len);
575	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		os_free(data);
579		return -1;
580	}
581	os_free(data);
582
583	os_memcpy(msk, buf, EAP_MSK_LEN);
584	os_memcpy(emsk, buf + EAP_MSK_LEN, EAP_EMSK_LEN);
585	os_memset(buf, 0, sizeof(buf));
586
587	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: MSK", msk, EAP_MSK_LEN);
588	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: EMSK", msk, EAP_EMSK_LEN);
589
590	return 0;
591}
592
593
594static int eap_eke_mac(u8 mac, const u8 *key, const u8 *data, size_t data_len,
595		       u8 *res)
596{
597	if (mac == EAP_EKE_MAC_HMAC_SHA1)
598		return hmac_sha1(key, SHA1_MAC_LEN, data, data_len, res);
599	if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
600		return hmac_sha256(key, SHA256_MAC_LEN, data, data_len, res);
601	return -1;
602}
603
604
605int 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	if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
613		block_size = AES_BLOCK_SIZE;
614	else
615		return -1;
616
617	if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
618		icv_len = SHA1_MAC_LEN;
619	else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
620		icv_len = SHA256_MAC_LEN;
621	else
622		return -1;
623
624	pad = data_len % block_size;
625	if (pad)
626		pad = block_size - pad;
627
628	if (*prot_len < block_size + data_len + pad + icv_len) {
629		wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for Prot() data");
630		return -1;
631	}
632	pos = prot;
633
634	if (random_get_bytes(pos, block_size))
635		return -1;
636	iv = pos;
637	wpa_hexdump(MSG_DEBUG, "EAP-EKE: IV for Prot()", iv, block_size);
638	pos += block_size;
639
640	e = pos;
641	os_memcpy(pos, data, data_len);
642	pos += data_len;
643	if (pad) {
644		if (random_get_bytes(pos, pad))
645			return -1;
646		pos += pad;
647	}
648
649	if (aes_128_cbc_encrypt(sess->ke, iv, e, data_len + pad) < 0 ||
650	    eap_eke_mac(sess->mac, sess->ki, e, data_len + pad, pos) < 0)
651		return -1;
652	pos += icv_len;
653
654	*prot_len = pos - prot;
655	return 0;
656}
657
658
659int 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	if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
667		block_size = AES_BLOCK_SIZE;
668	else
669		return -1;
670
671	if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
672		icv_len = SHA1_MAC_LEN;
673	else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
674		icv_len = SHA256_MAC_LEN;
675	else
676		return -1;
677
678	if (prot_len < 2 * block_size + icv_len ||
679	    (prot_len - icv_len) % block_size)
680		return -1;
681
682	if (eap_eke_mac(sess->mac, sess->ki, prot + block_size,
683			prot_len - block_size - icv_len, icv) < 0)
684		return -1;
685	if (os_memcmp_const(icv, prot + prot_len - icv_len, icv_len) != 0) {
686		wpa_printf(MSG_INFO, "EAP-EKE: ICV mismatch in Prot() data");
687		return -1;
688	}
689
690	if (*data_len < prot_len - block_size - icv_len) {
691		wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for decrypted Prot() data");
692		return -1;
693	}
694
695	*data_len = prot_len - block_size - icv_len;
696	os_memcpy(data, prot + block_size, *data_len);
697	if (aes_128_cbc_decrypt(sess->ke, prot, data, *data_len) < 0) {
698		wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt Prot() data");
699		return -1;
700	}
701	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Decrypted Prot() data",
702			data, *data_len);
703
704	return 0;
705}
706
707
708int eap_eke_auth(struct eap_eke_session *sess, const char *label,
709		 const struct wpabuf *msgs, u8 *auth)
710{
711	wpa_printf(MSG_DEBUG, "EAP-EKE: Auth(%s)", label);
712	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ka for Auth",
713			sess->ka, sess->auth_len);
714	wpa_hexdump_buf(MSG_MSGDUMP, "EAP-EKE: Messages for Auth", msgs);
715	return eap_eke_prf(sess->prf, sess->ka, sess->auth_len,
716			   (const u8 *) label, os_strlen(label),
717			   wpabuf_head(msgs), wpabuf_len(msgs), auth);
718}
719
720
721int eap_eke_session_init(struct eap_eke_session *sess, u8 dhgroup, u8 encr,
722			 u8 prf, u8 mac)
723{
724	sess->dhgroup = dhgroup;
725	sess->encr = encr;
726	sess->prf = prf;
727	sess->mac = mac;
728
729	sess->prf_len = eap_eke_prf_len(prf);
730	sess->nonce_len = eap_eke_nonce_len(prf);
731	sess->auth_len = eap_eke_auth_len(prf);
732	sess->dhcomp_len = eap_eke_dhcomp_len(sess->dhgroup, sess->encr);
733	sess->pnonce_len = eap_eke_pnonce_len(sess->mac);
734	sess->pnonce_ps_len = eap_eke_pnonce_ps_len(sess->mac);
735	if (sess->prf_len < 0 || sess->nonce_len < 0 || sess->auth_len < 0 ||
736	    sess->dhcomp_len < 0 || sess->pnonce_len < 0 ||
737	    sess->pnonce_ps_len < 0)
738		return -1;
739
740	return 0;
741}
742
743
744void eap_eke_session_clean(struct eap_eke_session *sess)
745{
746	os_memset(sess->shared_secret, 0, EAP_EKE_MAX_HASH_LEN);
747	os_memset(sess->ke, 0, EAP_EKE_MAX_KE_LEN);
748	os_memset(sess->ki, 0, EAP_EKE_MAX_KI_LEN);
749	os_memset(sess->ka, 0, EAP_EKE_MAX_KA_LEN);
750}
751