$search
00001 /* 00002 * EAP peer method: EAP-PSK (RFC 4764) 00003 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 * 00014 * Note: EAP-PSK is an EAP authentication method and as such, completely 00015 * different from WPA-PSK. This file is not needed for WPA-PSK functionality. 00016 */ 00017 00018 #include "includes.h" 00019 00020 #include "common.h" 00021 #include "crypto/aes_wrap.h" 00022 #include "eap_common/eap_psk_common.h" 00023 #include "eap_i.h" 00024 00025 00026 struct eap_psk_data { 00027 enum { PSK_INIT, PSK_MAC_SENT, PSK_DONE } state; 00028 u8 rand_p[EAP_PSK_RAND_LEN]; 00029 u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN]; 00030 u8 *id_s, *id_p; 00031 size_t id_s_len, id_p_len; 00032 u8 msk[EAP_MSK_LEN]; 00033 u8 emsk[EAP_EMSK_LEN]; 00034 }; 00035 00036 00037 static void * eap_psk_init(struct eap_sm *sm) 00038 { 00039 struct eap_psk_data *data; 00040 const u8 *identity, *password; 00041 size_t identity_len, password_len; 00042 00043 password = eap_get_config_password(sm, &password_len); 00044 if (!password || password_len != 16) { 00045 wpa_printf(MSG_INFO, "EAP-PSK: 16-octet pre-shared key not " 00046 "configured"); 00047 return NULL; 00048 } 00049 00050 data = os_zalloc(sizeof(*data)); 00051 if (data == NULL) 00052 return NULL; 00053 if (eap_psk_key_setup(password, data->ak, data->kdk)) { 00054 os_free(data); 00055 return NULL; 00056 } 00057 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN); 00058 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN); 00059 data->state = PSK_INIT; 00060 00061 identity = eap_get_config_identity(sm, &identity_len); 00062 if (identity) { 00063 data->id_p = os_malloc(identity_len); 00064 if (data->id_p) 00065 os_memcpy(data->id_p, identity, identity_len); 00066 data->id_p_len = identity_len; 00067 } 00068 if (data->id_p == NULL) { 00069 wpa_printf(MSG_INFO, "EAP-PSK: could not get own identity"); 00070 os_free(data); 00071 return NULL; 00072 } 00073 00074 return data; 00075 } 00076 00077 00078 static void eap_psk_deinit(struct eap_sm *sm, void *priv) 00079 { 00080 struct eap_psk_data *data = priv; 00081 os_free(data->id_s); 00082 os_free(data->id_p); 00083 os_free(data); 00084 } 00085 00086 00087 static struct wpabuf * eap_psk_process_1(struct eap_psk_data *data, 00088 struct eap_method_ret *ret, 00089 const struct wpabuf *reqData) 00090 { 00091 const struct eap_psk_hdr_1 *hdr1; 00092 struct eap_psk_hdr_2 *hdr2; 00093 struct wpabuf *resp; 00094 u8 *buf, *pos; 00095 size_t buflen, len; 00096 const u8 *cpos; 00097 00098 wpa_printf(MSG_DEBUG, "EAP-PSK: in INIT state"); 00099 00100 cpos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, reqData, &len); 00101 hdr1 = (const struct eap_psk_hdr_1 *) cpos; 00102 if (cpos == NULL || len < sizeof(*hdr1)) { 00103 wpa_printf(MSG_INFO, "EAP-PSK: Invalid first message " 00104 "length (%lu; expected %lu or more)", 00105 (unsigned long) len, 00106 (unsigned long) sizeof(*hdr1)); 00107 ret->ignore = TRUE; 00108 return NULL; 00109 } 00110 wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr1->flags); 00111 if (EAP_PSK_FLAGS_GET_T(hdr1->flags) != 0) { 00112 wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 0)", 00113 EAP_PSK_FLAGS_GET_T(hdr1->flags)); 00114 ret->methodState = METHOD_DONE; 00115 ret->decision = DECISION_FAIL; 00116 return NULL; 00117 } 00118 wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr1->rand_s, 00119 EAP_PSK_RAND_LEN); 00120 os_free(data->id_s); 00121 data->id_s_len = len - sizeof(*hdr1); 00122 data->id_s = os_malloc(data->id_s_len); 00123 if (data->id_s == NULL) { 00124 wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for " 00125 "ID_S (len=%lu)", (unsigned long) data->id_s_len); 00126 ret->ignore = TRUE; 00127 return NULL; 00128 } 00129 os_memcpy(data->id_s, (u8 *) (hdr1 + 1), data->id_s_len); 00130 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S", 00131 data->id_s, data->id_s_len); 00132 00133 if (os_get_random(data->rand_p, EAP_PSK_RAND_LEN)) { 00134 wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); 00135 ret->ignore = TRUE; 00136 return NULL; 00137 } 00138 00139 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, 00140 sizeof(*hdr2) + data->id_p_len, EAP_CODE_RESPONSE, 00141 eap_get_id(reqData)); 00142 if (resp == NULL) 00143 return NULL; 00144 hdr2 = wpabuf_put(resp, sizeof(*hdr2)); 00145 hdr2->flags = EAP_PSK_FLAGS_SET_T(1); /* T=1 */ 00146 os_memcpy(hdr2->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN); 00147 os_memcpy(hdr2->rand_p, data->rand_p, EAP_PSK_RAND_LEN); 00148 wpabuf_put_data(resp, data->id_p, data->id_p_len); 00149 /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */ 00150 buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN; 00151 buf = os_malloc(buflen); 00152 if (buf == NULL) { 00153 wpabuf_free(resp); 00154 return NULL; 00155 } 00156 os_memcpy(buf, data->id_p, data->id_p_len); 00157 pos = buf + data->id_p_len; 00158 os_memcpy(pos, data->id_s, data->id_s_len); 00159 pos += data->id_s_len; 00160 os_memcpy(pos, hdr1->rand_s, EAP_PSK_RAND_LEN); 00161 pos += EAP_PSK_RAND_LEN; 00162 os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN); 00163 if (omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p)) { 00164 os_free(buf); 00165 wpabuf_free(resp); 00166 return NULL; 00167 } 00168 os_free(buf); 00169 wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_P", hdr2->rand_p, 00170 EAP_PSK_RAND_LEN); 00171 wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", hdr2->mac_p, EAP_PSK_MAC_LEN); 00172 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_P", 00173 data->id_p, data->id_p_len); 00174 00175 data->state = PSK_MAC_SENT; 00176 00177 return resp; 00178 } 00179 00180 00181 static struct wpabuf * eap_psk_process_3(struct eap_psk_data *data, 00182 struct eap_method_ret *ret, 00183 const struct wpabuf *reqData) 00184 { 00185 const struct eap_psk_hdr_3 *hdr3; 00186 struct eap_psk_hdr_4 *hdr4; 00187 struct wpabuf *resp; 00188 u8 *buf, *rpchannel, nonce[16], *decrypted; 00189 const u8 *pchannel, *tag, *msg; 00190 u8 mac[EAP_PSK_MAC_LEN]; 00191 size_t buflen, left, data_len, len, plen; 00192 int failed = 0; 00193 const u8 *pos; 00194 00195 wpa_printf(MSG_DEBUG, "EAP-PSK: in MAC_SENT state"); 00196 00197 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, 00198 reqData, &len); 00199 hdr3 = (const struct eap_psk_hdr_3 *) pos; 00200 if (pos == NULL || len < sizeof(*hdr3)) { 00201 wpa_printf(MSG_INFO, "EAP-PSK: Invalid third message " 00202 "length (%lu; expected %lu or more)", 00203 (unsigned long) len, 00204 (unsigned long) sizeof(*hdr3)); 00205 ret->ignore = TRUE; 00206 return NULL; 00207 } 00208 left = len - sizeof(*hdr3); 00209 pchannel = (const u8 *) (hdr3 + 1); 00210 wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr3->flags); 00211 if (EAP_PSK_FLAGS_GET_T(hdr3->flags) != 2) { 00212 wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 2)", 00213 EAP_PSK_FLAGS_GET_T(hdr3->flags)); 00214 ret->methodState = METHOD_DONE; 00215 ret->decision = DECISION_FAIL; 00216 return NULL; 00217 } 00218 wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr3->rand_s, 00219 EAP_PSK_RAND_LEN); 00220 wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_S", hdr3->mac_s, EAP_PSK_MAC_LEN); 00221 wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL", pchannel, left); 00222 00223 if (left < 4 + 16 + 1) { 00224 wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " 00225 "third message (len=%lu, expected 21)", 00226 (unsigned long) left); 00227 ret->ignore = TRUE; 00228 return NULL; 00229 } 00230 00231 /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */ 00232 buflen = data->id_s_len + EAP_PSK_RAND_LEN; 00233 buf = os_malloc(buflen); 00234 if (buf == NULL) 00235 return NULL; 00236 os_memcpy(buf, data->id_s, data->id_s_len); 00237 os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN); 00238 if (omac1_aes_128(data->ak, buf, buflen, mac)) { 00239 os_free(buf); 00240 return NULL; 00241 } 00242 os_free(buf); 00243 if (os_memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) { 00244 wpa_printf(MSG_WARNING, "EAP-PSK: Invalid MAC_S in third " 00245 "message"); 00246 ret->methodState = METHOD_DONE; 00247 ret->decision = DECISION_FAIL; 00248 return NULL; 00249 } 00250 wpa_printf(MSG_DEBUG, "EAP-PSK: MAC_S verified successfully"); 00251 00252 if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, 00253 data->msk, data->emsk)) { 00254 ret->methodState = METHOD_DONE; 00255 ret->decision = DECISION_FAIL; 00256 return NULL; 00257 } 00258 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN); 00259 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN); 00260 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN); 00261 00262 os_memset(nonce, 0, 12); 00263 os_memcpy(nonce + 12, pchannel, 4); 00264 pchannel += 4; 00265 left -= 4; 00266 00267 tag = pchannel; 00268 pchannel += 16; 00269 left -= 16; 00270 00271 msg = pchannel; 00272 00273 wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - nonce", 00274 nonce, sizeof(nonce)); 00275 wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - hdr", 00276 wpabuf_head(reqData), 5); 00277 wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - cipher msg", msg, left); 00278 00279 decrypted = os_malloc(left); 00280 if (decrypted == NULL) { 00281 ret->methodState = METHOD_DONE; 00282 ret->decision = DECISION_FAIL; 00283 return NULL; 00284 } 00285 os_memcpy(decrypted, msg, left); 00286 00287 if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), 00288 wpabuf_head(reqData), 00289 sizeof(struct eap_hdr) + 1 + 00290 sizeof(*hdr3) - EAP_PSK_MAC_LEN, decrypted, 00291 left, tag)) { 00292 wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed"); 00293 os_free(decrypted); 00294 return NULL; 00295 } 00296 wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message", 00297 decrypted, left); 00298 00299 /* Verify R flag */ 00300 switch (decrypted[0] >> 6) { 00301 case EAP_PSK_R_FLAG_CONT: 00302 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported"); 00303 failed = 1; 00304 break; 00305 case EAP_PSK_R_FLAG_DONE_SUCCESS: 00306 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS"); 00307 break; 00308 case EAP_PSK_R_FLAG_DONE_FAILURE: 00309 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE"); 00310 wpa_printf(MSG_INFO, "EAP-PSK: Authentication server rejected " 00311 "authentication"); 00312 failed = 1; 00313 break; 00314 } 00315 00316 data_len = 1; 00317 if ((decrypted[0] & EAP_PSK_E_FLAG) && left > 1) 00318 data_len++; 00319 plen = sizeof(*hdr4) + 4 + 16 + data_len; 00320 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, plen, 00321 EAP_CODE_RESPONSE, eap_get_id(reqData)); 00322 if (resp == NULL) { 00323 os_free(decrypted); 00324 return NULL; 00325 } 00326 hdr4 = wpabuf_put(resp, sizeof(*hdr4)); 00327 hdr4->flags = EAP_PSK_FLAGS_SET_T(3); /* T=3 */ 00328 os_memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN); 00329 rpchannel = wpabuf_put(resp, 4 + 16 + data_len); 00330 00331 /* nonce++ */ 00332 inc_byte_array(nonce, sizeof(nonce)); 00333 os_memcpy(rpchannel, nonce + 12, 4); 00334 00335 if (decrypted[0] & EAP_PSK_E_FLAG) { 00336 wpa_printf(MSG_DEBUG, "EAP-PSK: Unsupported E (Ext) flag"); 00337 failed = 1; 00338 rpchannel[4 + 16] = (EAP_PSK_R_FLAG_DONE_FAILURE << 6) | 00339 EAP_PSK_E_FLAG; 00340 if (left > 1) { 00341 /* Add empty EXT_Payload with same EXT_Type */ 00342 rpchannel[4 + 16 + 1] = decrypted[1]; 00343 } 00344 } else if (failed) 00345 rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_FAILURE << 6; 00346 else 00347 rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6; 00348 00349 wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (plaintext)", 00350 rpchannel + 4 + 16, data_len); 00351 if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), 00352 wpabuf_head(resp), 00353 sizeof(struct eap_hdr) + 1 + sizeof(*hdr4), 00354 rpchannel + 4 + 16, data_len, rpchannel + 4)) { 00355 os_free(decrypted); 00356 wpabuf_free(resp); 00357 return NULL; 00358 } 00359 wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (PCHANNEL)", 00360 rpchannel, 4 + 16 + data_len); 00361 00362 wpa_printf(MSG_DEBUG, "EAP-PSK: Completed %ssuccessfully", 00363 failed ? "un" : ""); 00364 data->state = PSK_DONE; 00365 ret->methodState = METHOD_DONE; 00366 ret->decision = failed ? DECISION_FAIL : DECISION_UNCOND_SUCC; 00367 00368 os_free(decrypted); 00369 00370 return resp; 00371 } 00372 00373 00374 static struct wpabuf * eap_psk_process(struct eap_sm *sm, void *priv, 00375 struct eap_method_ret *ret, 00376 const struct wpabuf *reqData) 00377 { 00378 struct eap_psk_data *data = priv; 00379 const u8 *pos; 00380 struct wpabuf *resp = NULL; 00381 size_t len; 00382 00383 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, reqData, &len); 00384 if (pos == NULL) { 00385 ret->ignore = TRUE; 00386 return NULL; 00387 } 00388 00389 ret->ignore = FALSE; 00390 ret->methodState = METHOD_MAY_CONT; 00391 ret->decision = DECISION_FAIL; 00392 ret->allowNotifications = TRUE; 00393 00394 switch (data->state) { 00395 case PSK_INIT: 00396 resp = eap_psk_process_1(data, ret, reqData); 00397 break; 00398 case PSK_MAC_SENT: 00399 resp = eap_psk_process_3(data, ret, reqData); 00400 break; 00401 case PSK_DONE: 00402 wpa_printf(MSG_DEBUG, "EAP-PSK: in DONE state - ignore " 00403 "unexpected message"); 00404 ret->ignore = TRUE; 00405 return NULL; 00406 } 00407 00408 if (ret->methodState == METHOD_DONE) { 00409 ret->allowNotifications = FALSE; 00410 } 00411 00412 return resp; 00413 } 00414 00415 00416 static Boolean eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv) 00417 { 00418 struct eap_psk_data *data = priv; 00419 return data->state == PSK_DONE; 00420 } 00421 00422 00423 static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len) 00424 { 00425 struct eap_psk_data *data = priv; 00426 u8 *key; 00427 00428 if (data->state != PSK_DONE) 00429 return NULL; 00430 00431 key = os_malloc(EAP_MSK_LEN); 00432 if (key == NULL) 00433 return NULL; 00434 00435 *len = EAP_MSK_LEN; 00436 os_memcpy(key, data->msk, EAP_MSK_LEN); 00437 00438 return key; 00439 } 00440 00441 00442 static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 00443 { 00444 struct eap_psk_data *data = priv; 00445 u8 *key; 00446 00447 if (data->state != PSK_DONE) 00448 return NULL; 00449 00450 key = os_malloc(EAP_EMSK_LEN); 00451 if (key == NULL) 00452 return NULL; 00453 00454 *len = EAP_EMSK_LEN; 00455 os_memcpy(key, data->emsk, EAP_EMSK_LEN); 00456 00457 return key; 00458 } 00459 00460 00461 int eap_peer_psk_register(void) 00462 { 00463 struct eap_method *eap; 00464 int ret; 00465 00466 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 00467 EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK"); 00468 if (eap == NULL) 00469 return -1; 00470 00471 eap->init = eap_psk_init; 00472 eap->deinit = eap_psk_deinit; 00473 eap->process = eap_psk_process; 00474 eap->isKeyAvailable = eap_psk_isKeyAvailable; 00475 eap->getKey = eap_psk_getKey; 00476 eap->get_emsk = eap_psk_get_emsk; 00477 00478 ret = eap_peer_method_register(eap); 00479 if (ret) 00480 eap_peer_method_free(eap); 00481 return ret; 00482 }