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