xref: /freebsd/contrib/wpa/src/eap_common/eap_eke_common.c (revision 7648bc9fee8dec6cb3c4941e0165a930fbe8dcb0)
15b9c547cSRui Paulo /*
25b9c547cSRui Paulo  * EAP server/peer: EAP-EKE shared routines
35b9c547cSRui Paulo  * Copyright (c) 2011-2013, Jouni Malinen <j@w1.fi>
45b9c547cSRui Paulo  *
55b9c547cSRui Paulo  * This software may be distributed under the terms of the BSD license.
65b9c547cSRui Paulo  * See README for more details.
75b9c547cSRui Paulo  */
85b9c547cSRui Paulo 
95b9c547cSRui Paulo #include "includes.h"
105b9c547cSRui Paulo 
115b9c547cSRui Paulo #include "common.h"
125b9c547cSRui Paulo #include "crypto/aes.h"
135b9c547cSRui Paulo #include "crypto/aes_wrap.h"
145b9c547cSRui Paulo #include "crypto/crypto.h"
155b9c547cSRui Paulo #include "crypto/dh_groups.h"
165b9c547cSRui Paulo #include "crypto/random.h"
175b9c547cSRui Paulo #include "crypto/sha1.h"
185b9c547cSRui Paulo #include "crypto/sha256.h"
195b9c547cSRui Paulo #include "eap_common/eap_defs.h"
205b9c547cSRui Paulo #include "eap_eke_common.h"
215b9c547cSRui Paulo 
225b9c547cSRui Paulo 
eap_eke_dh_len(u8 group)235b9c547cSRui Paulo static int eap_eke_dh_len(u8 group)
245b9c547cSRui Paulo {
255b9c547cSRui Paulo 	switch (group) {
265b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_2:
275b9c547cSRui Paulo 		return 128;
285b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_5:
295b9c547cSRui Paulo 		return 192;
305b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_14:
315b9c547cSRui Paulo 		return 256;
325b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_15:
335b9c547cSRui Paulo 		return 384;
345b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_16:
355b9c547cSRui Paulo 		return 512;
365b9c547cSRui Paulo 	}
375b9c547cSRui Paulo 
385b9c547cSRui Paulo 	return -1;
395b9c547cSRui Paulo }
405b9c547cSRui Paulo 
415b9c547cSRui Paulo 
eap_eke_dhcomp_len(u8 dhgroup,u8 encr)425b9c547cSRui Paulo static int eap_eke_dhcomp_len(u8 dhgroup, u8 encr)
435b9c547cSRui Paulo {
445b9c547cSRui Paulo 	int dhlen;
455b9c547cSRui Paulo 
465b9c547cSRui Paulo 	dhlen = eap_eke_dh_len(dhgroup);
47780fb4a2SCy Schubert 	if (dhlen < 0 || encr != EAP_EKE_ENCR_AES128_CBC)
485b9c547cSRui Paulo 		return -1;
495b9c547cSRui Paulo 	return AES_BLOCK_SIZE + dhlen;
505b9c547cSRui Paulo }
515b9c547cSRui Paulo 
525b9c547cSRui Paulo 
eap_eke_dh_group(u8 group)535b9c547cSRui Paulo static const struct dh_group * eap_eke_dh_group(u8 group)
545b9c547cSRui Paulo {
555b9c547cSRui Paulo 	switch (group) {
565b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_2:
575b9c547cSRui Paulo 		return dh_groups_get(2);
585b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_5:
595b9c547cSRui Paulo 		return dh_groups_get(5);
605b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_14:
615b9c547cSRui Paulo 		return dh_groups_get(14);
625b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_15:
635b9c547cSRui Paulo 		return dh_groups_get(15);
645b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_16:
655b9c547cSRui Paulo 		return dh_groups_get(16);
665b9c547cSRui Paulo 	}
675b9c547cSRui Paulo 
685b9c547cSRui Paulo 	return NULL;
695b9c547cSRui Paulo }
705b9c547cSRui Paulo 
715b9c547cSRui Paulo 
eap_eke_dh_generator(u8 group)725b9c547cSRui Paulo static int eap_eke_dh_generator(u8 group)
735b9c547cSRui Paulo {
745b9c547cSRui Paulo 	switch (group) {
755b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_2:
765b9c547cSRui Paulo 		return 5;
775b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_5:
785b9c547cSRui Paulo 		return 31;
795b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_14:
805b9c547cSRui Paulo 		return 11;
815b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_15:
825b9c547cSRui Paulo 		return 5;
835b9c547cSRui Paulo 	case EAP_EKE_DHGROUP_EKE_16:
845b9c547cSRui Paulo 		return 5;
855b9c547cSRui Paulo 	}
865b9c547cSRui Paulo 
875b9c547cSRui Paulo 	return -1;
885b9c547cSRui Paulo }
895b9c547cSRui Paulo 
905b9c547cSRui Paulo 
eap_eke_pnonce_len(u8 mac)915b9c547cSRui Paulo static int eap_eke_pnonce_len(u8 mac)
925b9c547cSRui Paulo {
935b9c547cSRui Paulo 	int mac_len;
945b9c547cSRui Paulo 
955b9c547cSRui Paulo 	if (mac == EAP_EKE_MAC_HMAC_SHA1)
965b9c547cSRui Paulo 		mac_len = SHA1_MAC_LEN;
975b9c547cSRui Paulo 	else if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
985b9c547cSRui Paulo 		mac_len = SHA256_MAC_LEN;
995b9c547cSRui Paulo 	else
1005b9c547cSRui Paulo 		return -1;
1015b9c547cSRui Paulo 
1025b9c547cSRui Paulo 	return AES_BLOCK_SIZE + 16 + mac_len;
1035b9c547cSRui Paulo }
1045b9c547cSRui Paulo 
1055b9c547cSRui Paulo 
eap_eke_pnonce_ps_len(u8 mac)1065b9c547cSRui Paulo static int eap_eke_pnonce_ps_len(u8 mac)
1075b9c547cSRui Paulo {
1085b9c547cSRui Paulo 	int mac_len;
1095b9c547cSRui Paulo 
1105b9c547cSRui Paulo 	if (mac == EAP_EKE_MAC_HMAC_SHA1)
1115b9c547cSRui Paulo 		mac_len = SHA1_MAC_LEN;
1125b9c547cSRui Paulo 	else if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
1135b9c547cSRui Paulo 		mac_len = SHA256_MAC_LEN;
1145b9c547cSRui Paulo 	else
1155b9c547cSRui Paulo 		return -1;
1165b9c547cSRui Paulo 
1175b9c547cSRui Paulo 	return AES_BLOCK_SIZE + 2 * 16 + mac_len;
1185b9c547cSRui Paulo }
1195b9c547cSRui Paulo 
1205b9c547cSRui Paulo 
eap_eke_prf_len(u8 prf)1215b9c547cSRui Paulo static int eap_eke_prf_len(u8 prf)
1225b9c547cSRui Paulo {
1235b9c547cSRui Paulo 	if (prf == EAP_EKE_PRF_HMAC_SHA1)
1245b9c547cSRui Paulo 		return 20;
1255b9c547cSRui Paulo 	if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
1265b9c547cSRui Paulo 		return 32;
1275b9c547cSRui Paulo 	return -1;
1285b9c547cSRui Paulo }
1295b9c547cSRui Paulo 
1305b9c547cSRui Paulo 
eap_eke_nonce_len(u8 prf)1315b9c547cSRui Paulo static int eap_eke_nonce_len(u8 prf)
1325b9c547cSRui Paulo {
1335b9c547cSRui Paulo 	int prf_len;
1345b9c547cSRui Paulo 
1355b9c547cSRui Paulo 	prf_len = eap_eke_prf_len(prf);
1365b9c547cSRui Paulo 	if (prf_len < 0)
1375b9c547cSRui Paulo 		return -1;
1385b9c547cSRui Paulo 
1395b9c547cSRui Paulo 	if (prf_len > 2 * 16)
1405b9c547cSRui Paulo 		return (prf_len + 1) / 2;
1415b9c547cSRui Paulo 
1425b9c547cSRui Paulo 	return 16;
1435b9c547cSRui Paulo }
1445b9c547cSRui Paulo 
1455b9c547cSRui Paulo 
eap_eke_auth_len(u8 prf)1465b9c547cSRui Paulo static int eap_eke_auth_len(u8 prf)
1475b9c547cSRui Paulo {
1485b9c547cSRui Paulo 	switch (prf) {
1495b9c547cSRui Paulo 	case EAP_EKE_PRF_HMAC_SHA1:
1505b9c547cSRui Paulo 		return SHA1_MAC_LEN;
1515b9c547cSRui Paulo 	case EAP_EKE_PRF_HMAC_SHA2_256:
1525b9c547cSRui Paulo 		return SHA256_MAC_LEN;
1535b9c547cSRui Paulo 	}
1545b9c547cSRui Paulo 
1555b9c547cSRui Paulo 	return -1;
1565b9c547cSRui Paulo }
1575b9c547cSRui Paulo 
1585b9c547cSRui Paulo 
eap_eke_dh_init(u8 group,u8 * ret_priv,u8 * ret_pub)1595b9c547cSRui Paulo int eap_eke_dh_init(u8 group, u8 *ret_priv, u8 *ret_pub)
1605b9c547cSRui Paulo {
1615b9c547cSRui Paulo 	int generator;
1625b9c547cSRui Paulo 	u8 gen;
1635b9c547cSRui Paulo 	const struct dh_group *dh;
1645b9c547cSRui Paulo 
1655b9c547cSRui Paulo 	generator = eap_eke_dh_generator(group);
166780fb4a2SCy Schubert 	dh = eap_eke_dh_group(group);
167780fb4a2SCy Schubert 	if (generator < 0 || generator > 255 || !dh)
1685b9c547cSRui Paulo 		return -1;
1695b9c547cSRui Paulo 	gen = generator;
1705b9c547cSRui Paulo 
17185732ac8SCy Schubert 	if (crypto_dh_init(gen, dh->prime, dh->prime_len, ret_priv,
17285732ac8SCy Schubert 			   ret_pub) < 0)
1735b9c547cSRui Paulo 		return -1;
1745b9c547cSRui Paulo 	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: DH private value",
1755b9c547cSRui Paulo 			ret_priv, dh->prime_len);
1765b9c547cSRui Paulo 	wpa_hexdump(MSG_DEBUG, "EAP-EKE: DH public value",
1775b9c547cSRui Paulo 		    ret_pub, dh->prime_len);
1785b9c547cSRui Paulo 
1795b9c547cSRui Paulo 	return 0;
1805b9c547cSRui Paulo }
1815b9c547cSRui Paulo 
1825b9c547cSRui Paulo 
eap_eke_prf(u8 prf,const u8 * key,size_t key_len,const u8 * data,size_t data_len,const u8 * data2,size_t data2_len,u8 * res)1835b9c547cSRui Paulo static int eap_eke_prf(u8 prf, const u8 *key, size_t key_len, const u8 *data,
1845b9c547cSRui Paulo 		       size_t data_len, const u8 *data2, size_t data2_len,
1855b9c547cSRui Paulo 		       u8 *res)
1865b9c547cSRui Paulo {
1875b9c547cSRui Paulo 	const u8 *addr[2];
1885b9c547cSRui Paulo 	size_t len[2];
1895b9c547cSRui Paulo 	size_t num_elem = 1;
1905b9c547cSRui Paulo 
1915b9c547cSRui Paulo 	addr[0] = data;
1925b9c547cSRui Paulo 	len[0] = data_len;
1935b9c547cSRui Paulo 	if (data2) {
1945b9c547cSRui Paulo 		num_elem++;
1955b9c547cSRui Paulo 		addr[1] = data2;
1965b9c547cSRui Paulo 		len[1] = data2_len;
1975b9c547cSRui Paulo 	}
1985b9c547cSRui Paulo 
1995b9c547cSRui Paulo 	if (prf == EAP_EKE_PRF_HMAC_SHA1)
2005b9c547cSRui Paulo 		return hmac_sha1_vector(key, key_len, num_elem, addr, len, res);
2015b9c547cSRui Paulo 	if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
2025b9c547cSRui Paulo 		return hmac_sha256_vector(key, key_len, num_elem, addr, len,
2035b9c547cSRui Paulo 					  res);
2045b9c547cSRui Paulo 	return -1;
2055b9c547cSRui Paulo }
2065b9c547cSRui Paulo 
2075b9c547cSRui Paulo 
eap_eke_prf_hmac_sha1(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * res,size_t len)2085b9c547cSRui Paulo static int eap_eke_prf_hmac_sha1(const u8 *key, size_t key_len, const u8 *data,
2095b9c547cSRui Paulo 				 size_t data_len, u8 *res, size_t len)
2105b9c547cSRui Paulo {
2115b9c547cSRui Paulo 	u8 hash[SHA1_MAC_LEN];
2125b9c547cSRui Paulo 	u8 idx;
2135b9c547cSRui Paulo 	const u8 *addr[3];
2145b9c547cSRui Paulo 	size_t vlen[3];
2155b9c547cSRui Paulo 	int ret;
2165b9c547cSRui Paulo 
2175b9c547cSRui Paulo 	idx = 0;
2185b9c547cSRui Paulo 	addr[0] = hash;
2195b9c547cSRui Paulo 	vlen[0] = SHA1_MAC_LEN;
2205b9c547cSRui Paulo 	addr[1] = data;
2215b9c547cSRui Paulo 	vlen[1] = data_len;
2225b9c547cSRui Paulo 	addr[2] = &idx;
2235b9c547cSRui Paulo 	vlen[2] = 1;
2245b9c547cSRui Paulo 
2255b9c547cSRui Paulo 	while (len > 0) {
2265b9c547cSRui Paulo 		idx++;
2275b9c547cSRui Paulo 		if (idx == 1)
2285b9c547cSRui Paulo 			ret = hmac_sha1_vector(key, key_len, 2, &addr[1],
2295b9c547cSRui Paulo 					       &vlen[1], hash);
2305b9c547cSRui Paulo 		else
2315b9c547cSRui Paulo 			ret = hmac_sha1_vector(key, key_len, 3, addr, vlen,
2325b9c547cSRui Paulo 					       hash);
2335b9c547cSRui Paulo 		if (ret < 0)
2345b9c547cSRui Paulo 			return -1;
2355b9c547cSRui Paulo 		if (len > SHA1_MAC_LEN) {
2365b9c547cSRui Paulo 			os_memcpy(res, hash, SHA1_MAC_LEN);
2375b9c547cSRui Paulo 			res += SHA1_MAC_LEN;
2385b9c547cSRui Paulo 			len -= SHA1_MAC_LEN;
2395b9c547cSRui Paulo 		} else {
2405b9c547cSRui Paulo 			os_memcpy(res, hash, len);
2415b9c547cSRui Paulo 			len = 0;
2425b9c547cSRui Paulo 		}
2435b9c547cSRui Paulo 	}
2445b9c547cSRui Paulo 
2455b9c547cSRui Paulo 	return 0;
2465b9c547cSRui Paulo }
2475b9c547cSRui Paulo 
2485b9c547cSRui Paulo 
eap_eke_prf_hmac_sha256(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * res,size_t len)2495b9c547cSRui Paulo static int eap_eke_prf_hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
2505b9c547cSRui Paulo 				   size_t data_len, u8 *res, size_t len)
2515b9c547cSRui Paulo {
2525b9c547cSRui Paulo 	u8 hash[SHA256_MAC_LEN];
2535b9c547cSRui Paulo 	u8 idx;
2545b9c547cSRui Paulo 	const u8 *addr[3];
2555b9c547cSRui Paulo 	size_t vlen[3];
2565b9c547cSRui Paulo 	int ret;
2575b9c547cSRui Paulo 
2585b9c547cSRui Paulo 	idx = 0;
2595b9c547cSRui Paulo 	addr[0] = hash;
2605b9c547cSRui Paulo 	vlen[0] = SHA256_MAC_LEN;
2615b9c547cSRui Paulo 	addr[1] = data;
2625b9c547cSRui Paulo 	vlen[1] = data_len;
2635b9c547cSRui Paulo 	addr[2] = &idx;
2645b9c547cSRui Paulo 	vlen[2] = 1;
2655b9c547cSRui Paulo 
2665b9c547cSRui Paulo 	while (len > 0) {
2675b9c547cSRui Paulo 		idx++;
2685b9c547cSRui Paulo 		if (idx == 1)
2695b9c547cSRui Paulo 			ret = hmac_sha256_vector(key, key_len, 2, &addr[1],
2705b9c547cSRui Paulo 						 &vlen[1], hash);
2715b9c547cSRui Paulo 		else
2725b9c547cSRui Paulo 			ret = hmac_sha256_vector(key, key_len, 3, addr, vlen,
2735b9c547cSRui Paulo 						 hash);
2745b9c547cSRui Paulo 		if (ret < 0)
2755b9c547cSRui Paulo 			return -1;
2765b9c547cSRui Paulo 		if (len > SHA256_MAC_LEN) {
2775b9c547cSRui Paulo 			os_memcpy(res, hash, SHA256_MAC_LEN);
2785b9c547cSRui Paulo 			res += SHA256_MAC_LEN;
2795b9c547cSRui Paulo 			len -= SHA256_MAC_LEN;
2805b9c547cSRui Paulo 		} else {
2815b9c547cSRui Paulo 			os_memcpy(res, hash, len);
2825b9c547cSRui Paulo 			len = 0;
2835b9c547cSRui Paulo 		}
2845b9c547cSRui Paulo 	}
2855b9c547cSRui Paulo 
2865b9c547cSRui Paulo 	return 0;
2875b9c547cSRui Paulo }
2885b9c547cSRui Paulo 
2895b9c547cSRui Paulo 
eap_eke_prfplus(u8 prf,const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * res,size_t len)2905b9c547cSRui Paulo static int eap_eke_prfplus(u8 prf, const u8 *key, size_t key_len,
2915b9c547cSRui Paulo 			   const u8 *data, size_t data_len, u8 *res, size_t len)
2925b9c547cSRui Paulo {
2935b9c547cSRui Paulo 	if (prf == EAP_EKE_PRF_HMAC_SHA1)
2945b9c547cSRui Paulo 		return eap_eke_prf_hmac_sha1(key, key_len, data, data_len, res,
2955b9c547cSRui Paulo 					     len);
2965b9c547cSRui Paulo 	if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
2975b9c547cSRui Paulo 		return eap_eke_prf_hmac_sha256(key, key_len, data, data_len,
2985b9c547cSRui Paulo 					       res, len);
2995b9c547cSRui Paulo 	return -1;
3005b9c547cSRui Paulo }
3015b9c547cSRui Paulo 
3025b9c547cSRui Paulo 
eap_eke_derive_key(struct eap_eke_session * sess,const u8 * password,size_t password_len,const u8 * id_s,size_t id_s_len,const u8 * id_p,size_t id_p_len,u8 * key)3035b9c547cSRui Paulo int eap_eke_derive_key(struct eap_eke_session *sess,
3045b9c547cSRui Paulo 		       const u8 *password, size_t password_len,
3055b9c547cSRui Paulo 		       const u8 *id_s, size_t id_s_len, const u8 *id_p,
3065b9c547cSRui Paulo 		       size_t id_p_len, u8 *key)
3075b9c547cSRui Paulo {
3085b9c547cSRui Paulo 	u8 zeros[EAP_EKE_MAX_HASH_LEN];
3095b9c547cSRui Paulo 	u8 temp[EAP_EKE_MAX_HASH_LEN];
3105b9c547cSRui Paulo 	size_t key_len = 16; /* Only AES-128-CBC is used here */
3115b9c547cSRui Paulo 	u8 *id;
3125b9c547cSRui Paulo 
3135b9c547cSRui Paulo 	/* temp = prf(0+, password) */
3145b9c547cSRui Paulo 	os_memset(zeros, 0, sess->prf_len);
3155b9c547cSRui Paulo 	if (eap_eke_prf(sess->prf, zeros, sess->prf_len,
3165b9c547cSRui Paulo 			password, password_len, NULL, 0, temp) < 0)
3175b9c547cSRui Paulo 		return -1;
3185b9c547cSRui Paulo 	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: temp = prf(0+, password)",
3195b9c547cSRui Paulo 			temp, sess->prf_len);
3205b9c547cSRui Paulo 
3215b9c547cSRui Paulo 	/* key = prf+(temp, ID_S | ID_P) */
3225b9c547cSRui Paulo 	id = os_malloc(id_s_len + id_p_len);
3235b9c547cSRui Paulo 	if (id == NULL)
3245b9c547cSRui Paulo 		return -1;
3255b9c547cSRui Paulo 	os_memcpy(id, id_s, id_s_len);
3265b9c547cSRui Paulo 	os_memcpy(id + id_s_len, id_p, id_p_len);
3275b9c547cSRui Paulo 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: ID_S | ID_P",
3285b9c547cSRui Paulo 			  id, id_s_len + id_p_len);
3295b9c547cSRui Paulo 	if (eap_eke_prfplus(sess->prf, temp, sess->prf_len,
3305b9c547cSRui Paulo 			    id, id_s_len + id_p_len, key, key_len) < 0) {
3315b9c547cSRui Paulo 		os_free(id);
3325b9c547cSRui Paulo 		return -1;
3335b9c547cSRui Paulo 	}
3345b9c547cSRui Paulo 	os_free(id);
3355b9c547cSRui Paulo 	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: key = prf+(temp, ID_S | ID_P)",
3365b9c547cSRui Paulo 			key, key_len);
3375b9c547cSRui Paulo 
3385b9c547cSRui Paulo 	return 0;
3395b9c547cSRui Paulo }
3405b9c547cSRui Paulo 
3415b9c547cSRui Paulo 
eap_eke_dhcomp(struct eap_eke_session * sess,const u8 * key,const u8 * dhpub,u8 * ret_dhcomp)3425b9c547cSRui Paulo int eap_eke_dhcomp(struct eap_eke_session *sess, const u8 *key, const u8 *dhpub,
3435b9c547cSRui Paulo 		   u8 *ret_dhcomp)
3445b9c547cSRui Paulo {
3455b9c547cSRui Paulo 	u8 pub[EAP_EKE_MAX_DH_LEN];
3465b9c547cSRui Paulo 	int dh_len;
3475b9c547cSRui Paulo 	u8 iv[AES_BLOCK_SIZE];
3485b9c547cSRui Paulo 
3495b9c547cSRui Paulo 	dh_len = eap_eke_dh_len(sess->dhgroup);
3505b9c547cSRui Paulo 	if (dh_len < 0)
3515b9c547cSRui Paulo 		return -1;
3525b9c547cSRui Paulo 
3535b9c547cSRui Paulo 	/*
3545b9c547cSRui Paulo 	 * DHComponent = Encr(key, y)
3555b9c547cSRui Paulo 	 *
3565b9c547cSRui Paulo 	 * All defined DH groups use primes that have length devisible by 16, so
3575b9c547cSRui Paulo 	 * no need to do extra padding for y (= pub).
3585b9c547cSRui Paulo 	 */
3595b9c547cSRui Paulo 	if (sess->encr != EAP_EKE_ENCR_AES128_CBC)
3605b9c547cSRui Paulo 		return -1;
3615b9c547cSRui Paulo 	if (random_get_bytes(iv, AES_BLOCK_SIZE))
3625b9c547cSRui Paulo 		return -1;
3635b9c547cSRui Paulo 	wpa_hexdump(MSG_DEBUG, "EAP-EKE: IV for Encr(key, y)",
3645b9c547cSRui Paulo 		    iv, AES_BLOCK_SIZE);
3655b9c547cSRui Paulo 	os_memcpy(pub, dhpub, dh_len);
3665b9c547cSRui Paulo 	if (aes_128_cbc_encrypt(key, iv, pub, dh_len) < 0)
3675b9c547cSRui Paulo 		return -1;
3685b9c547cSRui Paulo 	os_memcpy(ret_dhcomp, iv, AES_BLOCK_SIZE);
3695b9c547cSRui Paulo 	os_memcpy(ret_dhcomp + AES_BLOCK_SIZE, pub, dh_len);
3705b9c547cSRui Paulo 	wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent = Encr(key, y)",
3715b9c547cSRui Paulo 		    ret_dhcomp, AES_BLOCK_SIZE + dh_len);
3725b9c547cSRui Paulo 
3735b9c547cSRui Paulo 	return 0;
3745b9c547cSRui Paulo }
3755b9c547cSRui Paulo 
3765b9c547cSRui Paulo 
eap_eke_shared_secret(struct eap_eke_session * sess,const u8 * key,const u8 * dhpriv,const u8 * peer_dhcomp)3775b9c547cSRui Paulo int eap_eke_shared_secret(struct eap_eke_session *sess, const u8 *key,
3785b9c547cSRui Paulo 			  const u8 *dhpriv, const u8 *peer_dhcomp)
3795b9c547cSRui Paulo {
3805b9c547cSRui Paulo 	u8 zeros[EAP_EKE_MAX_HASH_LEN];
3815b9c547cSRui Paulo 	u8 peer_pub[EAP_EKE_MAX_DH_LEN];
3825b9c547cSRui Paulo 	u8 modexp[EAP_EKE_MAX_DH_LEN];
3835b9c547cSRui Paulo 	size_t len;
3845b9c547cSRui Paulo 	const struct dh_group *dh;
3855b9c547cSRui Paulo 
3865b9c547cSRui Paulo 	dh = eap_eke_dh_group(sess->dhgroup);
387780fb4a2SCy Schubert 	if (sess->encr != EAP_EKE_ENCR_AES128_CBC || !dh)
3885b9c547cSRui Paulo 		return -1;
3895b9c547cSRui Paulo 
3905b9c547cSRui Paulo 	/* Decrypt peer DHComponent */
3915b9c547cSRui Paulo 	os_memcpy(peer_pub, peer_dhcomp + AES_BLOCK_SIZE, dh->prime_len);
3925b9c547cSRui Paulo 	if (aes_128_cbc_decrypt(key, peer_dhcomp, peer_pub, dh->prime_len) < 0) {
3935b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt DHComponent");
3945b9c547cSRui Paulo 		return -1;
3955b9c547cSRui Paulo 	}
3965b9c547cSRui Paulo 	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Decrypted peer DH pubkey",
3975b9c547cSRui Paulo 			peer_pub, dh->prime_len);
3985b9c547cSRui Paulo 
3995b9c547cSRui Paulo 	/* SharedSecret = prf(0+, g ^ (x_s * x_p) (mod p)) */
4005b9c547cSRui Paulo 	len = dh->prime_len;
40185732ac8SCy Schubert 	if (crypto_dh_derive_secret(*dh->generator, dh->prime, dh->prime_len,
402*4bc52338SCy Schubert 				    NULL, 0, dhpriv, dh->prime_len, peer_pub,
40385732ac8SCy Schubert 				    dh->prime_len, modexp, &len) < 0)
4045b9c547cSRui Paulo 		return -1;
4055b9c547cSRui Paulo 	if (len < dh->prime_len) {
4065b9c547cSRui Paulo 		size_t pad = dh->prime_len - len;
4075b9c547cSRui Paulo 		os_memmove(modexp + pad, modexp, len);
4085b9c547cSRui Paulo 		os_memset(modexp, 0, pad);
4095b9c547cSRui Paulo 	}
4105b9c547cSRui Paulo 
4115b9c547cSRui Paulo 	os_memset(zeros, 0, sess->auth_len);
4125b9c547cSRui Paulo 	if (eap_eke_prf(sess->prf, zeros, sess->auth_len, modexp, dh->prime_len,
4135b9c547cSRui Paulo 			NULL, 0, sess->shared_secret) < 0)
4145b9c547cSRui Paulo 		return -1;
4155b9c547cSRui Paulo 	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: SharedSecret",
4165b9c547cSRui Paulo 			sess->shared_secret, sess->auth_len);
4175b9c547cSRui Paulo 
4185b9c547cSRui Paulo 	return 0;
4195b9c547cSRui Paulo }
4205b9c547cSRui Paulo 
4215b9c547cSRui Paulo 
eap_eke_derive_ke_ki(struct eap_eke_session * sess,const u8 * id_s,size_t id_s_len,const u8 * id_p,size_t id_p_len)4225b9c547cSRui Paulo int eap_eke_derive_ke_ki(struct eap_eke_session *sess,
4235b9c547cSRui Paulo 			 const u8 *id_s, size_t id_s_len,
4245b9c547cSRui Paulo 			 const u8 *id_p, size_t id_p_len)
4255b9c547cSRui Paulo {
4265b9c547cSRui Paulo 	u8 buf[EAP_EKE_MAX_KE_LEN + EAP_EKE_MAX_KI_LEN];
4275b9c547cSRui Paulo 	size_t ke_len, ki_len;
4285b9c547cSRui Paulo 	u8 *data;
4295b9c547cSRui Paulo 	size_t data_len;
4305b9c547cSRui Paulo 	const char *label = "EAP-EKE Keys";
4315b9c547cSRui Paulo 	size_t label_len;
4325b9c547cSRui Paulo 
4335b9c547cSRui Paulo 	/*
4345b9c547cSRui Paulo 	 * Ke | Ki = prf+(SharedSecret, "EAP-EKE Keys" | ID_S | ID_P)
4355b9c547cSRui Paulo 	 * Ke = encryption key
4365b9c547cSRui Paulo 	 * Ki = integrity protection key
4375b9c547cSRui Paulo 	 * Length of each key depends on the selected algorithms.
4385b9c547cSRui Paulo 	 */
4395b9c547cSRui Paulo 
4405b9c547cSRui Paulo 	if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
4415b9c547cSRui Paulo 		ke_len = 16;
4425b9c547cSRui Paulo 	else
4435b9c547cSRui Paulo 		return -1;
4445b9c547cSRui Paulo 
4455b9c547cSRui Paulo 	if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
4465b9c547cSRui Paulo 		ki_len = 20;
4475b9c547cSRui Paulo 	else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
4485b9c547cSRui Paulo 		ki_len = 32;
4495b9c547cSRui Paulo 	else
4505b9c547cSRui Paulo 		return -1;
4515b9c547cSRui Paulo 
4525b9c547cSRui Paulo 	label_len = os_strlen(label);
4535b9c547cSRui Paulo 	data_len = label_len + id_s_len + id_p_len;
4545b9c547cSRui Paulo 	data = os_malloc(data_len);
4555b9c547cSRui Paulo 	if (data == NULL)
4565b9c547cSRui Paulo 		return -1;
4575b9c547cSRui Paulo 	os_memcpy(data, label, label_len);
4585b9c547cSRui Paulo 	os_memcpy(data + label_len, id_s, id_s_len);
4595b9c547cSRui Paulo 	os_memcpy(data + label_len + id_s_len, id_p, id_p_len);
4605b9c547cSRui Paulo 	if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
4615b9c547cSRui Paulo 			    data, data_len, buf, ke_len + ki_len) < 0) {
4625b9c547cSRui Paulo 		os_free(data);
4635b9c547cSRui Paulo 		return -1;
4645b9c547cSRui Paulo 	}
4655b9c547cSRui Paulo 
4665b9c547cSRui Paulo 	os_memcpy(sess->ke, buf, ke_len);
4675b9c547cSRui Paulo 	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ke", sess->ke, ke_len);
4685b9c547cSRui Paulo 	os_memcpy(sess->ki, buf + ke_len, ki_len);
4695b9c547cSRui Paulo 	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ki", sess->ki, ki_len);
4705b9c547cSRui Paulo 
4715b9c547cSRui Paulo 	os_free(data);
4725b9c547cSRui Paulo 	return 0;
4735b9c547cSRui Paulo }
4745b9c547cSRui Paulo 
4755b9c547cSRui Paulo 
eap_eke_derive_ka(struct eap_eke_session * sess,const u8 * id_s,size_t id_s_len,const u8 * id_p,size_t id_p_len,const u8 * nonce_p,const u8 * nonce_s)4765b9c547cSRui Paulo int eap_eke_derive_ka(struct eap_eke_session *sess,
4775b9c547cSRui Paulo 		      const u8 *id_s, size_t id_s_len,
4785b9c547cSRui Paulo 		      const u8 *id_p, size_t id_p_len,
4795b9c547cSRui Paulo 		      const u8 *nonce_p, const u8 *nonce_s)
4805b9c547cSRui Paulo {
4815b9c547cSRui Paulo 	u8 *data, *pos;
4825b9c547cSRui Paulo 	size_t data_len;
4835b9c547cSRui Paulo 	const char *label = "EAP-EKE Ka";
4845b9c547cSRui Paulo 	size_t label_len;
4855b9c547cSRui Paulo 
4865b9c547cSRui Paulo 	/*
4875b9c547cSRui Paulo 	 * Ka = prf+(SharedSecret, "EAP-EKE Ka" | ID_S | ID_P | Nonce_P |
4885b9c547cSRui Paulo 	 *	     Nonce_S)
4895b9c547cSRui Paulo 	 * Ka = authentication key
4905b9c547cSRui Paulo 	 * Length of the key depends on the selected algorithms.
4915b9c547cSRui Paulo 	 */
4925b9c547cSRui Paulo 
4935b9c547cSRui Paulo 	label_len = os_strlen(label);
4945b9c547cSRui Paulo 	data_len = label_len + id_s_len + id_p_len + 2 * sess->nonce_len;
4955b9c547cSRui Paulo 	data = os_malloc(data_len);
4965b9c547cSRui Paulo 	if (data == NULL)
4975b9c547cSRui Paulo 		return -1;
4985b9c547cSRui Paulo 	pos = data;
4995b9c547cSRui Paulo 	os_memcpy(pos, label, label_len);
5005b9c547cSRui Paulo 	pos += label_len;
5015b9c547cSRui Paulo 	os_memcpy(pos, id_s, id_s_len);
5025b9c547cSRui Paulo 	pos += id_s_len;
5035b9c547cSRui Paulo 	os_memcpy(pos, id_p, id_p_len);
5045b9c547cSRui Paulo 	pos += id_p_len;
5055b9c547cSRui Paulo 	os_memcpy(pos, nonce_p, sess->nonce_len);
5065b9c547cSRui Paulo 	pos += sess->nonce_len;
5075b9c547cSRui Paulo 	os_memcpy(pos, nonce_s, sess->nonce_len);
5085b9c547cSRui Paulo 	if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
5095b9c547cSRui Paulo 			    data, data_len, sess->ka, sess->prf_len) < 0) {
5105b9c547cSRui Paulo 		os_free(data);
5115b9c547cSRui Paulo 		return -1;
5125b9c547cSRui Paulo 	}
5135b9c547cSRui Paulo 	os_free(data);
5145b9c547cSRui Paulo 
5155b9c547cSRui Paulo 	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ka", sess->ka, sess->prf_len);
5165b9c547cSRui Paulo 
5175b9c547cSRui Paulo 	return 0;
5185b9c547cSRui Paulo }
5195b9c547cSRui Paulo 
5205b9c547cSRui Paulo 
eap_eke_derive_msk(struct eap_eke_session * sess,const u8 * id_s,size_t id_s_len,const u8 * id_p,size_t id_p_len,const u8 * nonce_p,const u8 * nonce_s,u8 * msk,u8 * emsk)5215b9c547cSRui Paulo int eap_eke_derive_msk(struct eap_eke_session *sess,
5225b9c547cSRui Paulo 		       const u8 *id_s, size_t id_s_len,
5235b9c547cSRui Paulo 		       const u8 *id_p, size_t id_p_len,
5245b9c547cSRui Paulo 		       const u8 *nonce_p, const u8 *nonce_s,
5255b9c547cSRui Paulo 		       u8 *msk, u8 *emsk)
5265b9c547cSRui Paulo {
5275b9c547cSRui Paulo 	u8 *data, *pos;
5285b9c547cSRui Paulo 	size_t data_len;
5295b9c547cSRui Paulo 	const char *label = "EAP-EKE Exported Keys";
5305b9c547cSRui Paulo 	size_t label_len;
5315b9c547cSRui Paulo 	u8 buf[EAP_MSK_LEN + EAP_EMSK_LEN];
5325b9c547cSRui Paulo 
5335b9c547cSRui Paulo 	/*
5345b9c547cSRui Paulo 	 * MSK | EMSK = prf+(SharedSecret, "EAP-EKE Exported Keys" | ID_S |
5355b9c547cSRui Paulo 	 *		     ID_P | Nonce_P | Nonce_S)
5365b9c547cSRui Paulo 	 */
5375b9c547cSRui Paulo 
5385b9c547cSRui Paulo 	label_len = os_strlen(label);
5395b9c547cSRui Paulo 	data_len = label_len + id_s_len + id_p_len + 2 * sess->nonce_len;
5405b9c547cSRui Paulo 	data = os_malloc(data_len);
5415b9c547cSRui Paulo 	if (data == NULL)
5425b9c547cSRui Paulo 		return -1;
5435b9c547cSRui Paulo 	pos = data;
5445b9c547cSRui Paulo 	os_memcpy(pos, label, label_len);
5455b9c547cSRui Paulo 	pos += label_len;
5465b9c547cSRui Paulo 	os_memcpy(pos, id_s, id_s_len);
5475b9c547cSRui Paulo 	pos += id_s_len;
5485b9c547cSRui Paulo 	os_memcpy(pos, id_p, id_p_len);
5495b9c547cSRui Paulo 	pos += id_p_len;
5505b9c547cSRui Paulo 	os_memcpy(pos, nonce_p, sess->nonce_len);
5515b9c547cSRui Paulo 	pos += sess->nonce_len;
5525b9c547cSRui Paulo 	os_memcpy(pos, nonce_s, sess->nonce_len);
5535b9c547cSRui Paulo 	if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
5545b9c547cSRui Paulo 			    data, data_len, buf, EAP_MSK_LEN + EAP_EMSK_LEN) <
5555b9c547cSRui Paulo 	    0) {
5565b9c547cSRui Paulo 		os_free(data);
5575b9c547cSRui Paulo 		return -1;
5585b9c547cSRui Paulo 	}
5595b9c547cSRui Paulo 	os_free(data);
5605b9c547cSRui Paulo 
5615b9c547cSRui Paulo 	os_memcpy(msk, buf, EAP_MSK_LEN);
5625b9c547cSRui Paulo 	os_memcpy(emsk, buf + EAP_MSK_LEN, EAP_EMSK_LEN);
5635b9c547cSRui Paulo 	os_memset(buf, 0, sizeof(buf));
5645b9c547cSRui Paulo 
5655b9c547cSRui Paulo 	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: MSK", msk, EAP_MSK_LEN);
5665b9c547cSRui Paulo 	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: EMSK", msk, EAP_EMSK_LEN);
5675b9c547cSRui Paulo 
5685b9c547cSRui Paulo 	return 0;
5695b9c547cSRui Paulo }
5705b9c547cSRui Paulo 
5715b9c547cSRui Paulo 
eap_eke_mac(u8 mac,const u8 * key,const u8 * data,size_t data_len,u8 * res)5725b9c547cSRui Paulo static int eap_eke_mac(u8 mac, const u8 *key, const u8 *data, size_t data_len,
5735b9c547cSRui Paulo 		       u8 *res)
5745b9c547cSRui Paulo {
5755b9c547cSRui Paulo 	if (mac == EAP_EKE_MAC_HMAC_SHA1)
5765b9c547cSRui Paulo 		return hmac_sha1(key, SHA1_MAC_LEN, data, data_len, res);
5775b9c547cSRui Paulo 	if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
5785b9c547cSRui Paulo 		return hmac_sha256(key, SHA256_MAC_LEN, data, data_len, res);
5795b9c547cSRui Paulo 	return -1;
5805b9c547cSRui Paulo }
5815b9c547cSRui Paulo 
5825b9c547cSRui Paulo 
eap_eke_prot(struct eap_eke_session * sess,const u8 * data,size_t data_len,u8 * prot,size_t * prot_len)5835b9c547cSRui Paulo int eap_eke_prot(struct eap_eke_session *sess,
5845b9c547cSRui Paulo 		 const u8 *data, size_t data_len,
5855b9c547cSRui Paulo 		 u8 *prot, size_t *prot_len)
5865b9c547cSRui Paulo {
5875b9c547cSRui Paulo 	size_t block_size, icv_len, pad;
5885b9c547cSRui Paulo 	u8 *pos, *iv, *e;
5895b9c547cSRui Paulo 
5905b9c547cSRui Paulo 	if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
5915b9c547cSRui Paulo 		block_size = AES_BLOCK_SIZE;
5925b9c547cSRui Paulo 	else
5935b9c547cSRui Paulo 		return -1;
5945b9c547cSRui Paulo 
5955b9c547cSRui Paulo 	if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
5965b9c547cSRui Paulo 		icv_len = SHA1_MAC_LEN;
5975b9c547cSRui Paulo 	else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
5985b9c547cSRui Paulo 		icv_len = SHA256_MAC_LEN;
5995b9c547cSRui Paulo 	else
6005b9c547cSRui Paulo 		return -1;
6015b9c547cSRui Paulo 
6025b9c547cSRui Paulo 	pad = data_len % block_size;
6035b9c547cSRui Paulo 	if (pad)
6045b9c547cSRui Paulo 		pad = block_size - pad;
6055b9c547cSRui Paulo 
6065b9c547cSRui Paulo 	if (*prot_len < block_size + data_len + pad + icv_len) {
6075b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for Prot() data");
608780fb4a2SCy Schubert 		return -1;
6095b9c547cSRui Paulo 	}
6105b9c547cSRui Paulo 	pos = prot;
6115b9c547cSRui Paulo 
6125b9c547cSRui Paulo 	if (random_get_bytes(pos, block_size))
6135b9c547cSRui Paulo 		return -1;
6145b9c547cSRui Paulo 	iv = pos;
6155b9c547cSRui Paulo 	wpa_hexdump(MSG_DEBUG, "EAP-EKE: IV for Prot()", iv, block_size);
6165b9c547cSRui Paulo 	pos += block_size;
6175b9c547cSRui Paulo 
6185b9c547cSRui Paulo 	e = pos;
6195b9c547cSRui Paulo 	os_memcpy(pos, data, data_len);
6205b9c547cSRui Paulo 	pos += data_len;
6215b9c547cSRui Paulo 	if (pad) {
6225b9c547cSRui Paulo 		if (random_get_bytes(pos, pad))
6235b9c547cSRui Paulo 			return -1;
6245b9c547cSRui Paulo 		pos += pad;
6255b9c547cSRui Paulo 	}
6265b9c547cSRui Paulo 
627780fb4a2SCy Schubert 	if (aes_128_cbc_encrypt(sess->ke, iv, e, data_len + pad) < 0 ||
628780fb4a2SCy Schubert 	    eap_eke_mac(sess->mac, sess->ki, e, data_len + pad, pos) < 0)
6295b9c547cSRui Paulo 		return -1;
6305b9c547cSRui Paulo 	pos += icv_len;
6315b9c547cSRui Paulo 
6325b9c547cSRui Paulo 	*prot_len = pos - prot;
6335b9c547cSRui Paulo 	return 0;
6345b9c547cSRui Paulo }
6355b9c547cSRui Paulo 
6365b9c547cSRui Paulo 
eap_eke_decrypt_prot(struct eap_eke_session * sess,const u8 * prot,size_t prot_len,u8 * data,size_t * data_len)6375b9c547cSRui Paulo int eap_eke_decrypt_prot(struct eap_eke_session *sess,
6385b9c547cSRui Paulo 			 const u8 *prot, size_t prot_len,
6395b9c547cSRui Paulo 			 u8 *data, size_t *data_len)
6405b9c547cSRui Paulo {
6415b9c547cSRui Paulo 	size_t block_size, icv_len;
6425b9c547cSRui Paulo 	u8 icv[EAP_EKE_MAX_HASH_LEN];
6435b9c547cSRui Paulo 
6445b9c547cSRui Paulo 	if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
6455b9c547cSRui Paulo 		block_size = AES_BLOCK_SIZE;
6465b9c547cSRui Paulo 	else
6475b9c547cSRui Paulo 		return -1;
6485b9c547cSRui Paulo 
6495b9c547cSRui Paulo 	if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
6505b9c547cSRui Paulo 		icv_len = SHA1_MAC_LEN;
6515b9c547cSRui Paulo 	else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
6525b9c547cSRui Paulo 		icv_len = SHA256_MAC_LEN;
6535b9c547cSRui Paulo 	else
6545b9c547cSRui Paulo 		return -1;
6555b9c547cSRui Paulo 
656780fb4a2SCy Schubert 	if (prot_len < 2 * block_size + icv_len ||
657780fb4a2SCy Schubert 	    (prot_len - icv_len) % block_size)
6585b9c547cSRui Paulo 		return -1;
6595b9c547cSRui Paulo 
6605b9c547cSRui Paulo 	if (eap_eke_mac(sess->mac, sess->ki, prot + block_size,
6615b9c547cSRui Paulo 			prot_len - block_size - icv_len, icv) < 0)
6625b9c547cSRui Paulo 		return -1;
6635b9c547cSRui Paulo 	if (os_memcmp_const(icv, prot + prot_len - icv_len, icv_len) != 0) {
6645b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "EAP-EKE: ICV mismatch in Prot() data");
6655b9c547cSRui Paulo 		return -1;
6665b9c547cSRui Paulo 	}
6675b9c547cSRui Paulo 
6685b9c547cSRui Paulo 	if (*data_len < prot_len - block_size - icv_len) {
6695b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for decrypted Prot() data");
6705b9c547cSRui Paulo 		return -1;
6715b9c547cSRui Paulo 	}
6725b9c547cSRui Paulo 
6735b9c547cSRui Paulo 	*data_len = prot_len - block_size - icv_len;
6745b9c547cSRui Paulo 	os_memcpy(data, prot + block_size, *data_len);
6755b9c547cSRui Paulo 	if (aes_128_cbc_decrypt(sess->ke, prot, data, *data_len) < 0) {
6765b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt Prot() data");
6775b9c547cSRui Paulo 		return -1;
6785b9c547cSRui Paulo 	}
6795b9c547cSRui Paulo 	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Decrypted Prot() data",
6805b9c547cSRui Paulo 			data, *data_len);
6815b9c547cSRui Paulo 
6825b9c547cSRui Paulo 	return 0;
6835b9c547cSRui Paulo }
6845b9c547cSRui Paulo 
6855b9c547cSRui Paulo 
eap_eke_auth(struct eap_eke_session * sess,const char * label,const struct wpabuf * msgs,u8 * auth)6865b9c547cSRui Paulo int eap_eke_auth(struct eap_eke_session *sess, const char *label,
6875b9c547cSRui Paulo 		 const struct wpabuf *msgs, u8 *auth)
6885b9c547cSRui Paulo {
6895b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "EAP-EKE: Auth(%s)", label);
6905b9c547cSRui Paulo 	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ka for Auth",
6915b9c547cSRui Paulo 			sess->ka, sess->auth_len);
6925b9c547cSRui Paulo 	wpa_hexdump_buf(MSG_MSGDUMP, "EAP-EKE: Messages for Auth", msgs);
6935b9c547cSRui Paulo 	return eap_eke_prf(sess->prf, sess->ka, sess->auth_len,
6945b9c547cSRui Paulo 			   (const u8 *) label, os_strlen(label),
6955b9c547cSRui Paulo 			   wpabuf_head(msgs), wpabuf_len(msgs), auth);
6965b9c547cSRui Paulo }
6975b9c547cSRui Paulo 
6985b9c547cSRui Paulo 
eap_eke_session_init(struct eap_eke_session * sess,u8 dhgroup,u8 encr,u8 prf,u8 mac)6995b9c547cSRui Paulo int eap_eke_session_init(struct eap_eke_session *sess, u8 dhgroup, u8 encr,
7005b9c547cSRui Paulo 			 u8 prf, u8 mac)
7015b9c547cSRui Paulo {
7025b9c547cSRui Paulo 	sess->dhgroup = dhgroup;
7035b9c547cSRui Paulo 	sess->encr = encr;
7045b9c547cSRui Paulo 	sess->prf = prf;
7055b9c547cSRui Paulo 	sess->mac = mac;
7065b9c547cSRui Paulo 
7075b9c547cSRui Paulo 	sess->prf_len = eap_eke_prf_len(prf);
7085b9c547cSRui Paulo 	sess->nonce_len = eap_eke_nonce_len(prf);
7095b9c547cSRui Paulo 	sess->auth_len = eap_eke_auth_len(prf);
7105b9c547cSRui Paulo 	sess->dhcomp_len = eap_eke_dhcomp_len(sess->dhgroup, sess->encr);
7115b9c547cSRui Paulo 	sess->pnonce_len = eap_eke_pnonce_len(sess->mac);
7125b9c547cSRui Paulo 	sess->pnonce_ps_len = eap_eke_pnonce_ps_len(sess->mac);
713780fb4a2SCy Schubert 	if (sess->prf_len < 0 || sess->nonce_len < 0 || sess->auth_len < 0 ||
714780fb4a2SCy Schubert 	    sess->dhcomp_len < 0 || sess->pnonce_len < 0 ||
715780fb4a2SCy Schubert 	    sess->pnonce_ps_len < 0)
7165b9c547cSRui Paulo 		return -1;
7175b9c547cSRui Paulo 
7185b9c547cSRui Paulo 	return 0;
7195b9c547cSRui Paulo }
7205b9c547cSRui Paulo 
7215b9c547cSRui Paulo 
eap_eke_session_clean(struct eap_eke_session * sess)7225b9c547cSRui Paulo void eap_eke_session_clean(struct eap_eke_session *sess)
7235b9c547cSRui Paulo {
7245b9c547cSRui Paulo 	os_memset(sess->shared_secret, 0, EAP_EKE_MAX_HASH_LEN);
7255b9c547cSRui Paulo 	os_memset(sess->ke, 0, EAP_EKE_MAX_KE_LEN);
7265b9c547cSRui Paulo 	os_memset(sess->ki, 0, EAP_EKE_MAX_KI_LEN);
7275b9c547cSRui Paulo 	os_memset(sess->ka, 0, EAP_EKE_MAX_KA_LEN);
7285b9c547cSRui Paulo }
729