eap_psk.c

Go to the documentation of this file.
00001 
00019 #include "includes.h"
00020 
00021 #include "common.h"
00022 #include "eap_server/eap_i.h"
00023 #include "aes_wrap.h"
00024 #include "eap_common/eap_psk_common.h"
00025 
00026 
00027 struct eap_psk_data {
00028         enum { PSK_1, PSK_3, SUCCESS, FAILURE } state;
00029         u8 rand_s[EAP_PSK_RAND_LEN];
00030         u8 rand_p[EAP_PSK_RAND_LEN];
00031         u8 *id_p, *id_s;
00032         size_t id_p_len, id_s_len;
00033         u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN];
00034         u8 msk[EAP_MSK_LEN];
00035         u8 emsk[EAP_EMSK_LEN];
00036 };
00037 
00038 
00039 static void * eap_psk_init(struct eap_sm *sm)
00040 {
00041         struct eap_psk_data *data;
00042 
00043         data = os_zalloc(sizeof(*data));
00044         if (data == NULL)
00045                 return NULL;
00046         data->state = PSK_1;
00047         data->id_s = (u8 *) "hostapd";
00048         data->id_s_len = 7;
00049 
00050         return data;
00051 }
00052 
00053 
00054 static void eap_psk_reset(struct eap_sm *sm, void *priv)
00055 {
00056         struct eap_psk_data *data = priv;
00057         os_free(data->id_p);
00058         os_free(data);
00059 }
00060 
00061 
00062 static struct wpabuf * eap_psk_build_1(struct eap_sm *sm,
00063                                        struct eap_psk_data *data, u8 id)
00064 {
00065         struct wpabuf *req;
00066         struct eap_psk_hdr_1 *psk;
00067 
00068         wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-1 (sending)");
00069 
00070         if (os_get_random(data->rand_s, EAP_PSK_RAND_LEN)) {
00071                 wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data");
00072                 data->state = FAILURE;
00073                 return NULL;
00074         }
00075         wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_S (server rand)",
00076                     data->rand_s, EAP_PSK_RAND_LEN);
00077 
00078         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK,
00079                             sizeof(*psk) + data->id_s_len,
00080                             EAP_CODE_REQUEST, id);
00081         if (req == NULL) {
00082                 wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory "
00083                            "request");
00084                 data->state = FAILURE;
00085                 return NULL;
00086         }
00087 
00088         psk = wpabuf_put(req, sizeof(*psk));
00089         psk->flags = EAP_PSK_FLAGS_SET_T(0); /* T=0 */
00090         os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN);
00091         wpabuf_put_data(req, data->id_s, data->id_s_len);
00092 
00093         return req;
00094 }
00095 
00096 
00097 static struct wpabuf * eap_psk_build_3(struct eap_sm *sm,
00098                                        struct eap_psk_data *data, u8 id)
00099 {
00100         struct wpabuf *req;
00101         struct eap_psk_hdr_3 *psk;
00102         u8 *buf, *pchannel, nonce[16];
00103         size_t buflen;
00104 
00105         wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-3 (sending)");
00106 
00107         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK,
00108                             sizeof(*psk) + 4 + 16 + 1, EAP_CODE_REQUEST, id);
00109         if (req == NULL) {
00110                 wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory "
00111                            "request");
00112                 data->state = FAILURE;
00113                 return NULL;
00114         }
00115 
00116         psk = wpabuf_put(req, sizeof(*psk));
00117         psk->flags = EAP_PSK_FLAGS_SET_T(2); /* T=2 */
00118         os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN);
00119 
00120         /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */
00121         buflen = data->id_s_len + EAP_PSK_RAND_LEN;
00122         buf = os_malloc(buflen);
00123         if (buf == NULL)
00124                 goto fail;
00125 
00126         os_memcpy(buf, data->id_s, data->id_s_len);
00127         os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN);
00128         if (omac1_aes_128(data->ak, buf, buflen, psk->mac_s))
00129                 goto fail;
00130         os_free(buf);
00131 
00132         if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, data->msk,
00133                                 data->emsk))
00134                 goto fail;
00135         wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN);
00136         wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN);
00137         wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN);
00138 
00139         os_memset(nonce, 0, sizeof(nonce));
00140         pchannel = wpabuf_put(req, 4 + 16 + 1);
00141         os_memcpy(pchannel, nonce + 12, 4);
00142         os_memset(pchannel + 4, 0, 16); /* Tag */
00143         pchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6;
00144         wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (plaintext)",
00145                     pchannel, 4 + 16 + 1);
00146         if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce),
00147                                 wpabuf_head(req), 22,
00148                                 pchannel + 4 + 16, 1, pchannel + 4))
00149                 goto fail;
00150         wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (encrypted)",
00151                     pchannel, 4 + 16 + 1);
00152 
00153         return req;
00154 
00155 fail:
00156         wpabuf_free(req);
00157         data->state = FAILURE;
00158         return NULL;
00159 }
00160 
00161 
00162 static struct wpabuf * eap_psk_buildReq(struct eap_sm *sm, void *priv, u8 id)
00163 {
00164         struct eap_psk_data *data = priv;
00165 
00166         switch (data->state) {
00167         case PSK_1:
00168                 return eap_psk_build_1(sm, data, id);
00169         case PSK_3:
00170                 return eap_psk_build_3(sm, data, id);
00171         default:
00172                 wpa_printf(MSG_DEBUG, "EAP-PSK: Unknown state %d in buildReq",
00173                            data->state);
00174                 break;
00175         }
00176         return NULL;
00177 }
00178 
00179 
00180 static Boolean eap_psk_check(struct eap_sm *sm, void *priv,
00181                              struct wpabuf *respData)
00182 {
00183         struct eap_psk_data *data = priv;
00184         size_t len;
00185         u8 t;
00186         const u8 *pos;
00187 
00188         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &len);
00189         if (pos == NULL || len < 1) {
00190                 wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame");
00191                 return TRUE;
00192         }
00193         t = EAP_PSK_FLAGS_GET_T(*pos);
00194 
00195         wpa_printf(MSG_DEBUG, "EAP-PSK: received frame: T=%d", t);
00196 
00197         if (data->state == PSK_1 && t != 1) {
00198                 wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-2 - "
00199                            "ignore T=%d", t);
00200                 return TRUE;
00201         }
00202 
00203         if (data->state == PSK_3 && t != 3) {
00204                 wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-4 - "
00205                            "ignore T=%d", t);
00206                 return TRUE;
00207         }
00208 
00209         if ((t == 1 && len < sizeof(struct eap_psk_hdr_2)) ||
00210             (t == 3 && len < sizeof(struct eap_psk_hdr_4))) {
00211                 wpa_printf(MSG_DEBUG, "EAP-PSK: Too short frame");
00212                 return TRUE;
00213         }
00214 
00215         return FALSE;
00216 }
00217 
00218 
00219 static void eap_psk_process_2(struct eap_sm *sm,
00220                               struct eap_psk_data *data,
00221                               struct wpabuf *respData)
00222 {
00223         const struct eap_psk_hdr_2 *resp;
00224         u8 *pos, mac[EAP_PSK_MAC_LEN], *buf;
00225         size_t left, buflen;
00226         int i;
00227         const u8 *cpos;
00228 
00229         if (data->state != PSK_1)
00230                 return;
00231 
00232         wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-2");
00233 
00234         cpos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData,
00235                                 &left);
00236         if (cpos == NULL || left < sizeof(*resp)) {
00237                 wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame");
00238                 return;
00239         }
00240         resp = (const struct eap_psk_hdr_2 *) cpos;
00241         cpos = (const u8 *) (resp + 1);
00242         left -= sizeof(*resp);
00243 
00244         os_free(data->id_p);
00245         data->id_p = os_malloc(left);
00246         if (data->id_p == NULL) {
00247                 wpa_printf(MSG_INFO, "EAP-PSK: Failed to allocate memory for "
00248                            "ID_P");
00249                 return;
00250         }
00251         os_memcpy(data->id_p, cpos, left);
00252         data->id_p_len = left;
00253         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PSK: ID_P",
00254                           data->id_p, data->id_p_len);
00255 
00256         if (eap_user_get(sm, data->id_p, data->id_p_len, 0) < 0) {
00257                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: unknown ID_P",
00258                                   data->id_p, data->id_p_len);
00259                 data->state = FAILURE;
00260                 return;
00261         }
00262 
00263         for (i = 0;
00264              i < EAP_MAX_METHODS &&
00265                      (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
00266                       sm->user->methods[i].method != EAP_TYPE_NONE);
00267              i++) {
00268                 if (sm->user->methods[i].vendor == EAP_VENDOR_IETF &&
00269                     sm->user->methods[i].method == EAP_TYPE_PSK)
00270                         break;
00271         }
00272 
00273         if (i >= EAP_MAX_METHODS ||
00274             sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
00275             sm->user->methods[i].method != EAP_TYPE_PSK) {
00276                 wpa_hexdump_ascii(MSG_DEBUG,
00277                                   "EAP-PSK: EAP-PSK not enabled for ID_P",
00278                                   data->id_p, data->id_p_len);
00279                 data->state = FAILURE;
00280                 return;
00281         }
00282 
00283         if (sm->user->password == NULL ||
00284             sm->user->password_len != EAP_PSK_PSK_LEN) {
00285                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: invalid password in "
00286                                   "user database for ID_P",
00287                                   data->id_p, data->id_p_len);
00288                 data->state = FAILURE;
00289                 return;
00290         }
00291         if (eap_psk_key_setup(sm->user->password, data->ak, data->kdk)) {
00292                 data->state = FAILURE;
00293                 return;
00294         }
00295         wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN);
00296         wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN);
00297 
00298         wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_P (client rand)",
00299                     resp->rand_p, EAP_PSK_RAND_LEN);
00300         os_memcpy(data->rand_p, resp->rand_p, EAP_PSK_RAND_LEN);
00301 
00302         /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */
00303         buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN;
00304         buf = os_malloc(buflen);
00305         if (buf == NULL) {
00306                 data->state = FAILURE;
00307                 return;
00308         }
00309         os_memcpy(buf, data->id_p, data->id_p_len);
00310         pos = buf + data->id_p_len;
00311         os_memcpy(pos, data->id_s, data->id_s_len);
00312         pos += data->id_s_len;
00313         os_memcpy(pos, data->rand_s, EAP_PSK_RAND_LEN);
00314         pos += EAP_PSK_RAND_LEN;
00315         os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN);
00316         if (omac1_aes_128(data->ak, buf, buflen, mac)) {
00317                 os_free(buf);
00318                 data->state = FAILURE;
00319                 return;
00320         }
00321         os_free(buf);
00322         wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", resp->mac_p, EAP_PSK_MAC_LEN);
00323         if (os_memcmp(mac, resp->mac_p, EAP_PSK_MAC_LEN) != 0) {
00324                 wpa_printf(MSG_INFO, "EAP-PSK: Invalid MAC_P");
00325                 wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Expected MAC_P",
00326                             mac, EAP_PSK_MAC_LEN);
00327                 data->state = FAILURE;
00328                 return;
00329         }
00330 
00331         data->state = PSK_3;
00332 }
00333 
00334 
00335 static void eap_psk_process_4(struct eap_sm *sm,
00336                               struct eap_psk_data *data,
00337                               struct wpabuf *respData)
00338 {
00339         const struct eap_psk_hdr_4 *resp;
00340         u8 *decrypted, nonce[16];
00341         size_t left;
00342         const u8 *pos, *tag;
00343 
00344         if (data->state != PSK_3)
00345                 return;
00346 
00347         wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-4");
00348 
00349         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &left);
00350         if (pos == NULL || left < sizeof(*resp)) {
00351                 wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame");
00352                 return;
00353         }
00354         resp = (const struct eap_psk_hdr_4 *) pos;
00355         pos = (const u8 *) (resp + 1);
00356         left -= sizeof(*resp);
00357 
00358         wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Encrypted PCHANNEL", pos, left);
00359 
00360         if (left < 4 + 16 + 1) {
00361                 wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in "
00362                            "PSK-4 (len=%lu, expected 21)",
00363                            (unsigned long) left);
00364                 return;
00365         }
00366 
00367         if (pos[0] == 0 && pos[1] == 0 && pos[2] == 0 && pos[3] == 0) {
00368                 wpa_printf(MSG_DEBUG, "EAP-PSK: Nonce did not increase");
00369                 return;
00370         }
00371 
00372         os_memset(nonce, 0, 12);
00373         os_memcpy(nonce + 12, pos, 4);
00374         pos += 4;
00375         left -= 4;
00376         tag = pos;
00377         pos += 16;
00378         left -= 16;
00379 
00380         decrypted = os_malloc(left);
00381         if (decrypted == NULL)
00382                 return;
00383         os_memcpy(decrypted, pos, left);
00384 
00385         if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce),
00386                                 wpabuf_head(respData), 22, decrypted, left,
00387                                 tag)) {
00388                 wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed");
00389                 os_free(decrypted);
00390                 data->state = FAILURE;
00391                 return;
00392         }
00393         wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message",
00394                     decrypted, left);
00395 
00396         /* Verify R flag */
00397         switch (decrypted[0] >> 6) {
00398         case EAP_PSK_R_FLAG_CONT:
00399                 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported");
00400                 data->state = FAILURE;
00401                 break;
00402         case EAP_PSK_R_FLAG_DONE_SUCCESS:
00403                 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS");
00404                 data->state = SUCCESS;
00405                 break;
00406         case EAP_PSK_R_FLAG_DONE_FAILURE:
00407                 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE");
00408                 data->state = FAILURE;
00409                 break;
00410         }
00411         os_free(decrypted);
00412 }
00413 
00414 
00415 static void eap_psk_process(struct eap_sm *sm, void *priv,
00416                             struct wpabuf *respData)
00417 {
00418         struct eap_psk_data *data = priv;
00419         const u8 *pos;
00420         size_t len;
00421 
00422         if (sm->user == NULL || sm->user->password == NULL) {
00423                 wpa_printf(MSG_INFO, "EAP-PSK: Plaintext password not "
00424                            "configured");
00425                 data->state = FAILURE;
00426                 return;
00427         }
00428 
00429         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &len);
00430         if (pos == NULL || len < 1)
00431                 return;
00432 
00433         switch (EAP_PSK_FLAGS_GET_T(*pos)) {
00434         case 1:
00435                 eap_psk_process_2(sm, data, respData);
00436                 break;
00437         case 3:
00438                 eap_psk_process_4(sm, data, respData);
00439                 break;
00440         }
00441 }
00442 
00443 
00444 static Boolean eap_psk_isDone(struct eap_sm *sm, void *priv)
00445 {
00446         struct eap_psk_data *data = priv;
00447         return data->state == SUCCESS || data->state == FAILURE;
00448 }
00449 
00450 
00451 static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len)
00452 {
00453         struct eap_psk_data *data = priv;
00454         u8 *key;
00455 
00456         if (data->state != SUCCESS)
00457                 return NULL;
00458 
00459         key = os_malloc(EAP_MSK_LEN);
00460         if (key == NULL)
00461                 return NULL;
00462         os_memcpy(key, data->msk, EAP_MSK_LEN);
00463         *len = EAP_MSK_LEN;
00464 
00465         return key;
00466 }
00467 
00468 
00469 static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
00470 {
00471         struct eap_psk_data *data = priv;
00472         u8 *key;
00473 
00474         if (data->state != SUCCESS)
00475                 return NULL;
00476 
00477         key = os_malloc(EAP_EMSK_LEN);
00478         if (key == NULL)
00479                 return NULL;
00480         os_memcpy(key, data->emsk, EAP_EMSK_LEN);
00481         *len = EAP_EMSK_LEN;
00482 
00483         return key;
00484 }
00485 
00486 
00487 static Boolean eap_psk_isSuccess(struct eap_sm *sm, void *priv)
00488 {
00489         struct eap_psk_data *data = priv;
00490         return data->state == SUCCESS;
00491 }
00492 
00493 
00494 int eap_server_psk_register(void)
00495 {
00496         struct eap_method *eap;
00497         int ret;
00498 
00499         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
00500                                       EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK");
00501         if (eap == NULL)
00502                 return -1;
00503 
00504         eap->init = eap_psk_init;
00505         eap->reset = eap_psk_reset;
00506         eap->buildReq = eap_psk_buildReq;
00507         eap->check = eap_psk_check;
00508         eap->process = eap_psk_process;
00509         eap->isDone = eap_psk_isDone;
00510         eap->getKey = eap_psk_getKey;
00511         eap->isSuccess = eap_psk_isSuccess;
00512         eap->get_emsk = eap_psk_get_emsk;
00513 
00514         ret = eap_server_method_register(eap);
00515         if (ret)
00516                 eap_server_method_free(eap);
00517         return ret;
00518 }
00519 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:52 2009 for hostapd by  doxygen 1.6.1