00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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);
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
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
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
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);
00328 os_memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN);
00329 rpchannel = wpabuf_put(resp, 4 + 16 + data_len);
00330
00331
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
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 }