LCOV - code coverage report
Current view: top level - src/eap_server - eap_server_pax.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1422976643 Lines: 229 314 72.9 %
Date: 2015-02-03 Functions: 15 15 100.0 %

          Line data    Source code
       1             : /*
       2             :  * hostapd / EAP-PAX (RFC 4746) server
       3             :  * Copyright (c) 2005-2007, 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             : 
       9             : #include "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "crypto/random.h"
      13             : #include "eap_server/eap_i.h"
      14             : #include "eap_common/eap_pax_common.h"
      15             : 
      16             : /*
      17             :  * Note: only PAX_STD subprotocol is currently supported
      18             :  *
      19             :  * TODO: Add support with PAX_SEC with the mandatory to implement ciphersuite
      20             :  * (HMAC_SHA1_128, IANA DH Group 14 (2048 bits), RSA-PKCS1-V1_5) and
      21             :  * recommended ciphersuite (HMAC_SHA256_128, IANA DH Group 15 (3072 bits),
      22             :  * RSAES-OAEP).
      23             :  */
      24             : 
      25             : struct eap_pax_data {
      26             :         enum { PAX_STD_1, PAX_STD_3, SUCCESS, FAILURE } state;
      27             :         u8 mac_id;
      28             :         union {
      29             :                 u8 e[2 * EAP_PAX_RAND_LEN];
      30             :                 struct {
      31             :                         u8 x[EAP_PAX_RAND_LEN]; /* server rand */
      32             :                         u8 y[EAP_PAX_RAND_LEN]; /* client rand */
      33             :                 } r;
      34             :         } rand;
      35             :         u8 ak[EAP_PAX_AK_LEN];
      36             :         u8 mk[EAP_PAX_MK_LEN];
      37             :         u8 ck[EAP_PAX_CK_LEN];
      38             :         u8 ick[EAP_PAX_ICK_LEN];
      39             :         u8 mid[EAP_PAX_MID_LEN];
      40             :         int keys_set;
      41             :         char *cid;
      42             :         size_t cid_len;
      43             : };
      44             : 
      45             : 
      46          27 : static void * eap_pax_init(struct eap_sm *sm)
      47             : {
      48             :         struct eap_pax_data *data;
      49             : 
      50          27 :         data = os_zalloc(sizeof(*data));
      51          27 :         if (data == NULL)
      52           0 :                 return NULL;
      53          27 :         data->state = PAX_STD_1;
      54             :         /*
      55             :          * TODO: make this configurable once EAP_PAX_HMAC_SHA256_128 is
      56             :          * supported
      57             :          */
      58          27 :         data->mac_id = EAP_PAX_MAC_HMAC_SHA1_128;
      59             : 
      60          27 :         return data;
      61             : }
      62             : 
      63             : 
      64          27 : static void eap_pax_reset(struct eap_sm *sm, void *priv)
      65             : {
      66          27 :         struct eap_pax_data *data = priv;
      67          27 :         os_free(data->cid);
      68          27 :         bin_clear_free(data, sizeof(*data));
      69          27 : }
      70             : 
      71             : 
      72          27 : static struct wpabuf * eap_pax_build_std_1(struct eap_sm *sm,
      73             :                                            struct eap_pax_data *data, u8 id)
      74             : {
      75             :         struct wpabuf *req;
      76             :         struct eap_pax_hdr *pax;
      77             :         u8 *pos;
      78             : 
      79          27 :         wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (sending)");
      80             : 
      81          27 :         if (random_get_bytes(data->rand.r.x, EAP_PAX_RAND_LEN)) {
      82           0 :                 wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data");
      83           0 :                 data->state = FAILURE;
      84           0 :                 return NULL;
      85             :         }
      86             : 
      87          27 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX,
      88             :                             sizeof(*pax) + 2 + EAP_PAX_RAND_LEN +
      89             :                             EAP_PAX_ICV_LEN, EAP_CODE_REQUEST, id);
      90          27 :         if (req == NULL) {
      91           0 :                 wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory "
      92             :                            "request");
      93           0 :                 data->state = FAILURE;
      94           0 :                 return NULL;
      95             :         }
      96             : 
      97          27 :         pax = wpabuf_put(req, sizeof(*pax));
      98          27 :         pax->op_code = EAP_PAX_OP_STD_1;
      99          27 :         pax->flags = 0;
     100          27 :         pax->mac_id = data->mac_id;
     101          27 :         pax->dh_group_id = EAP_PAX_DH_GROUP_NONE;
     102          27 :         pax->public_key_id = EAP_PAX_PUBLIC_KEY_NONE;
     103             : 
     104          27 :         wpabuf_put_be16(req, EAP_PAX_RAND_LEN);
     105          27 :         wpabuf_put_data(req, data->rand.r.x, EAP_PAX_RAND_LEN);
     106          27 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: A = X (server rand)",
     107          27 :                     data->rand.r.x, EAP_PAX_RAND_LEN);
     108             : 
     109          27 :         pos = wpabuf_put(req, EAP_PAX_MAC_LEN);
     110          54 :         eap_pax_mac(data->mac_id, (u8 *) "", 0,
     111          54 :                     wpabuf_mhead(req), wpabuf_len(req) - EAP_PAX_ICV_LEN,
     112             :                     NULL, 0, NULL, 0, pos);
     113          27 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN);
     114             : 
     115          27 :         return req;
     116             : }
     117             : 
     118             : 
     119          26 : static struct wpabuf * eap_pax_build_std_3(struct eap_sm *sm,
     120             :                                            struct eap_pax_data *data, u8 id)
     121             : {
     122             :         struct wpabuf *req;
     123             :         struct eap_pax_hdr *pax;
     124             :         u8 *pos;
     125             : 
     126          26 :         wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-3 (sending)");
     127             : 
     128          26 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX,
     129             :                             sizeof(*pax) + 2 + EAP_PAX_MAC_LEN +
     130             :                             EAP_PAX_ICV_LEN, EAP_CODE_REQUEST, id);
     131          26 :         if (req == NULL) {
     132           0 :                 wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory "
     133             :                            "request");
     134           0 :                 data->state = FAILURE;
     135           0 :                 return NULL;
     136             :         }
     137             : 
     138          26 :         pax = wpabuf_put(req, sizeof(*pax));
     139          26 :         pax->op_code = EAP_PAX_OP_STD_3;
     140          26 :         pax->flags = 0;
     141          26 :         pax->mac_id = data->mac_id;
     142          26 :         pax->dh_group_id = EAP_PAX_DH_GROUP_NONE;
     143          26 :         pax->public_key_id = EAP_PAX_PUBLIC_KEY_NONE;
     144             : 
     145          26 :         wpabuf_put_be16(req, EAP_PAX_MAC_LEN);
     146          26 :         pos = wpabuf_put(req, EAP_PAX_MAC_LEN);
     147          52 :         eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN,
     148          26 :                     data->rand.r.y, EAP_PAX_RAND_LEN,
     149          26 :                     (u8 *) data->cid, data->cid_len, NULL, 0, pos);
     150          26 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)",
     151             :                     pos, EAP_PAX_MAC_LEN);
     152             : 
     153             :         /* Optional ADE could be added here, if needed */
     154             : 
     155          26 :         pos = wpabuf_put(req, EAP_PAX_MAC_LEN);
     156          52 :         eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
     157          52 :                     wpabuf_mhead(req), wpabuf_len(req) - EAP_PAX_ICV_LEN,
     158             :                     NULL, 0, NULL, 0, pos);
     159          26 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN);
     160             : 
     161          26 :         return req;
     162             : }
     163             : 
     164             : 
     165          53 : static struct wpabuf * eap_pax_buildReq(struct eap_sm *sm, void *priv, u8 id)
     166             : {
     167          53 :         struct eap_pax_data *data = priv;
     168             : 
     169          53 :         switch (data->state) {
     170             :         case PAX_STD_1:
     171          27 :                 return eap_pax_build_std_1(sm, data, id);
     172             :         case PAX_STD_3:
     173          26 :                 return eap_pax_build_std_3(sm, data, id);
     174             :         default:
     175           0 :                 wpa_printf(MSG_DEBUG, "EAP-PAX: Unknown state %d in buildReq",
     176           0 :                            data->state);
     177           0 :                 break;
     178             :         }
     179           0 :         return NULL;
     180             : }
     181             : 
     182             : 
     183          53 : static Boolean eap_pax_check(struct eap_sm *sm, void *priv,
     184             :                              struct wpabuf *respData)
     185             : {
     186          53 :         struct eap_pax_data *data = priv;
     187             :         struct eap_pax_hdr *resp;
     188             :         const u8 *pos;
     189             :         size_t len, mlen;
     190             :         u8 icvbuf[EAP_PAX_ICV_LEN], *icv;
     191             : 
     192          53 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len);
     193          53 :         if (pos == NULL || len < sizeof(*resp)) {
     194           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Invalid frame");
     195           0 :                 return TRUE;
     196             :         }
     197             : 
     198          53 :         mlen = sizeof(struct eap_hdr) + 1 + len;
     199          53 :         resp = (struct eap_pax_hdr *) pos;
     200             : 
     201         265 :         wpa_printf(MSG_DEBUG, "EAP-PAX: received frame: op_code 0x%x "
     202             :                    "flags 0x%x mac_id 0x%x dh_group_id 0x%x "
     203             :                    "public_key_id 0x%x",
     204         212 :                    resp->op_code, resp->flags, resp->mac_id, resp->dh_group_id,
     205          53 :                    resp->public_key_id);
     206          53 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: received payload",
     207          53 :                     (u8 *) (resp + 1), len - sizeof(*resp) - EAP_PAX_ICV_LEN);
     208             : 
     209          80 :         if (data->state == PAX_STD_1 &&
     210          27 :             resp->op_code != EAP_PAX_OP_STD_2) {
     211           0 :                 wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX_STD-2 - "
     212           0 :                            "ignore op %d", resp->op_code);
     213           0 :                 return TRUE;
     214             :         }
     215             : 
     216          79 :         if (data->state == PAX_STD_3 &&
     217          26 :             resp->op_code != EAP_PAX_OP_ACK) {
     218           0 :                 wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX-ACK - "
     219           0 :                            "ignore op %d", resp->op_code);
     220           0 :                 return TRUE;
     221             :         }
     222             : 
     223          79 :         if (resp->op_code != EAP_PAX_OP_STD_2 &&
     224          26 :             resp->op_code != EAP_PAX_OP_ACK) {
     225           0 :                 wpa_printf(MSG_DEBUG, "EAP-PAX: Unknown op_code 0x%x",
     226           0 :                            resp->op_code);
     227             :         }
     228             : 
     229          53 :         if (data->mac_id != resp->mac_id) {
     230           0 :                 wpa_printf(MSG_DEBUG, "EAP-PAX: Expected MAC ID 0x%x, "
     231           0 :                            "received 0x%x", data->mac_id, resp->mac_id);
     232           0 :                 return TRUE;
     233             :         }
     234             : 
     235          53 :         if (resp->dh_group_id != EAP_PAX_DH_GROUP_NONE) {
     236           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Expected DH Group ID 0x%x, "
     237             :                            "received 0x%x", EAP_PAX_DH_GROUP_NONE,
     238           0 :                            resp->dh_group_id);
     239           0 :                 return TRUE;
     240             :         }
     241             : 
     242          53 :         if (resp->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) {
     243           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Expected Public Key ID 0x%x, "
     244             :                            "received 0x%x", EAP_PAX_PUBLIC_KEY_NONE,
     245           0 :                            resp->public_key_id);
     246           0 :                 return TRUE;
     247             :         }
     248             : 
     249          53 :         if (resp->flags & EAP_PAX_FLAGS_MF) {
     250             :                 /* TODO: add support for reassembling fragments */
     251           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported");
     252           0 :                 return TRUE;
     253             :         }
     254             : 
     255          53 :         if (resp->flags & EAP_PAX_FLAGS_CE) {
     256           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Unexpected CE flag");
     257           0 :                 return TRUE;
     258             :         }
     259             : 
     260          53 :         if (data->keys_set) {
     261          26 :                 if (len - sizeof(*resp) < EAP_PAX_ICV_LEN) {
     262           0 :                         wpa_printf(MSG_INFO, "EAP-PAX: No ICV in the packet");
     263           0 :                         return TRUE;
     264             :                 }
     265          26 :                 icv = wpabuf_mhead_u8(respData) + mlen - EAP_PAX_ICV_LEN;
     266          26 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", icv, EAP_PAX_ICV_LEN);
     267          52 :                 eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
     268          26 :                             wpabuf_mhead(respData),
     269          26 :                             wpabuf_len(respData) - EAP_PAX_ICV_LEN,
     270             :                             NULL, 0, NULL, 0, icvbuf);
     271          26 :                 if (os_memcmp_const(icvbuf, icv, EAP_PAX_ICV_LEN) != 0) {
     272           0 :                         wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV");
     273           0 :                         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV",
     274             :                                     icvbuf, EAP_PAX_ICV_LEN);
     275           0 :                         return TRUE;
     276             :                 }
     277             :         }
     278             : 
     279          53 :         return FALSE;
     280             : }
     281             : 
     282             : 
     283          27 : static void eap_pax_process_std_2(struct eap_sm *sm,
     284             :                                   struct eap_pax_data *data,
     285             :                                   struct wpabuf *respData)
     286             : {
     287             :         struct eap_pax_hdr *resp;
     288             :         u8 mac[EAP_PAX_MAC_LEN], icvbuf[EAP_PAX_ICV_LEN];
     289             :         const u8 *pos;
     290             :         size_t len, left, cid_len;
     291             :         int i;
     292             : 
     293          27 :         if (data->state != PAX_STD_1)
     294           1 :                 return;
     295             : 
     296          27 :         wpa_printf(MSG_DEBUG, "EAP-PAX: Received PAX_STD-2");
     297             : 
     298          27 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len);
     299          27 :         if (pos == NULL || len < sizeof(*resp) + EAP_PAX_ICV_LEN)
     300           0 :                 return;
     301             : 
     302          27 :         resp = (struct eap_pax_hdr *) pos;
     303          27 :         pos = (u8 *) (resp + 1);
     304          27 :         left = len - sizeof(*resp);
     305             : 
     306          54 :         if (left < 2 + EAP_PAX_RAND_LEN ||
     307          27 :             WPA_GET_BE16(pos) != EAP_PAX_RAND_LEN) {
     308           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (B)");
     309           0 :                 return;
     310             :         }
     311          27 :         pos += 2;
     312          27 :         left -= 2;
     313          27 :         os_memcpy(data->rand.r.y, pos, EAP_PAX_RAND_LEN);
     314          27 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)",
     315          27 :                     data->rand.r.y, EAP_PAX_RAND_LEN);
     316          27 :         pos += EAP_PAX_RAND_LEN;
     317          27 :         left -= EAP_PAX_RAND_LEN;
     318             : 
     319          27 :         if (left < 2 || (size_t) 2 + WPA_GET_BE16(pos) > left) {
     320           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (CID)");
     321           0 :                 return;
     322             :         }
     323          27 :         cid_len = WPA_GET_BE16(pos);
     324          27 :         if (cid_len > 1500) {
     325           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Too long CID");
     326           0 :                 return;
     327             :         }
     328          27 :         data->cid_len = cid_len;
     329          27 :         os_free(data->cid);
     330          27 :         data->cid = os_malloc(data->cid_len);
     331          27 :         if (data->cid == NULL) {
     332           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Failed to allocate memory for "
     333             :                            "CID");
     334           0 :                 return;
     335             :         }
     336          27 :         os_memcpy(data->cid, pos + 2, data->cid_len);
     337          27 :         pos += 2 + data->cid_len;
     338          27 :         left -= 2 + data->cid_len;
     339          54 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID",
     340          27 :                           (u8 *) data->cid, data->cid_len);
     341             : 
     342          54 :         if (left < 2 + EAP_PAX_MAC_LEN ||
     343          27 :             WPA_GET_BE16(pos) != EAP_PAX_MAC_LEN) {
     344           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (MAC_CK)");
     345           0 :                 return;
     346             :         }
     347          27 :         pos += 2;
     348          27 :         left -= 2;
     349          27 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(A, B, CID)",
     350             :                     pos, EAP_PAX_MAC_LEN);
     351             : 
     352          27 :         if (eap_user_get(sm, (u8 *) data->cid, data->cid_len, 0) < 0) {
     353           0 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: unknown CID",
     354           0 :                                   (u8 *) data->cid, data->cid_len);
     355           0 :                 data->state = FAILURE;
     356           0 :                 return;
     357             :         }
     358             : 
     359          54 :         for (i = 0;
     360          27 :              i < EAP_MAX_METHODS &&
     361          54 :                      (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
     362          27 :                       sm->user->methods[i].method != EAP_TYPE_NONE);
     363           0 :              i++) {
     364          54 :                 if (sm->user->methods[i].vendor == EAP_VENDOR_IETF &&
     365          27 :                     sm->user->methods[i].method == EAP_TYPE_PAX)
     366          27 :                         break;
     367             :         }
     368             : 
     369          54 :         if (i >= EAP_MAX_METHODS ||
     370          54 :             sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
     371          27 :             sm->user->methods[i].method != EAP_TYPE_PAX) {
     372           0 :                 wpa_hexdump_ascii(MSG_DEBUG,
     373             :                                   "EAP-PAX: EAP-PAX not enabled for CID",
     374           0 :                                   (u8 *) data->cid, data->cid_len);
     375           0 :                 data->state = FAILURE;
     376           0 :                 return;
     377             :         }
     378             : 
     379          54 :         if (sm->user->password == NULL ||
     380          27 :             sm->user->password_len != EAP_PAX_AK_LEN) {
     381           0 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: invalid password in "
     382             :                                   "user database for CID",
     383           0 :                                   (u8 *) data->cid, data->cid_len);
     384           0 :                 data->state = FAILURE;
     385           0 :                 return;
     386             :         }
     387          27 :         os_memcpy(data->ak, sm->user->password, EAP_PAX_AK_LEN);
     388             : 
     389          27 :         if (eap_pax_initial_key_derivation(data->mac_id, data->ak,
     390          27 :                                            data->rand.e, data->mk, data->ck,
     391          27 :                                            data->ick, data->mid) < 0) {
     392           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Failed to complete initial "
     393             :                            "key derivation");
     394           0 :                 data->state = FAILURE;
     395           0 :                 return;
     396             :         }
     397          27 :         data->keys_set = 1;
     398             : 
     399          54 :         eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN,
     400          27 :                     data->rand.r.x, EAP_PAX_RAND_LEN,
     401          27 :                     data->rand.r.y, EAP_PAX_RAND_LEN,
     402          27 :                     (u8 *) data->cid, data->cid_len, mac);
     403          27 :         if (os_memcmp_const(mac, pos, EAP_PAX_MAC_LEN) != 0) {
     404           1 :                 wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(A, B, CID) in "
     405             :                            "PAX_STD-2");
     406           1 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected MAC_CK(A, B, CID)",
     407             :                             mac, EAP_PAX_MAC_LEN);
     408           1 :                 data->state = FAILURE;
     409           1 :                 return;
     410             :         }
     411             : 
     412          26 :         pos += EAP_PAX_MAC_LEN;
     413          26 :         left -= EAP_PAX_MAC_LEN;
     414             : 
     415          26 :         if (left < EAP_PAX_ICV_LEN) {
     416           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Too short ICV (%lu) in "
     417             :                            "PAX_STD-2", (unsigned long) left);
     418           0 :                 return;
     419             :         }
     420          26 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN);
     421          52 :         eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
     422          26 :                     wpabuf_head(respData),
     423          26 :                     wpabuf_len(respData) - EAP_PAX_ICV_LEN, NULL, 0, NULL, 0,
     424             :                     icvbuf);
     425          26 :         if (os_memcmp_const(icvbuf, pos, EAP_PAX_ICV_LEN) != 0) {
     426           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV in PAX_STD-2");
     427           0 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV",
     428             :                             icvbuf, EAP_PAX_ICV_LEN);
     429           0 :                 return;
     430             :         }
     431          26 :         pos += EAP_PAX_ICV_LEN;
     432          26 :         left -= EAP_PAX_ICV_LEN;
     433             : 
     434          26 :         if (left > 0) {
     435           0 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload",
     436             :                             pos, left);
     437             :         }
     438             : 
     439          26 :         data->state = PAX_STD_3;
     440             : }
     441             : 
     442             : 
     443          26 : static void eap_pax_process_ack(struct eap_sm *sm,
     444             :                                 struct eap_pax_data *data,
     445             :                                 struct wpabuf *respData)
     446             : {
     447          26 :         if (data->state != PAX_STD_3)
     448          26 :                 return;
     449             : 
     450          26 :         wpa_printf(MSG_DEBUG, "EAP-PAX: Received PAX-ACK - authentication "
     451             :                    "completed successfully");
     452          26 :         data->state = SUCCESS;
     453             : }
     454             : 
     455             : 
     456          53 : static void eap_pax_process(struct eap_sm *sm, void *priv,
     457             :                             struct wpabuf *respData)
     458             : {
     459          53 :         struct eap_pax_data *data = priv;
     460             :         struct eap_pax_hdr *resp;
     461             :         const u8 *pos;
     462             :         size_t len;
     463             : 
     464          53 :         if (sm->user == NULL || sm->user->password == NULL) {
     465           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Plaintext password not "
     466             :                            "configured");
     467           0 :                 data->state = FAILURE;
     468           0 :                 return;
     469             :         }
     470             : 
     471          53 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len);
     472          53 :         if (pos == NULL || len < sizeof(*resp))
     473           0 :                 return;
     474             : 
     475          53 :         resp = (struct eap_pax_hdr *) pos;
     476             : 
     477          53 :         switch (resp->op_code) {
     478             :         case EAP_PAX_OP_STD_2:
     479          27 :                 eap_pax_process_std_2(sm, data, respData);
     480          27 :                 break;
     481             :         case EAP_PAX_OP_ACK:
     482          26 :                 eap_pax_process_ack(sm, data, respData);
     483          26 :                 break;
     484             :         }
     485             : }
     486             : 
     487             : 
     488          54 : static Boolean eap_pax_isDone(struct eap_sm *sm, void *priv)
     489             : {
     490          54 :         struct eap_pax_data *data = priv;
     491          54 :         return data->state == SUCCESS || data->state == FAILURE;
     492             : }
     493             : 
     494             : 
     495          27 : static u8 * eap_pax_getKey(struct eap_sm *sm, void *priv, size_t *len)
     496             : {
     497          27 :         struct eap_pax_data *data = priv;
     498             :         u8 *key;
     499             : 
     500          27 :         if (data->state != SUCCESS)
     501           1 :                 return NULL;
     502             : 
     503          26 :         key = os_malloc(EAP_MSK_LEN);
     504          26 :         if (key == NULL)
     505           0 :                 return NULL;
     506             : 
     507          26 :         *len = EAP_MSK_LEN;
     508          26 :         eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
     509          26 :                     "Master Session Key", data->rand.e, 2 * EAP_PAX_RAND_LEN,
     510             :                     EAP_MSK_LEN, key);
     511             : 
     512          26 :         return key;
     513             : }
     514             : 
     515             : 
     516           2 : static u8 * eap_pax_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
     517             : {
     518           2 :         struct eap_pax_data *data = priv;
     519             :         u8 *key;
     520             : 
     521           2 :         if (data->state != SUCCESS)
     522           0 :                 return NULL;
     523             : 
     524           2 :         key = os_malloc(EAP_EMSK_LEN);
     525           2 :         if (key == NULL)
     526           0 :                 return NULL;
     527             : 
     528           2 :         *len = EAP_EMSK_LEN;
     529           2 :         eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
     530             :                     "Extended Master Session Key",
     531           2 :                     data->rand.e, 2 * EAP_PAX_RAND_LEN,
     532             :                     EAP_EMSK_LEN, key);
     533             : 
     534           2 :         return key;
     535             : }
     536             : 
     537             : 
     538          28 : static Boolean eap_pax_isSuccess(struct eap_sm *sm, void *priv)
     539             : {
     540          28 :         struct eap_pax_data *data = priv;
     541          28 :         return data->state == SUCCESS;
     542             : }
     543             : 
     544             : 
     545          27 : static u8 * eap_pax_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
     546             : {
     547          27 :         struct eap_pax_data *data = priv;
     548             :         u8 *sid;
     549             : 
     550          27 :         if (data->state != SUCCESS)
     551           1 :                 return NULL;
     552             : 
     553          26 :         sid = os_malloc(1 + EAP_PAX_MID_LEN);
     554          26 :         if (sid == NULL)
     555           0 :                 return NULL;
     556             : 
     557          26 :         *len = 1 + EAP_PAX_MID_LEN;
     558          26 :         sid[0] = EAP_TYPE_PAX;
     559          26 :         os_memcpy(sid + 1, data->mid, EAP_PAX_MID_LEN);
     560             : 
     561          26 :         return sid;
     562             : }
     563             : 
     564             : 
     565          10 : int eap_server_pax_register(void)
     566             : {
     567             :         struct eap_method *eap;
     568             :         int ret;
     569             : 
     570          10 :         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
     571             :                                       EAP_VENDOR_IETF, EAP_TYPE_PAX, "PAX");
     572          10 :         if (eap == NULL)
     573           0 :                 return -1;
     574             : 
     575          10 :         eap->init = eap_pax_init;
     576          10 :         eap->reset = eap_pax_reset;
     577          10 :         eap->buildReq = eap_pax_buildReq;
     578          10 :         eap->check = eap_pax_check;
     579          10 :         eap->process = eap_pax_process;
     580          10 :         eap->isDone = eap_pax_isDone;
     581          10 :         eap->getKey = eap_pax_getKey;
     582          10 :         eap->isSuccess = eap_pax_isSuccess;
     583          10 :         eap->get_emsk = eap_pax_get_emsk;
     584          10 :         eap->getSessionId = eap_pax_get_session_id;
     585             : 
     586          10 :         ret = eap_server_method_register(eap);
     587          10 :         if (ret)
     588           0 :                 eap_server_method_free(eap);
     589          10 :         return ret;
     590             : }

Generated by: LCOV version 1.10