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