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