Home | History | Annotate | Download | only in wpa_supplicant
      1 /*
      2  * EAP peer method: EAP-PSK (RFC 4764)
      3  * Copyright (c) 2004-2007, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License version 2 as
      7  * published by the Free Software Foundation.
      8  *
      9  * Alternatively, this software may be distributed under the terms of BSD
     10  * license.
     11  *
     12  * See README and COPYING for more details.
     13  *
     14  * Note: EAP-PSK is an EAP authentication method and as such, completely
     15  * different from WPA-PSK. This file is not needed for WPA-PSK functionality.
     16  */
     17 
     18 #include "includes.h"
     19 
     20 #include "common.h"
     21 #include "eap_i.h"
     22 #include "config_ssid.h"
     23 #include "md5.h"
     24 #include "aes_wrap.h"
     25 #include "eap_psk_common.h"
     26 
     27 
     28 struct eap_psk_data {
     29 	enum { PSK_INIT, PSK_MAC_SENT, PSK_DONE } state;
     30 	u8 rand_p[EAP_PSK_RAND_LEN];
     31 	u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN];
     32 	u8 *id_s, *id_p;
     33 	size_t id_s_len, id_p_len;
     34 	u8 msk[EAP_MSK_LEN];
     35 	u8 emsk[EAP_EMSK_LEN];
     36 };
     37 
     38 
     39 static void * eap_psk_init(struct eap_sm *sm)
     40 {
     41 	struct wpa_ssid *config = eap_get_config(sm);
     42 	struct eap_psk_data *data;
     43 
     44 	if (config == NULL || !config->eappsk) {
     45 		wpa_printf(MSG_INFO, "EAP-PSK: pre-shared key not configured");
     46 		return NULL;
     47 	}
     48 
     49 	data = os_zalloc(sizeof(*data));
     50 	if (data == NULL)
     51 		return NULL;
     52 	eap_psk_key_setup(config->eappsk, data->ak, data->kdk);
     53 	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN);
     54 	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN);
     55 	data->state = PSK_INIT;
     56 
     57 	if (config->nai) {
     58 		data->id_p = os_malloc(config->nai_len);
     59 		if (data->id_p)
     60 			os_memcpy(data->id_p, config->nai, config->nai_len);
     61 		data->id_p_len = config->nai_len;
     62 	}
     63 	if (data->id_p == NULL) {
     64 		wpa_printf(MSG_INFO, "EAP-PSK: could not get own identity");
     65 		os_free(data);
     66 		return NULL;
     67 	}
     68 
     69 	return data;
     70 }
     71 
     72 
     73 static void eap_psk_deinit(struct eap_sm *sm, void *priv)
     74 {
     75 	struct eap_psk_data *data = priv;
     76 	os_free(data->id_s);
     77 	os_free(data->id_p);
     78 	os_free(data);
     79 }
     80 
     81 
     82 static u8 * eap_psk_process_1(struct eap_psk_data *data,
     83 			      struct eap_method_ret *ret,
     84 			      const u8 *reqData, size_t reqDataLen,
     85 			      size_t *respDataLen)
     86 {
     87 	const struct eap_psk_hdr_1 *hdr1;
     88 	struct eap_psk_hdr_2 *hdr2;
     89 	u8 *resp, *buf, *pos;
     90 	size_t buflen;
     91 
     92 	wpa_printf(MSG_DEBUG, "EAP-PSK: in INIT state");
     93 
     94 	hdr1 = (const struct eap_psk_hdr_1 *) reqData;
     95 	if (reqDataLen < sizeof(*hdr1) ||
     96 	    be_to_host16(hdr1->length) < sizeof(*hdr1) ||
     97 	    be_to_host16(hdr1->length) > reqDataLen) {
     98 		wpa_printf(MSG_INFO, "EAP-PSK: Invalid first message "
     99 			   "length (%lu %d; expected %lu or more)",
    100 			   (unsigned long) reqDataLen,
    101 			   be_to_host16(hdr1->length),
    102 			   (unsigned long) sizeof(*hdr1));
    103 		ret->ignore = TRUE;
    104 		return NULL;
    105 	}
    106 	wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr1->flags);
    107 	if (EAP_PSK_FLAGS_GET_T(hdr1->flags) != 0) {
    108 		wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 0)",
    109 			   EAP_PSK_FLAGS_GET_T(hdr1->flags));
    110 		ret->methodState = METHOD_DONE;
    111 		ret->decision = DECISION_FAIL;
    112 		return NULL;
    113 	}
    114 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr1->rand_s,
    115 		    EAP_PSK_RAND_LEN);
    116 	os_free(data->id_s);
    117 	data->id_s_len = be_to_host16(hdr1->length) - sizeof(*hdr1);
    118 	data->id_s = os_malloc(data->id_s_len);
    119 	if (data->id_s == NULL) {
    120 		wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for "
    121 			   "ID_S (len=%lu)", (unsigned long) data->id_s_len);
    122 		ret->ignore = TRUE;
    123 		return NULL;
    124 	}
    125 	os_memcpy(data->id_s, (u8 *) (hdr1 + 1), data->id_s_len);
    126 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S",
    127 			  data->id_s, data->id_s_len);
    128 
    129 	if (hostapd_get_rand(data->rand_p, EAP_PSK_RAND_LEN)) {
    130 		wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data");
    131 		ret->ignore = TRUE;
    132 		return NULL;
    133 	}
    134 
    135 	*respDataLen = sizeof(*hdr2) + data->id_p_len;
    136 	resp = os_malloc(*respDataLen);
    137 	if (resp == NULL)
    138 		return NULL;
    139 	hdr2 = (struct eap_psk_hdr_2 *) resp;
    140 	hdr2->code = EAP_CODE_RESPONSE;
    141 	hdr2->identifier = hdr1->identifier;
    142 	hdr2->length = host_to_be16(*respDataLen);
    143 	hdr2->type = EAP_TYPE_PSK;
    144 	hdr2->flags = EAP_PSK_FLAGS_SET_T(1); /* T=1 */
    145 	os_memcpy(hdr2->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN);
    146 	os_memcpy(hdr2->rand_p, data->rand_p, EAP_PSK_RAND_LEN);
    147 	os_memcpy((u8 *) (hdr2 + 1), data->id_p, data->id_p_len);
    148 	/* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */
    149 	buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN;
    150 	buf = os_malloc(buflen);
    151 	if (buf == NULL) {
    152 		os_free(resp);
    153 		return NULL;
    154 	}
    155 	os_memcpy(buf, data->id_p, data->id_p_len);
    156 	pos = buf + data->id_p_len;
    157 	os_memcpy(pos, data->id_s, data->id_s_len);
    158 	pos += data->id_s_len;
    159 	os_memcpy(pos, hdr1->rand_s, EAP_PSK_RAND_LEN);
    160 	pos += EAP_PSK_RAND_LEN;
    161 	os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN);
    162 	omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p);
    163 	os_free(buf);
    164 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_P", hdr2->rand_p,
    165 		    EAP_PSK_RAND_LEN);
    166 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", hdr2->mac_p, EAP_PSK_MAC_LEN);
    167 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_P",
    168 			  (u8 *) (hdr2 + 1), data->id_p_len);
    169 
    170 	data->state = PSK_MAC_SENT;
    171 
    172 	return resp;
    173 }
    174 
    175 
    176 static u8 * eap_psk_process_3(struct eap_psk_data *data,
    177 			      struct eap_method_ret *ret,
    178 			      const u8 *reqData, size_t reqDataLen,
    179 			      size_t *respDataLen)
    180 {
    181 	const struct eap_psk_hdr_3 *hdr3;
    182 	struct eap_psk_hdr_4 *hdr4;
    183 	u8 *resp, *buf, *rpchannel, nonce[16], *decrypted;
    184 	const u8 *pchannel, *tag, *msg;
    185 	u8 mac[EAP_PSK_MAC_LEN];
    186 	size_t buflen, left, data_len;
    187 	int failed = 0;
    188 
    189 	wpa_printf(MSG_DEBUG, "EAP-PSK: in MAC_SENT state");
    190 
    191 	hdr3 = (const struct eap_psk_hdr_3 *) reqData;
    192 	left = be_to_host16(hdr3->length);
    193 	if (left < sizeof(*hdr3) || reqDataLen < left) {
    194 		wpa_printf(MSG_INFO, "EAP-PSK: Invalid third message "
    195 			   "length (%lu %d; expected %lu)",
    196 			   (unsigned long) reqDataLen,
    197 			   be_to_host16(hdr3->length),
    198 			   (unsigned long) sizeof(*hdr3));
    199 		ret->ignore = TRUE;
    200 		return NULL;
    201 	}
    202 	left -= sizeof(*hdr3);
    203 	pchannel = (const u8 *) (hdr3 + 1);
    204 	wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr3->flags);
    205 	if (EAP_PSK_FLAGS_GET_T(hdr3->flags) != 2) {
    206 		wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 2)",
    207 			   EAP_PSK_FLAGS_GET_T(hdr3->flags));
    208 		ret->methodState = METHOD_DONE;
    209 		ret->decision = DECISION_FAIL;
    210 		return NULL;
    211 	}
    212 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr3->rand_s,
    213 		    EAP_PSK_RAND_LEN);
    214 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_S", hdr3->mac_s, EAP_PSK_MAC_LEN);
    215 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL", pchannel, left);
    216 
    217 	if (left < 4 + 16 + 1) {
    218 		wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in "
    219 			   "third message (len=%lu, expected 21)",
    220 			   (unsigned long) left);
    221 		ret->ignore = TRUE;
    222 		return NULL;
    223 	}
    224 
    225 	/* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */
    226 	buflen = data->id_s_len + EAP_PSK_RAND_LEN;
    227 	buf = os_malloc(buflen);
    228 	if (buf == NULL)
    229 		return NULL;
    230 	os_memcpy(buf, data->id_s, data->id_s_len);
    231 	os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN);
    232 	omac1_aes_128(data->ak, buf, buflen, mac);
    233 	os_free(buf);
    234 	if (os_memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) {
    235 		wpa_printf(MSG_WARNING, "EAP-PSK: Invalid MAC_S in third "
    236 			   "message");
    237 		ret->methodState = METHOD_DONE;
    238 		ret->decision = DECISION_FAIL;
    239 		return NULL;
    240 	}
    241 	wpa_printf(MSG_DEBUG, "EAP-PSK: MAC_S verified successfully");
    242 
    243 	eap_psk_derive_keys(data->kdk, data->rand_p, data->tek,
    244 			    data->msk, data->emsk);
    245 	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN);
    246 	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN);
    247 	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN);
    248 
    249 	os_memset(nonce, 0, 12);
    250 	os_memcpy(nonce + 12, pchannel, 4);
    251 	pchannel += 4;
    252 	left -= 4;
    253 
    254 	tag = pchannel;
    255 	pchannel += 16;
    256 	left -= 16;
    257 
    258 	msg = pchannel;
    259 
    260 	wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - nonce",
    261 		    nonce, sizeof(nonce));
    262 	wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - hdr", reqData, 5);
    263 	wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - cipher msg", msg, left);
    264 
    265 	decrypted = os_malloc(left);
    266 	if (decrypted == NULL) {
    267 		ret->methodState = METHOD_DONE;
    268 		ret->decision = DECISION_FAIL;
    269 		return NULL;
    270 	}
    271 	os_memcpy(decrypted, msg, left);
    272 
    273 	if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce),
    274 				reqData, 22, decrypted, left, tag)) {
    275 		wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed");
    276 		os_free(decrypted);
    277 		return NULL;
    278 	}
    279 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message",
    280 		    decrypted, left);
    281 
    282 	/* Verify R flag */
    283 	switch (decrypted[0] >> 6) {
    284 	case EAP_PSK_R_FLAG_CONT:
    285 		wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported");
    286 		failed = 1;
    287 		break;
    288 	case EAP_PSK_R_FLAG_DONE_SUCCESS:
    289 		wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS");
    290 		break;
    291 	case EAP_PSK_R_FLAG_DONE_FAILURE:
    292 		wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE");
    293 		wpa_printf(MSG_INFO, "EAP-PSK: Authentication server rejected "
    294 			   "authentication");
    295 		failed = 1;
    296 		break;
    297 	}
    298 
    299 	*respDataLen = sizeof(*hdr4) + 4 + 16 + 1;
    300 	resp = os_malloc(*respDataLen + 1);
    301 	if (resp == NULL) {
    302 		os_free(decrypted);
    303 		return NULL;
    304 	}
    305 	hdr4 = (struct eap_psk_hdr_4 *) resp;
    306 	hdr4->code = EAP_CODE_RESPONSE;
    307 	hdr4->identifier = hdr3->identifier;
    308 	hdr4->length = host_to_be16(*respDataLen);
    309 	hdr4->type = EAP_TYPE_PSK;
    310 	hdr4->flags = EAP_PSK_FLAGS_SET_T(3); /* T=3 */
    311 	os_memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN);
    312 	rpchannel = (u8 *) (hdr4 + 1);
    313 
    314 	/* nonce++ */
    315 	inc_byte_array(nonce, sizeof(nonce));
    316 	os_memcpy(rpchannel, nonce + 12, 4);
    317 
    318 	data_len = 1;
    319 	if (decrypted[0] & EAP_PSK_E_FLAG) {
    320 		wpa_printf(MSG_DEBUG, "EAP-PSK: Unsupported E (Ext) flag");
    321 		failed = 1;
    322 		rpchannel[4 + 16] = (EAP_PSK_R_FLAG_DONE_FAILURE << 6) |
    323 			EAP_PSK_E_FLAG;
    324 		if (left > 1) {
    325 			/* Add empty EXT_Payload with same EXT_Type */
    326 			(*respDataLen)++;
    327 			hdr4->length = host_to_be16(*respDataLen);
    328 			rpchannel[4 + 16 + 1] = decrypted[1];
    329 			data_len++;
    330 		}
    331 	} else if (failed)
    332 		rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_FAILURE << 6;
    333 	else
    334 		rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6;
    335 
    336 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (plaintext)",
    337 		    rpchannel + 4 + 16, data_len);
    338 	aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), resp, 22,
    339 			    rpchannel + 4 + 16, data_len, rpchannel + 4);
    340 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (PCHANNEL)",
    341 		    rpchannel, 4 + 16 + data_len);
    342 
    343 	wpa_printf(MSG_DEBUG, "EAP-PSK: Completed %ssuccessfully",
    344 		   failed ? "un" : "");
    345 	data->state = PSK_DONE;
    346 	ret->methodState = METHOD_DONE;
    347 	ret->decision = failed ? DECISION_FAIL : DECISION_UNCOND_SUCC;
    348 
    349 	os_free(decrypted);
    350 
    351 	return resp;
    352 }
    353 
    354 
    355 static u8 * eap_psk_process(struct eap_sm *sm, void *priv,
    356 			    struct eap_method_ret *ret,
    357 			    const u8 *reqData, size_t reqDataLen,
    358 			    size_t *respDataLen)
    359 {
    360 	struct eap_psk_data *data = priv;
    361 	const u8 *pos;
    362 	u8 *resp = NULL;
    363 	size_t len;
    364 
    365 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK,
    366 			       reqData, reqDataLen, &len);
    367 	if (pos == NULL) {
    368 		ret->ignore = TRUE;
    369 		return NULL;
    370 	}
    371 	len += sizeof(struct eap_hdr) + 1;
    372 
    373 	ret->ignore = FALSE;
    374 	ret->methodState = METHOD_MAY_CONT;
    375 	ret->decision = DECISION_FAIL;
    376 	ret->allowNotifications = TRUE;
    377 
    378 	switch (data->state) {
    379 	case PSK_INIT:
    380 		resp = eap_psk_process_1(data, ret, reqData, len,
    381 					 respDataLen);
    382 		break;
    383 	case PSK_MAC_SENT:
    384 		resp = eap_psk_process_3(data, ret, reqData, len,
    385 					 respDataLen);
    386 		break;
    387 	case PSK_DONE:
    388 		wpa_printf(MSG_DEBUG, "EAP-PSK: in DONE state - ignore "
    389 			   "unexpected message");
    390 		ret->ignore = TRUE;
    391 		return NULL;
    392 	}
    393 
    394 	if (ret->methodState == METHOD_DONE) {
    395 		ret->allowNotifications = FALSE;
    396 	}
    397 
    398 	return resp;
    399 }
    400 
    401 
    402 static Boolean eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv)
    403 {
    404 	struct eap_psk_data *data = priv;
    405 	return data->state == PSK_DONE;
    406 }
    407 
    408 
    409 static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len)
    410 {
    411 	struct eap_psk_data *data = priv;
    412 	u8 *key;
    413 
    414 	if (data->state != PSK_DONE)
    415 		return NULL;
    416 
    417 	key = os_malloc(EAP_MSK_LEN);
    418 	if (key == NULL)
    419 		return NULL;
    420 
    421 	*len = EAP_MSK_LEN;
    422 	os_memcpy(key, data->msk, EAP_MSK_LEN);
    423 
    424 	return key;
    425 }
    426 
    427 
    428 static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
    429 {
    430 	struct eap_psk_data *data = priv;
    431 	u8 *key;
    432 
    433 	if (data->state != PSK_DONE)
    434 		return NULL;
    435 
    436 	key = os_malloc(EAP_EMSK_LEN);
    437 	if (key == NULL)
    438 		return NULL;
    439 
    440 	*len = EAP_EMSK_LEN;
    441 	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
    442 
    443 	return key;
    444 }
    445 
    446 
    447 int eap_peer_psk_register(void)
    448 {
    449 	struct eap_method *eap;
    450 	int ret;
    451 
    452 	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
    453 				    EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK");
    454 	if (eap == NULL)
    455 		return -1;
    456 
    457 	eap->init = eap_psk_init;
    458 	eap->deinit = eap_psk_deinit;
    459 	eap->process = eap_psk_process;
    460 	eap->isKeyAvailable = eap_psk_isKeyAvailable;
    461 	eap->getKey = eap_psk_getKey;
    462 	eap->get_emsk = eap_psk_get_emsk;
    463 
    464 	ret = eap_peer_method_register(eap);
    465 	if (ret)
    466 		eap_peer_method_free(eap);
    467 	return ret;
    468 }
    469