13ff40c12SJohn Marino /*
23ff40c12SJohn Marino * EAP server/peer: EAP-EKE shared routines
33ff40c12SJohn Marino * Copyright (c) 2011-2013, Jouni Malinen <j@w1.fi>
43ff40c12SJohn Marino *
53ff40c12SJohn Marino * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino * See README for more details.
73ff40c12SJohn Marino */
83ff40c12SJohn Marino
93ff40c12SJohn Marino #include "includes.h"
103ff40c12SJohn Marino
113ff40c12SJohn Marino #include "common.h"
123ff40c12SJohn Marino #include "crypto/aes.h"
133ff40c12SJohn Marino #include "crypto/aes_wrap.h"
143ff40c12SJohn Marino #include "crypto/crypto.h"
153ff40c12SJohn Marino #include "crypto/dh_groups.h"
163ff40c12SJohn Marino #include "crypto/random.h"
173ff40c12SJohn Marino #include "crypto/sha1.h"
183ff40c12SJohn Marino #include "crypto/sha256.h"
193ff40c12SJohn Marino #include "eap_common/eap_defs.h"
203ff40c12SJohn Marino #include "eap_eke_common.h"
213ff40c12SJohn Marino
223ff40c12SJohn Marino
eap_eke_dh_len(u8 group)233ff40c12SJohn Marino static int eap_eke_dh_len(u8 group)
243ff40c12SJohn Marino {
253ff40c12SJohn Marino switch (group) {
263ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_2:
273ff40c12SJohn Marino return 128;
283ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_5:
293ff40c12SJohn Marino return 192;
303ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_14:
313ff40c12SJohn Marino return 256;
323ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_15:
333ff40c12SJohn Marino return 384;
343ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_16:
353ff40c12SJohn Marino return 512;
363ff40c12SJohn Marino }
373ff40c12SJohn Marino
383ff40c12SJohn Marino return -1;
393ff40c12SJohn Marino }
403ff40c12SJohn Marino
413ff40c12SJohn Marino
eap_eke_dhcomp_len(u8 dhgroup,u8 encr)423ff40c12SJohn Marino static int eap_eke_dhcomp_len(u8 dhgroup, u8 encr)
433ff40c12SJohn Marino {
443ff40c12SJohn Marino int dhlen;
453ff40c12SJohn Marino
463ff40c12SJohn Marino dhlen = eap_eke_dh_len(dhgroup);
47*a1157835SDaniel Fojt if (dhlen < 0 || encr != EAP_EKE_ENCR_AES128_CBC)
483ff40c12SJohn Marino return -1;
493ff40c12SJohn Marino return AES_BLOCK_SIZE + dhlen;
503ff40c12SJohn Marino }
513ff40c12SJohn Marino
523ff40c12SJohn Marino
eap_eke_dh_group(u8 group)533ff40c12SJohn Marino static const struct dh_group * eap_eke_dh_group(u8 group)
543ff40c12SJohn Marino {
553ff40c12SJohn Marino switch (group) {
563ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_2:
573ff40c12SJohn Marino return dh_groups_get(2);
583ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_5:
593ff40c12SJohn Marino return dh_groups_get(5);
603ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_14:
613ff40c12SJohn Marino return dh_groups_get(14);
623ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_15:
633ff40c12SJohn Marino return dh_groups_get(15);
643ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_16:
653ff40c12SJohn Marino return dh_groups_get(16);
663ff40c12SJohn Marino }
673ff40c12SJohn Marino
683ff40c12SJohn Marino return NULL;
693ff40c12SJohn Marino }
703ff40c12SJohn Marino
713ff40c12SJohn Marino
eap_eke_dh_generator(u8 group)723ff40c12SJohn Marino static int eap_eke_dh_generator(u8 group)
733ff40c12SJohn Marino {
743ff40c12SJohn Marino switch (group) {
753ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_2:
763ff40c12SJohn Marino return 5;
773ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_5:
783ff40c12SJohn Marino return 31;
793ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_14:
803ff40c12SJohn Marino return 11;
813ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_15:
823ff40c12SJohn Marino return 5;
833ff40c12SJohn Marino case EAP_EKE_DHGROUP_EKE_16:
843ff40c12SJohn Marino return 5;
853ff40c12SJohn Marino }
863ff40c12SJohn Marino
873ff40c12SJohn Marino return -1;
883ff40c12SJohn Marino }
893ff40c12SJohn Marino
903ff40c12SJohn Marino
eap_eke_pnonce_len(u8 mac)913ff40c12SJohn Marino static int eap_eke_pnonce_len(u8 mac)
923ff40c12SJohn Marino {
933ff40c12SJohn Marino int mac_len;
943ff40c12SJohn Marino
953ff40c12SJohn Marino if (mac == EAP_EKE_MAC_HMAC_SHA1)
963ff40c12SJohn Marino mac_len = SHA1_MAC_LEN;
973ff40c12SJohn Marino else if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
983ff40c12SJohn Marino mac_len = SHA256_MAC_LEN;
993ff40c12SJohn Marino else
1003ff40c12SJohn Marino return -1;
1013ff40c12SJohn Marino
1023ff40c12SJohn Marino return AES_BLOCK_SIZE + 16 + mac_len;
1033ff40c12SJohn Marino }
1043ff40c12SJohn Marino
1053ff40c12SJohn Marino
eap_eke_pnonce_ps_len(u8 mac)1063ff40c12SJohn Marino static int eap_eke_pnonce_ps_len(u8 mac)
1073ff40c12SJohn Marino {
1083ff40c12SJohn Marino int mac_len;
1093ff40c12SJohn Marino
1103ff40c12SJohn Marino if (mac == EAP_EKE_MAC_HMAC_SHA1)
1113ff40c12SJohn Marino mac_len = SHA1_MAC_LEN;
1123ff40c12SJohn Marino else if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
1133ff40c12SJohn Marino mac_len = SHA256_MAC_LEN;
1143ff40c12SJohn Marino else
1153ff40c12SJohn Marino return -1;
1163ff40c12SJohn Marino
1173ff40c12SJohn Marino return AES_BLOCK_SIZE + 2 * 16 + mac_len;
1183ff40c12SJohn Marino }
1193ff40c12SJohn Marino
1203ff40c12SJohn Marino
eap_eke_prf_len(u8 prf)1213ff40c12SJohn Marino static int eap_eke_prf_len(u8 prf)
1223ff40c12SJohn Marino {
1233ff40c12SJohn Marino if (prf == EAP_EKE_PRF_HMAC_SHA1)
1243ff40c12SJohn Marino return 20;
1253ff40c12SJohn Marino if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
1263ff40c12SJohn Marino return 32;
1273ff40c12SJohn Marino return -1;
1283ff40c12SJohn Marino }
1293ff40c12SJohn Marino
1303ff40c12SJohn Marino
eap_eke_nonce_len(u8 prf)1313ff40c12SJohn Marino static int eap_eke_nonce_len(u8 prf)
1323ff40c12SJohn Marino {
1333ff40c12SJohn Marino int prf_len;
1343ff40c12SJohn Marino
1353ff40c12SJohn Marino prf_len = eap_eke_prf_len(prf);
1363ff40c12SJohn Marino if (prf_len < 0)
1373ff40c12SJohn Marino return -1;
1383ff40c12SJohn Marino
1393ff40c12SJohn Marino if (prf_len > 2 * 16)
1403ff40c12SJohn Marino return (prf_len + 1) / 2;
1413ff40c12SJohn Marino
1423ff40c12SJohn Marino return 16;
1433ff40c12SJohn Marino }
1443ff40c12SJohn Marino
1453ff40c12SJohn Marino
eap_eke_auth_len(u8 prf)1463ff40c12SJohn Marino static int eap_eke_auth_len(u8 prf)
1473ff40c12SJohn Marino {
1483ff40c12SJohn Marino switch (prf) {
1493ff40c12SJohn Marino case EAP_EKE_PRF_HMAC_SHA1:
1503ff40c12SJohn Marino return SHA1_MAC_LEN;
1513ff40c12SJohn Marino case EAP_EKE_PRF_HMAC_SHA2_256:
1523ff40c12SJohn Marino return SHA256_MAC_LEN;
1533ff40c12SJohn Marino }
1543ff40c12SJohn Marino
1553ff40c12SJohn Marino return -1;
1563ff40c12SJohn Marino }
1573ff40c12SJohn Marino
1583ff40c12SJohn Marino
eap_eke_dh_init(u8 group,u8 * ret_priv,u8 * ret_pub)1593ff40c12SJohn Marino int eap_eke_dh_init(u8 group, u8 *ret_priv, u8 *ret_pub)
1603ff40c12SJohn Marino {
1613ff40c12SJohn Marino int generator;
1623ff40c12SJohn Marino u8 gen;
1633ff40c12SJohn Marino const struct dh_group *dh;
1643ff40c12SJohn Marino
1653ff40c12SJohn Marino generator = eap_eke_dh_generator(group);
166*a1157835SDaniel Fojt dh = eap_eke_dh_group(group);
167*a1157835SDaniel Fojt if (generator < 0 || generator > 255 || !dh)
1683ff40c12SJohn Marino return -1;
1693ff40c12SJohn Marino gen = generator;
1703ff40c12SJohn Marino
171*a1157835SDaniel Fojt if (crypto_dh_init(gen, dh->prime, dh->prime_len, ret_priv,
172*a1157835SDaniel Fojt ret_pub) < 0)
1733ff40c12SJohn Marino return -1;
1743ff40c12SJohn Marino wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: DH private value",
1753ff40c12SJohn Marino ret_priv, dh->prime_len);
1763ff40c12SJohn Marino wpa_hexdump(MSG_DEBUG, "EAP-EKE: DH public value",
1773ff40c12SJohn Marino ret_pub, dh->prime_len);
1783ff40c12SJohn Marino
1793ff40c12SJohn Marino return 0;
1803ff40c12SJohn Marino }
1813ff40c12SJohn Marino
1823ff40c12SJohn Marino
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)1833ff40c12SJohn Marino static int eap_eke_prf(u8 prf, const u8 *key, size_t key_len, const u8 *data,
1843ff40c12SJohn Marino size_t data_len, const u8 *data2, size_t data2_len,
1853ff40c12SJohn Marino u8 *res)
1863ff40c12SJohn Marino {
1873ff40c12SJohn Marino const u8 *addr[2];
1883ff40c12SJohn Marino size_t len[2];
1893ff40c12SJohn Marino size_t num_elem = 1;
1903ff40c12SJohn Marino
1913ff40c12SJohn Marino addr[0] = data;
1923ff40c12SJohn Marino len[0] = data_len;
1933ff40c12SJohn Marino if (data2) {
1943ff40c12SJohn Marino num_elem++;
1953ff40c12SJohn Marino addr[1] = data2;
1963ff40c12SJohn Marino len[1] = data2_len;
1973ff40c12SJohn Marino }
1983ff40c12SJohn Marino
1993ff40c12SJohn Marino if (prf == EAP_EKE_PRF_HMAC_SHA1)
2003ff40c12SJohn Marino return hmac_sha1_vector(key, key_len, num_elem, addr, len, res);
2013ff40c12SJohn Marino if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
2023ff40c12SJohn Marino return hmac_sha256_vector(key, key_len, num_elem, addr, len,
2033ff40c12SJohn Marino res);
2043ff40c12SJohn Marino return -1;
2053ff40c12SJohn Marino }
2063ff40c12SJohn Marino
2073ff40c12SJohn Marino
eap_eke_prf_hmac_sha1(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * res,size_t len)2083ff40c12SJohn Marino static int eap_eke_prf_hmac_sha1(const u8 *key, size_t key_len, const u8 *data,
2093ff40c12SJohn Marino size_t data_len, u8 *res, size_t len)
2103ff40c12SJohn Marino {
2113ff40c12SJohn Marino u8 hash[SHA1_MAC_LEN];
2123ff40c12SJohn Marino u8 idx;
2133ff40c12SJohn Marino const u8 *addr[3];
2143ff40c12SJohn Marino size_t vlen[3];
2153ff40c12SJohn Marino int ret;
2163ff40c12SJohn Marino
2173ff40c12SJohn Marino idx = 0;
2183ff40c12SJohn Marino addr[0] = hash;
2193ff40c12SJohn Marino vlen[0] = SHA1_MAC_LEN;
2203ff40c12SJohn Marino addr[1] = data;
2213ff40c12SJohn Marino vlen[1] = data_len;
2223ff40c12SJohn Marino addr[2] = &idx;
2233ff40c12SJohn Marino vlen[2] = 1;
2243ff40c12SJohn Marino
2253ff40c12SJohn Marino while (len > 0) {
2263ff40c12SJohn Marino idx++;
2273ff40c12SJohn Marino if (idx == 1)
2283ff40c12SJohn Marino ret = hmac_sha1_vector(key, key_len, 2, &addr[1],
2293ff40c12SJohn Marino &vlen[1], hash);
2303ff40c12SJohn Marino else
2313ff40c12SJohn Marino ret = hmac_sha1_vector(key, key_len, 3, addr, vlen,
2323ff40c12SJohn Marino hash);
2333ff40c12SJohn Marino if (ret < 0)
2343ff40c12SJohn Marino return -1;
2353ff40c12SJohn Marino if (len > SHA1_MAC_LEN) {
2363ff40c12SJohn Marino os_memcpy(res, hash, SHA1_MAC_LEN);
2373ff40c12SJohn Marino res += SHA1_MAC_LEN;
2383ff40c12SJohn Marino len -= SHA1_MAC_LEN;
2393ff40c12SJohn Marino } else {
2403ff40c12SJohn Marino os_memcpy(res, hash, len);
2413ff40c12SJohn Marino len = 0;
2423ff40c12SJohn Marino }
2433ff40c12SJohn Marino }
2443ff40c12SJohn Marino
2453ff40c12SJohn Marino return 0;
2463ff40c12SJohn Marino }
2473ff40c12SJohn Marino
2483ff40c12SJohn Marino
eap_eke_prf_hmac_sha256(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * res,size_t len)2493ff40c12SJohn Marino static int eap_eke_prf_hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
2503ff40c12SJohn Marino size_t data_len, u8 *res, size_t len)
2513ff40c12SJohn Marino {
2523ff40c12SJohn Marino u8 hash[SHA256_MAC_LEN];
2533ff40c12SJohn Marino u8 idx;
2543ff40c12SJohn Marino const u8 *addr[3];
2553ff40c12SJohn Marino size_t vlen[3];
2563ff40c12SJohn Marino int ret;
2573ff40c12SJohn Marino
2583ff40c12SJohn Marino idx = 0;
2593ff40c12SJohn Marino addr[0] = hash;
2603ff40c12SJohn Marino vlen[0] = SHA256_MAC_LEN;
2613ff40c12SJohn Marino addr[1] = data;
2623ff40c12SJohn Marino vlen[1] = data_len;
2633ff40c12SJohn Marino addr[2] = &idx;
2643ff40c12SJohn Marino vlen[2] = 1;
2653ff40c12SJohn Marino
2663ff40c12SJohn Marino while (len > 0) {
2673ff40c12SJohn Marino idx++;
2683ff40c12SJohn Marino if (idx == 1)
2693ff40c12SJohn Marino ret = hmac_sha256_vector(key, key_len, 2, &addr[1],
2703ff40c12SJohn Marino &vlen[1], hash);
2713ff40c12SJohn Marino else
2723ff40c12SJohn Marino ret = hmac_sha256_vector(key, key_len, 3, addr, vlen,
2733ff40c12SJohn Marino hash);
2743ff40c12SJohn Marino if (ret < 0)
2753ff40c12SJohn Marino return -1;
2763ff40c12SJohn Marino if (len > SHA256_MAC_LEN) {
2773ff40c12SJohn Marino os_memcpy(res, hash, SHA256_MAC_LEN);
2783ff40c12SJohn Marino res += SHA256_MAC_LEN;
2793ff40c12SJohn Marino len -= SHA256_MAC_LEN;
2803ff40c12SJohn Marino } else {
2813ff40c12SJohn Marino os_memcpy(res, hash, len);
2823ff40c12SJohn Marino len = 0;
2833ff40c12SJohn Marino }
2843ff40c12SJohn Marino }
2853ff40c12SJohn Marino
2863ff40c12SJohn Marino return 0;
2873ff40c12SJohn Marino }
2883ff40c12SJohn Marino
2893ff40c12SJohn Marino
eap_eke_prfplus(u8 prf,const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * res,size_t len)2903ff40c12SJohn Marino static int eap_eke_prfplus(u8 prf, const u8 *key, size_t key_len,
2913ff40c12SJohn Marino const u8 *data, size_t data_len, u8 *res, size_t len)
2923ff40c12SJohn Marino {
2933ff40c12SJohn Marino if (prf == EAP_EKE_PRF_HMAC_SHA1)
2943ff40c12SJohn Marino return eap_eke_prf_hmac_sha1(key, key_len, data, data_len, res,
2953ff40c12SJohn Marino len);
2963ff40c12SJohn Marino if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
2973ff40c12SJohn Marino return eap_eke_prf_hmac_sha256(key, key_len, data, data_len,
2983ff40c12SJohn Marino res, len);
2993ff40c12SJohn Marino return -1;
3003ff40c12SJohn Marino }
3013ff40c12SJohn Marino
3023ff40c12SJohn Marino
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)3033ff40c12SJohn Marino int eap_eke_derive_key(struct eap_eke_session *sess,
3043ff40c12SJohn Marino const u8 *password, size_t password_len,
3053ff40c12SJohn Marino const u8 *id_s, size_t id_s_len, const u8 *id_p,
3063ff40c12SJohn Marino size_t id_p_len, u8 *key)
3073ff40c12SJohn Marino {
3083ff40c12SJohn Marino u8 zeros[EAP_EKE_MAX_HASH_LEN];
3093ff40c12SJohn Marino u8 temp[EAP_EKE_MAX_HASH_LEN];
3103ff40c12SJohn Marino size_t key_len = 16; /* Only AES-128-CBC is used here */
3113ff40c12SJohn Marino u8 *id;
3123ff40c12SJohn Marino
3133ff40c12SJohn Marino /* temp = prf(0+, password) */
3143ff40c12SJohn Marino os_memset(zeros, 0, sess->prf_len);
3153ff40c12SJohn Marino if (eap_eke_prf(sess->prf, zeros, sess->prf_len,
3163ff40c12SJohn Marino password, password_len, NULL, 0, temp) < 0)
3173ff40c12SJohn Marino return -1;
3183ff40c12SJohn Marino wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: temp = prf(0+, password)",
3193ff40c12SJohn Marino temp, sess->prf_len);
3203ff40c12SJohn Marino
3213ff40c12SJohn Marino /* key = prf+(temp, ID_S | ID_P) */
3223ff40c12SJohn Marino id = os_malloc(id_s_len + id_p_len);
3233ff40c12SJohn Marino if (id == NULL)
3243ff40c12SJohn Marino return -1;
3253ff40c12SJohn Marino os_memcpy(id, id_s, id_s_len);
3263ff40c12SJohn Marino os_memcpy(id + id_s_len, id_p, id_p_len);
3273ff40c12SJohn Marino wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: ID_S | ID_P",
3283ff40c12SJohn Marino id, id_s_len + id_p_len);
3293ff40c12SJohn Marino if (eap_eke_prfplus(sess->prf, temp, sess->prf_len,
3303ff40c12SJohn Marino id, id_s_len + id_p_len, key, key_len) < 0) {
3313ff40c12SJohn Marino os_free(id);
3323ff40c12SJohn Marino return -1;
3333ff40c12SJohn Marino }
3343ff40c12SJohn Marino os_free(id);
3353ff40c12SJohn Marino wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: key = prf+(temp, ID_S | ID_P)",
3363ff40c12SJohn Marino key, key_len);
3373ff40c12SJohn Marino
3383ff40c12SJohn Marino return 0;
3393ff40c12SJohn Marino }
3403ff40c12SJohn Marino
3413ff40c12SJohn Marino
eap_eke_dhcomp(struct eap_eke_session * sess,const u8 * key,const u8 * dhpub,u8 * ret_dhcomp)3423ff40c12SJohn Marino int eap_eke_dhcomp(struct eap_eke_session *sess, const u8 *key, const u8 *dhpub,
3433ff40c12SJohn Marino u8 *ret_dhcomp)
3443ff40c12SJohn Marino {
3453ff40c12SJohn Marino u8 pub[EAP_EKE_MAX_DH_LEN];
3463ff40c12SJohn Marino int dh_len;
3473ff40c12SJohn Marino u8 iv[AES_BLOCK_SIZE];
3483ff40c12SJohn Marino
3493ff40c12SJohn Marino dh_len = eap_eke_dh_len(sess->dhgroup);
3503ff40c12SJohn Marino if (dh_len < 0)
3513ff40c12SJohn Marino return -1;
3523ff40c12SJohn Marino
3533ff40c12SJohn Marino /*
3543ff40c12SJohn Marino * DHComponent = Encr(key, y)
3553ff40c12SJohn Marino *
3563ff40c12SJohn Marino * All defined DH groups use primes that have length devisible by 16, so
3573ff40c12SJohn Marino * no need to do extra padding for y (= pub).
3583ff40c12SJohn Marino */
3593ff40c12SJohn Marino if (sess->encr != EAP_EKE_ENCR_AES128_CBC)
3603ff40c12SJohn Marino return -1;
3613ff40c12SJohn Marino if (random_get_bytes(iv, AES_BLOCK_SIZE))
3623ff40c12SJohn Marino return -1;
3633ff40c12SJohn Marino wpa_hexdump(MSG_DEBUG, "EAP-EKE: IV for Encr(key, y)",
3643ff40c12SJohn Marino iv, AES_BLOCK_SIZE);
3653ff40c12SJohn Marino os_memcpy(pub, dhpub, dh_len);
3663ff40c12SJohn Marino if (aes_128_cbc_encrypt(key, iv, pub, dh_len) < 0)
3673ff40c12SJohn Marino return -1;
3683ff40c12SJohn Marino os_memcpy(ret_dhcomp, iv, AES_BLOCK_SIZE);
3693ff40c12SJohn Marino os_memcpy(ret_dhcomp + AES_BLOCK_SIZE, pub, dh_len);
3703ff40c12SJohn Marino wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent = Encr(key, y)",
3713ff40c12SJohn Marino ret_dhcomp, AES_BLOCK_SIZE + dh_len);
3723ff40c12SJohn Marino
3733ff40c12SJohn Marino return 0;
3743ff40c12SJohn Marino }
3753ff40c12SJohn Marino
3763ff40c12SJohn Marino
eap_eke_shared_secret(struct eap_eke_session * sess,const u8 * key,const u8 * dhpriv,const u8 * peer_dhcomp)3773ff40c12SJohn Marino int eap_eke_shared_secret(struct eap_eke_session *sess, const u8 *key,
3783ff40c12SJohn Marino const u8 *dhpriv, const u8 *peer_dhcomp)
3793ff40c12SJohn Marino {
3803ff40c12SJohn Marino u8 zeros[EAP_EKE_MAX_HASH_LEN];
3813ff40c12SJohn Marino u8 peer_pub[EAP_EKE_MAX_DH_LEN];
3823ff40c12SJohn Marino u8 modexp[EAP_EKE_MAX_DH_LEN];
3833ff40c12SJohn Marino size_t len;
3843ff40c12SJohn Marino const struct dh_group *dh;
3853ff40c12SJohn Marino
3863ff40c12SJohn Marino dh = eap_eke_dh_group(sess->dhgroup);
387*a1157835SDaniel Fojt if (sess->encr != EAP_EKE_ENCR_AES128_CBC || !dh)
3883ff40c12SJohn Marino return -1;
3893ff40c12SJohn Marino
3903ff40c12SJohn Marino /* Decrypt peer DHComponent */
3913ff40c12SJohn Marino os_memcpy(peer_pub, peer_dhcomp + AES_BLOCK_SIZE, dh->prime_len);
3923ff40c12SJohn Marino if (aes_128_cbc_decrypt(key, peer_dhcomp, peer_pub, dh->prime_len) < 0) {
3933ff40c12SJohn Marino wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt DHComponent");
3943ff40c12SJohn Marino return -1;
3953ff40c12SJohn Marino }
3963ff40c12SJohn Marino wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Decrypted peer DH pubkey",
3973ff40c12SJohn Marino peer_pub, dh->prime_len);
3983ff40c12SJohn Marino
3993ff40c12SJohn Marino /* SharedSecret = prf(0+, g ^ (x_s * x_p) (mod p)) */
4003ff40c12SJohn Marino len = dh->prime_len;
401*a1157835SDaniel Fojt if (crypto_dh_derive_secret(*dh->generator, dh->prime, dh->prime_len,
402*a1157835SDaniel Fojt NULL, 0, dhpriv, dh->prime_len, peer_pub,
403*a1157835SDaniel Fojt dh->prime_len, modexp, &len) < 0)
4043ff40c12SJohn Marino return -1;
4053ff40c12SJohn Marino if (len < dh->prime_len) {
4063ff40c12SJohn Marino size_t pad = dh->prime_len - len;
4073ff40c12SJohn Marino os_memmove(modexp + pad, modexp, len);
4083ff40c12SJohn Marino os_memset(modexp, 0, pad);
4093ff40c12SJohn Marino }
4103ff40c12SJohn Marino
4113ff40c12SJohn Marino os_memset(zeros, 0, sess->auth_len);
4123ff40c12SJohn Marino if (eap_eke_prf(sess->prf, zeros, sess->auth_len, modexp, dh->prime_len,
4133ff40c12SJohn Marino NULL, 0, sess->shared_secret) < 0)
4143ff40c12SJohn Marino return -1;
4153ff40c12SJohn Marino wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: SharedSecret",
4163ff40c12SJohn Marino sess->shared_secret, sess->auth_len);
4173ff40c12SJohn Marino
4183ff40c12SJohn Marino return 0;
4193ff40c12SJohn Marino }
4203ff40c12SJohn Marino
4213ff40c12SJohn Marino
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)4223ff40c12SJohn Marino int eap_eke_derive_ke_ki(struct eap_eke_session *sess,
4233ff40c12SJohn Marino const u8 *id_s, size_t id_s_len,
4243ff40c12SJohn Marino const u8 *id_p, size_t id_p_len)
4253ff40c12SJohn Marino {
4263ff40c12SJohn Marino u8 buf[EAP_EKE_MAX_KE_LEN + EAP_EKE_MAX_KI_LEN];
4273ff40c12SJohn Marino size_t ke_len, ki_len;
4283ff40c12SJohn Marino u8 *data;
4293ff40c12SJohn Marino size_t data_len;
4303ff40c12SJohn Marino const char *label = "EAP-EKE Keys";
4313ff40c12SJohn Marino size_t label_len;
4323ff40c12SJohn Marino
4333ff40c12SJohn Marino /*
4343ff40c12SJohn Marino * Ke | Ki = prf+(SharedSecret, "EAP-EKE Keys" | ID_S | ID_P)
4353ff40c12SJohn Marino * Ke = encryption key
4363ff40c12SJohn Marino * Ki = integrity protection key
4373ff40c12SJohn Marino * Length of each key depends on the selected algorithms.
4383ff40c12SJohn Marino */
4393ff40c12SJohn Marino
4403ff40c12SJohn Marino if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
4413ff40c12SJohn Marino ke_len = 16;
4423ff40c12SJohn Marino else
4433ff40c12SJohn Marino return -1;
4443ff40c12SJohn Marino
4453ff40c12SJohn Marino if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
4463ff40c12SJohn Marino ki_len = 20;
4473ff40c12SJohn Marino else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
4483ff40c12SJohn Marino ki_len = 32;
4493ff40c12SJohn Marino else
4503ff40c12SJohn Marino return -1;
4513ff40c12SJohn Marino
4523ff40c12SJohn Marino label_len = os_strlen(label);
4533ff40c12SJohn Marino data_len = label_len + id_s_len + id_p_len;
4543ff40c12SJohn Marino data = os_malloc(data_len);
4553ff40c12SJohn Marino if (data == NULL)
4563ff40c12SJohn Marino return -1;
4573ff40c12SJohn Marino os_memcpy(data, label, label_len);
4583ff40c12SJohn Marino os_memcpy(data + label_len, id_s, id_s_len);
4593ff40c12SJohn Marino os_memcpy(data + label_len + id_s_len, id_p, id_p_len);
4603ff40c12SJohn Marino if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
4613ff40c12SJohn Marino data, data_len, buf, ke_len + ki_len) < 0) {
4623ff40c12SJohn Marino os_free(data);
4633ff40c12SJohn Marino return -1;
4643ff40c12SJohn Marino }
4653ff40c12SJohn Marino
4663ff40c12SJohn Marino os_memcpy(sess->ke, buf, ke_len);
4673ff40c12SJohn Marino wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ke", sess->ke, ke_len);
4683ff40c12SJohn Marino os_memcpy(sess->ki, buf + ke_len, ki_len);
4693ff40c12SJohn Marino wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ki", sess->ki, ki_len);
4703ff40c12SJohn Marino
4713ff40c12SJohn Marino os_free(data);
4723ff40c12SJohn Marino return 0;
4733ff40c12SJohn Marino }
4743ff40c12SJohn Marino
4753ff40c12SJohn Marino
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)4763ff40c12SJohn Marino int eap_eke_derive_ka(struct eap_eke_session *sess,
4773ff40c12SJohn Marino const u8 *id_s, size_t id_s_len,
4783ff40c12SJohn Marino const u8 *id_p, size_t id_p_len,
4793ff40c12SJohn Marino const u8 *nonce_p, const u8 *nonce_s)
4803ff40c12SJohn Marino {
4813ff40c12SJohn Marino u8 *data, *pos;
4823ff40c12SJohn Marino size_t data_len;
4833ff40c12SJohn Marino const char *label = "EAP-EKE Ka";
4843ff40c12SJohn Marino size_t label_len;
4853ff40c12SJohn Marino
4863ff40c12SJohn Marino /*
4873ff40c12SJohn Marino * Ka = prf+(SharedSecret, "EAP-EKE Ka" | ID_S | ID_P | Nonce_P |
4883ff40c12SJohn Marino * Nonce_S)
4893ff40c12SJohn Marino * Ka = authentication key
4903ff40c12SJohn Marino * Length of the key depends on the selected algorithms.
4913ff40c12SJohn Marino */
4923ff40c12SJohn Marino
4933ff40c12SJohn Marino label_len = os_strlen(label);
4943ff40c12SJohn Marino data_len = label_len + id_s_len + id_p_len + 2 * sess->nonce_len;
4953ff40c12SJohn Marino data = os_malloc(data_len);
4963ff40c12SJohn Marino if (data == NULL)
4973ff40c12SJohn Marino return -1;
4983ff40c12SJohn Marino pos = data;
4993ff40c12SJohn Marino os_memcpy(pos, label, label_len);
5003ff40c12SJohn Marino pos += label_len;
5013ff40c12SJohn Marino os_memcpy(pos, id_s, id_s_len);
5023ff40c12SJohn Marino pos += id_s_len;
5033ff40c12SJohn Marino os_memcpy(pos, id_p, id_p_len);
5043ff40c12SJohn Marino pos += id_p_len;
5053ff40c12SJohn Marino os_memcpy(pos, nonce_p, sess->nonce_len);
5063ff40c12SJohn Marino pos += sess->nonce_len;
5073ff40c12SJohn Marino os_memcpy(pos, nonce_s, sess->nonce_len);
5083ff40c12SJohn Marino if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
5093ff40c12SJohn Marino data, data_len, sess->ka, sess->prf_len) < 0) {
5103ff40c12SJohn Marino os_free(data);
5113ff40c12SJohn Marino return -1;
5123ff40c12SJohn Marino }
5133ff40c12SJohn Marino os_free(data);
5143ff40c12SJohn Marino
5153ff40c12SJohn Marino wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ka", sess->ka, sess->prf_len);
5163ff40c12SJohn Marino
5173ff40c12SJohn Marino return 0;
5183ff40c12SJohn Marino }
5193ff40c12SJohn Marino
5203ff40c12SJohn Marino
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)5213ff40c12SJohn Marino int eap_eke_derive_msk(struct eap_eke_session *sess,
5223ff40c12SJohn Marino const u8 *id_s, size_t id_s_len,
5233ff40c12SJohn Marino const u8 *id_p, size_t id_p_len,
5243ff40c12SJohn Marino const u8 *nonce_p, const u8 *nonce_s,
5253ff40c12SJohn Marino u8 *msk, u8 *emsk)
5263ff40c12SJohn Marino {
5273ff40c12SJohn Marino u8 *data, *pos;
5283ff40c12SJohn Marino size_t data_len;
5293ff40c12SJohn Marino const char *label = "EAP-EKE Exported Keys";
5303ff40c12SJohn Marino size_t label_len;
5313ff40c12SJohn Marino u8 buf[EAP_MSK_LEN + EAP_EMSK_LEN];
5323ff40c12SJohn Marino
5333ff40c12SJohn Marino /*
5343ff40c12SJohn Marino * MSK | EMSK = prf+(SharedSecret, "EAP-EKE Exported Keys" | ID_S |
5353ff40c12SJohn Marino * ID_P | Nonce_P | Nonce_S)
5363ff40c12SJohn Marino */
5373ff40c12SJohn Marino
5383ff40c12SJohn Marino label_len = os_strlen(label);
5393ff40c12SJohn Marino data_len = label_len + id_s_len + id_p_len + 2 * sess->nonce_len;
5403ff40c12SJohn Marino data = os_malloc(data_len);
5413ff40c12SJohn Marino if (data == NULL)
5423ff40c12SJohn Marino return -1;
5433ff40c12SJohn Marino pos = data;
5443ff40c12SJohn Marino os_memcpy(pos, label, label_len);
5453ff40c12SJohn Marino pos += label_len;
5463ff40c12SJohn Marino os_memcpy(pos, id_s, id_s_len);
5473ff40c12SJohn Marino pos += id_s_len;
5483ff40c12SJohn Marino os_memcpy(pos, id_p, id_p_len);
5493ff40c12SJohn Marino pos += id_p_len;
5503ff40c12SJohn Marino os_memcpy(pos, nonce_p, sess->nonce_len);
5513ff40c12SJohn Marino pos += sess->nonce_len;
5523ff40c12SJohn Marino os_memcpy(pos, nonce_s, sess->nonce_len);
5533ff40c12SJohn Marino if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
5543ff40c12SJohn Marino data, data_len, buf, EAP_MSK_LEN + EAP_EMSK_LEN) <
5553ff40c12SJohn Marino 0) {
5563ff40c12SJohn Marino os_free(data);
5573ff40c12SJohn Marino return -1;
5583ff40c12SJohn Marino }
5593ff40c12SJohn Marino os_free(data);
5603ff40c12SJohn Marino
5613ff40c12SJohn Marino os_memcpy(msk, buf, EAP_MSK_LEN);
5623ff40c12SJohn Marino os_memcpy(emsk, buf + EAP_MSK_LEN, EAP_EMSK_LEN);
5633ff40c12SJohn Marino os_memset(buf, 0, sizeof(buf));
5643ff40c12SJohn Marino
5653ff40c12SJohn Marino wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: MSK", msk, EAP_MSK_LEN);
5663ff40c12SJohn Marino wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: EMSK", msk, EAP_EMSK_LEN);
5673ff40c12SJohn Marino
5683ff40c12SJohn Marino return 0;
5693ff40c12SJohn Marino }
5703ff40c12SJohn Marino
5713ff40c12SJohn Marino
eap_eke_mac(u8 mac,const u8 * key,const u8 * data,size_t data_len,u8 * res)5723ff40c12SJohn Marino static int eap_eke_mac(u8 mac, const u8 *key, const u8 *data, size_t data_len,
5733ff40c12SJohn Marino u8 *res)
5743ff40c12SJohn Marino {
5753ff40c12SJohn Marino if (mac == EAP_EKE_MAC_HMAC_SHA1)
5763ff40c12SJohn Marino return hmac_sha1(key, SHA1_MAC_LEN, data, data_len, res);
5773ff40c12SJohn Marino if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
5783ff40c12SJohn Marino return hmac_sha256(key, SHA256_MAC_LEN, data, data_len, res);
5793ff40c12SJohn Marino return -1;
5803ff40c12SJohn Marino }
5813ff40c12SJohn Marino
5823ff40c12SJohn Marino
eap_eke_prot(struct eap_eke_session * sess,const u8 * data,size_t data_len,u8 * prot,size_t * prot_len)5833ff40c12SJohn Marino int eap_eke_prot(struct eap_eke_session *sess,
5843ff40c12SJohn Marino const u8 *data, size_t data_len,
5853ff40c12SJohn Marino u8 *prot, size_t *prot_len)
5863ff40c12SJohn Marino {
5873ff40c12SJohn Marino size_t block_size, icv_len, pad;
5883ff40c12SJohn Marino u8 *pos, *iv, *e;
5893ff40c12SJohn Marino
5903ff40c12SJohn Marino if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
5913ff40c12SJohn Marino block_size = AES_BLOCK_SIZE;
5923ff40c12SJohn Marino else
5933ff40c12SJohn Marino return -1;
5943ff40c12SJohn Marino
5953ff40c12SJohn Marino if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
5963ff40c12SJohn Marino icv_len = SHA1_MAC_LEN;
5973ff40c12SJohn Marino else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
5983ff40c12SJohn Marino icv_len = SHA256_MAC_LEN;
5993ff40c12SJohn Marino else
6003ff40c12SJohn Marino return -1;
6013ff40c12SJohn Marino
6023ff40c12SJohn Marino pad = data_len % block_size;
6033ff40c12SJohn Marino if (pad)
6043ff40c12SJohn Marino pad = block_size - pad;
6053ff40c12SJohn Marino
6063ff40c12SJohn Marino if (*prot_len < block_size + data_len + pad + icv_len) {
6073ff40c12SJohn Marino wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for Prot() data");
608*a1157835SDaniel Fojt return -1;
6093ff40c12SJohn Marino }
6103ff40c12SJohn Marino pos = prot;
6113ff40c12SJohn Marino
6123ff40c12SJohn Marino if (random_get_bytes(pos, block_size))
6133ff40c12SJohn Marino return -1;
6143ff40c12SJohn Marino iv = pos;
6153ff40c12SJohn Marino wpa_hexdump(MSG_DEBUG, "EAP-EKE: IV for Prot()", iv, block_size);
6163ff40c12SJohn Marino pos += block_size;
6173ff40c12SJohn Marino
6183ff40c12SJohn Marino e = pos;
6193ff40c12SJohn Marino os_memcpy(pos, data, data_len);
6203ff40c12SJohn Marino pos += data_len;
6213ff40c12SJohn Marino if (pad) {
6223ff40c12SJohn Marino if (random_get_bytes(pos, pad))
6233ff40c12SJohn Marino return -1;
6243ff40c12SJohn Marino pos += pad;
6253ff40c12SJohn Marino }
6263ff40c12SJohn Marino
627*a1157835SDaniel Fojt if (aes_128_cbc_encrypt(sess->ke, iv, e, data_len + pad) < 0 ||
628*a1157835SDaniel Fojt eap_eke_mac(sess->mac, sess->ki, e, data_len + pad, pos) < 0)
6293ff40c12SJohn Marino return -1;
6303ff40c12SJohn Marino pos += icv_len;
6313ff40c12SJohn Marino
6323ff40c12SJohn Marino *prot_len = pos - prot;
6333ff40c12SJohn Marino return 0;
6343ff40c12SJohn Marino }
6353ff40c12SJohn Marino
6363ff40c12SJohn Marino
eap_eke_decrypt_prot(struct eap_eke_session * sess,const u8 * prot,size_t prot_len,u8 * data,size_t * data_len)6373ff40c12SJohn Marino int eap_eke_decrypt_prot(struct eap_eke_session *sess,
6383ff40c12SJohn Marino const u8 *prot, size_t prot_len,
6393ff40c12SJohn Marino u8 *data, size_t *data_len)
6403ff40c12SJohn Marino {
6413ff40c12SJohn Marino size_t block_size, icv_len;
6423ff40c12SJohn Marino u8 icv[EAP_EKE_MAX_HASH_LEN];
6433ff40c12SJohn Marino
6443ff40c12SJohn Marino if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
6453ff40c12SJohn Marino block_size = AES_BLOCK_SIZE;
6463ff40c12SJohn Marino else
6473ff40c12SJohn Marino return -1;
6483ff40c12SJohn Marino
6493ff40c12SJohn Marino if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
6503ff40c12SJohn Marino icv_len = SHA1_MAC_LEN;
6513ff40c12SJohn Marino else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
6523ff40c12SJohn Marino icv_len = SHA256_MAC_LEN;
6533ff40c12SJohn Marino else
6543ff40c12SJohn Marino return -1;
6553ff40c12SJohn Marino
656*a1157835SDaniel Fojt if (prot_len < 2 * block_size + icv_len ||
657*a1157835SDaniel Fojt (prot_len - icv_len) % block_size)
6583ff40c12SJohn Marino return -1;
6593ff40c12SJohn Marino
6603ff40c12SJohn Marino if (eap_eke_mac(sess->mac, sess->ki, prot + block_size,
6613ff40c12SJohn Marino prot_len - block_size - icv_len, icv) < 0)
6623ff40c12SJohn Marino return -1;
663*a1157835SDaniel Fojt if (os_memcmp_const(icv, prot + prot_len - icv_len, icv_len) != 0) {
6643ff40c12SJohn Marino wpa_printf(MSG_INFO, "EAP-EKE: ICV mismatch in Prot() data");
6653ff40c12SJohn Marino return -1;
6663ff40c12SJohn Marino }
6673ff40c12SJohn Marino
6683ff40c12SJohn Marino if (*data_len < prot_len - block_size - icv_len) {
6693ff40c12SJohn Marino wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for decrypted Prot() data");
6703ff40c12SJohn Marino return -1;
6713ff40c12SJohn Marino }
6723ff40c12SJohn Marino
6733ff40c12SJohn Marino *data_len = prot_len - block_size - icv_len;
6743ff40c12SJohn Marino os_memcpy(data, prot + block_size, *data_len);
6753ff40c12SJohn Marino if (aes_128_cbc_decrypt(sess->ke, prot, data, *data_len) < 0) {
6763ff40c12SJohn Marino wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt Prot() data");
6773ff40c12SJohn Marino return -1;
6783ff40c12SJohn Marino }
6793ff40c12SJohn Marino wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Decrypted Prot() data",
6803ff40c12SJohn Marino data, *data_len);
6813ff40c12SJohn Marino
6823ff40c12SJohn Marino return 0;
6833ff40c12SJohn Marino }
6843ff40c12SJohn Marino
6853ff40c12SJohn Marino
eap_eke_auth(struct eap_eke_session * sess,const char * label,const struct wpabuf * msgs,u8 * auth)6863ff40c12SJohn Marino int eap_eke_auth(struct eap_eke_session *sess, const char *label,
6873ff40c12SJohn Marino const struct wpabuf *msgs, u8 *auth)
6883ff40c12SJohn Marino {
6893ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "EAP-EKE: Auth(%s)", label);
6903ff40c12SJohn Marino wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ka for Auth",
6913ff40c12SJohn Marino sess->ka, sess->auth_len);
6923ff40c12SJohn Marino wpa_hexdump_buf(MSG_MSGDUMP, "EAP-EKE: Messages for Auth", msgs);
6933ff40c12SJohn Marino return eap_eke_prf(sess->prf, sess->ka, sess->auth_len,
6943ff40c12SJohn Marino (const u8 *) label, os_strlen(label),
6953ff40c12SJohn Marino wpabuf_head(msgs), wpabuf_len(msgs), auth);
6963ff40c12SJohn Marino }
6973ff40c12SJohn Marino
6983ff40c12SJohn Marino
eap_eke_session_init(struct eap_eke_session * sess,u8 dhgroup,u8 encr,u8 prf,u8 mac)6993ff40c12SJohn Marino int eap_eke_session_init(struct eap_eke_session *sess, u8 dhgroup, u8 encr,
7003ff40c12SJohn Marino u8 prf, u8 mac)
7013ff40c12SJohn Marino {
7023ff40c12SJohn Marino sess->dhgroup = dhgroup;
7033ff40c12SJohn Marino sess->encr = encr;
7043ff40c12SJohn Marino sess->prf = prf;
7053ff40c12SJohn Marino sess->mac = mac;
7063ff40c12SJohn Marino
7073ff40c12SJohn Marino sess->prf_len = eap_eke_prf_len(prf);
7083ff40c12SJohn Marino sess->nonce_len = eap_eke_nonce_len(prf);
7093ff40c12SJohn Marino sess->auth_len = eap_eke_auth_len(prf);
7103ff40c12SJohn Marino sess->dhcomp_len = eap_eke_dhcomp_len(sess->dhgroup, sess->encr);
7113ff40c12SJohn Marino sess->pnonce_len = eap_eke_pnonce_len(sess->mac);
7123ff40c12SJohn Marino sess->pnonce_ps_len = eap_eke_pnonce_ps_len(sess->mac);
713*a1157835SDaniel Fojt if (sess->prf_len < 0 || sess->nonce_len < 0 || sess->auth_len < 0 ||
714*a1157835SDaniel Fojt sess->dhcomp_len < 0 || sess->pnonce_len < 0 ||
715*a1157835SDaniel Fojt sess->pnonce_ps_len < 0)
7163ff40c12SJohn Marino return -1;
7173ff40c12SJohn Marino
7183ff40c12SJohn Marino return 0;
7193ff40c12SJohn Marino }
7203ff40c12SJohn Marino
7213ff40c12SJohn Marino
eap_eke_session_clean(struct eap_eke_session * sess)7223ff40c12SJohn Marino void eap_eke_session_clean(struct eap_eke_session *sess)
7233ff40c12SJohn Marino {
7243ff40c12SJohn Marino os_memset(sess->shared_secret, 0, EAP_EKE_MAX_HASH_LEN);
7253ff40c12SJohn Marino os_memset(sess->ke, 0, EAP_EKE_MAX_KE_LEN);
7263ff40c12SJohn Marino os_memset(sess->ki, 0, EAP_EKE_MAX_KI_LEN);
7273ff40c12SJohn Marino os_memset(sess->ka, 0, EAP_EKE_MAX_KA_LEN);
7283ff40c12SJohn Marino }
729