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