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


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:34