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 1401264779 Lines: 208 299 69.6 %
Date: 2014-05-28 Functions: 13 14 92.9 %

          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             :         int keys_set;
      40             :         char *cid;
      41             :         size_t cid_len;
      42             : };
      43             : 
      44             : 
      45          14 : static void * eap_pax_init(struct eap_sm *sm)
      46             : {
      47             :         struct eap_pax_data *data;
      48             : 
      49          14 :         data = os_zalloc(sizeof(*data));
      50          14 :         if (data == NULL)
      51           0 :                 return NULL;
      52          14 :         data->state = PAX_STD_1;
      53             :         /*
      54             :          * TODO: make this configurable once EAP_PAX_HMAC_SHA256_128 is
      55             :          * supported
      56             :          */
      57          14 :         data->mac_id = EAP_PAX_MAC_HMAC_SHA1_128;
      58             : 
      59          14 :         return data;
      60             : }
      61             : 
      62             : 
      63          14 : static void eap_pax_reset(struct eap_sm *sm, void *priv)
      64             : {
      65          14 :         struct eap_pax_data *data = priv;
      66          14 :         os_free(data->cid);
      67          14 :         os_free(data);
      68          14 : }
      69             : 
      70             : 
      71          14 : static struct wpabuf * eap_pax_build_std_1(struct eap_sm *sm,
      72             :                                            struct eap_pax_data *data, u8 id)
      73             : {
      74             :         struct wpabuf *req;
      75             :         struct eap_pax_hdr *pax;
      76             :         u8 *pos;
      77             : 
      78          14 :         wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (sending)");
      79             : 
      80          14 :         if (random_get_bytes(data->rand.r.x, EAP_PAX_RAND_LEN)) {
      81           0 :                 wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data");
      82           0 :                 data->state = FAILURE;
      83           0 :                 return NULL;
      84             :         }
      85             : 
      86          14 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX,
      87             :                             sizeof(*pax) + 2 + EAP_PAX_RAND_LEN +
      88             :                             EAP_PAX_ICV_LEN, EAP_CODE_REQUEST, id);
      89          14 :         if (req == NULL) {
      90           0 :                 wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory "
      91             :                            "request");
      92           0 :                 data->state = FAILURE;
      93           0 :                 return NULL;
      94             :         }
      95             : 
      96          14 :         pax = wpabuf_put(req, sizeof(*pax));
      97          14 :         pax->op_code = EAP_PAX_OP_STD_1;
      98          14 :         pax->flags = 0;
      99          14 :         pax->mac_id = data->mac_id;
     100          14 :         pax->dh_group_id = EAP_PAX_DH_GROUP_NONE;
     101          14 :         pax->public_key_id = EAP_PAX_PUBLIC_KEY_NONE;
     102             : 
     103          14 :         wpabuf_put_be16(req, EAP_PAX_RAND_LEN);
     104          14 :         wpabuf_put_data(req, data->rand.r.x, EAP_PAX_RAND_LEN);
     105          14 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: A = X (server rand)",
     106          14 :                     data->rand.r.x, EAP_PAX_RAND_LEN);
     107             : 
     108          14 :         pos = wpabuf_put(req, EAP_PAX_MAC_LEN);
     109          28 :         eap_pax_mac(data->mac_id, (u8 *) "", 0,
     110          28 :                     wpabuf_mhead(req), wpabuf_len(req) - EAP_PAX_ICV_LEN,
     111             :                     NULL, 0, NULL, 0, pos);
     112          14 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN);
     113             : 
     114          14 :         return req;
     115             : }
     116             : 
     117             : 
     118          13 : static struct wpabuf * eap_pax_build_std_3(struct eap_sm *sm,
     119             :                                            struct eap_pax_data *data, u8 id)
     120             : {
     121             :         struct wpabuf *req;
     122             :         struct eap_pax_hdr *pax;
     123             :         u8 *pos;
     124             : 
     125          13 :         wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-3 (sending)");
     126             : 
     127          13 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX,
     128             :                             sizeof(*pax) + 2 + EAP_PAX_MAC_LEN +
     129             :                             EAP_PAX_ICV_LEN, EAP_CODE_REQUEST, id);
     130          13 :         if (req == NULL) {
     131           0 :                 wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory "
     132             :                            "request");
     133           0 :                 data->state = FAILURE;
     134           0 :                 return NULL;
     135             :         }
     136             : 
     137          13 :         pax = wpabuf_put(req, sizeof(*pax));
     138          13 :         pax->op_code = EAP_PAX_OP_STD_3;
     139          13 :         pax->flags = 0;
     140          13 :         pax->mac_id = data->mac_id;
     141          13 :         pax->dh_group_id = EAP_PAX_DH_GROUP_NONE;
     142          13 :         pax->public_key_id = EAP_PAX_PUBLIC_KEY_NONE;
     143             : 
     144          13 :         wpabuf_put_be16(req, EAP_PAX_MAC_LEN);
     145          13 :         pos = wpabuf_put(req, EAP_PAX_MAC_LEN);
     146          26 :         eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN,
     147          13 :                     data->rand.r.y, EAP_PAX_RAND_LEN,
     148          13 :                     (u8 *) data->cid, data->cid_len, NULL, 0, pos);
     149          13 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)",
     150             :                     pos, EAP_PAX_MAC_LEN);
     151          13 :         pos += EAP_PAX_MAC_LEN;
     152             : 
     153             :         /* Optional ADE could be added here, if needed */
     154             : 
     155          13 :         pos = wpabuf_put(req, EAP_PAX_MAC_LEN);
     156          26 :         eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
     157          26 :                     wpabuf_mhead(req), wpabuf_len(req) - EAP_PAX_ICV_LEN,
     158             :                     NULL, 0, NULL, 0, pos);
     159          13 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN);
     160             : 
     161          13 :         return req;
     162             : }
     163             : 
     164             : 
     165          27 : static struct wpabuf * eap_pax_buildReq(struct eap_sm *sm, void *priv, u8 id)
     166             : {
     167          27 :         struct eap_pax_data *data = priv;
     168             : 
     169          27 :         switch (data->state) {
     170             :         case PAX_STD_1:
     171          14 :                 return eap_pax_build_std_1(sm, data, id);
     172             :         case PAX_STD_3:
     173          13 :                 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          27 : static Boolean eap_pax_check(struct eap_sm *sm, void *priv,
     184             :                              struct wpabuf *respData)
     185             : {
     186          27 :         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          27 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len);
     193          27 :         if (pos == NULL || len < sizeof(*resp)) {
     194           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Invalid frame");
     195           0 :                 return TRUE;
     196             :         }
     197             : 
     198          27 :         mlen = sizeof(struct eap_hdr) + 1 + len;
     199          27 :         resp = (struct eap_pax_hdr *) pos;
     200             : 
     201         135 :         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         108 :                    resp->op_code, resp->flags, resp->mac_id, resp->dh_group_id,
     205          27 :                    resp->public_key_id);
     206          27 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: received payload",
     207          27 :                     (u8 *) (resp + 1), len - sizeof(*resp) - EAP_PAX_ICV_LEN);
     208             : 
     209          41 :         if (data->state == PAX_STD_1 &&
     210          14 :             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          40 :         if (data->state == PAX_STD_3 &&
     217          13 :             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          40 :         if (resp->op_code != EAP_PAX_OP_STD_2 &&
     224          13 :             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          27 :         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          27 :         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          27 :         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          27 :         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          27 :         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          27 :         if (data->keys_set) {
     261          13 :                 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          13 :                 icv = wpabuf_mhead_u8(respData) + mlen - EAP_PAX_ICV_LEN;
     266          13 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", icv, EAP_PAX_ICV_LEN);
     267          26 :                 eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
     268          13 :                             wpabuf_mhead(respData),
     269          13 :                             wpabuf_len(respData) - EAP_PAX_ICV_LEN,
     270             :                             NULL, 0, NULL, 0, icvbuf);
     271          13 :                 if (os_memcmp(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          27 :         return FALSE;
     280             : }
     281             : 
     282             : 
     283          14 : 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;
     291             :         int i;
     292             : 
     293          14 :         if (data->state != PAX_STD_1)
     294           1 :                 return;
     295             : 
     296          14 :         wpa_printf(MSG_DEBUG, "EAP-PAX: Received PAX_STD-2");
     297             : 
     298          14 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len);
     299          14 :         if (pos == NULL || len < sizeof(*resp) + EAP_PAX_ICV_LEN)
     300           0 :                 return;
     301             : 
     302          14 :         resp = (struct eap_pax_hdr *) pos;
     303          14 :         pos = (u8 *) (resp + 1);
     304          14 :         left = len - sizeof(*resp);
     305             : 
     306          28 :         if (left < 2 + EAP_PAX_RAND_LEN ||
     307          14 :             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          14 :         pos += 2;
     312          14 :         left -= 2;
     313          14 :         os_memcpy(data->rand.r.y, pos, EAP_PAX_RAND_LEN);
     314          14 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)",
     315          14 :                     data->rand.r.y, EAP_PAX_RAND_LEN);
     316          14 :         pos += EAP_PAX_RAND_LEN;
     317          14 :         left -= EAP_PAX_RAND_LEN;
     318             : 
     319          14 :         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          14 :         data->cid_len = WPA_GET_BE16(pos);
     324          14 :         os_free(data->cid);
     325          14 :         data->cid = os_malloc(data->cid_len);
     326          14 :         if (data->cid == NULL) {
     327           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Failed to allocate memory for "
     328             :                            "CID");
     329           0 :                 return;
     330             :         }
     331          14 :         os_memcpy(data->cid, pos + 2, data->cid_len);
     332          14 :         pos += 2 + data->cid_len;
     333          14 :         left -= 2 + data->cid_len;
     334          28 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID",
     335          14 :                           (u8 *) data->cid, data->cid_len);
     336             : 
     337          28 :         if (left < 2 + EAP_PAX_MAC_LEN ||
     338          14 :             WPA_GET_BE16(pos) != EAP_PAX_MAC_LEN) {
     339           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (MAC_CK)");
     340           0 :                 return;
     341             :         }
     342          14 :         pos += 2;
     343          14 :         left -= 2;
     344          14 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(A, B, CID)",
     345             :                     pos, EAP_PAX_MAC_LEN);
     346             : 
     347          14 :         if (eap_user_get(sm, (u8 *) data->cid, data->cid_len, 0) < 0) {
     348           0 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: unknown CID",
     349           0 :                                   (u8 *) data->cid, data->cid_len);
     350           0 :                 data->state = FAILURE;
     351           0 :                 return;
     352             :         }
     353             : 
     354          28 :         for (i = 0;
     355          14 :              i < EAP_MAX_METHODS &&
     356          28 :                      (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
     357          14 :                       sm->user->methods[i].method != EAP_TYPE_NONE);
     358           0 :              i++) {
     359          28 :                 if (sm->user->methods[i].vendor == EAP_VENDOR_IETF &&
     360          14 :                     sm->user->methods[i].method == EAP_TYPE_PAX)
     361          14 :                         break;
     362             :         }
     363             : 
     364          28 :         if (i >= EAP_MAX_METHODS ||
     365          28 :             sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
     366          14 :             sm->user->methods[i].method != EAP_TYPE_PAX) {
     367           0 :                 wpa_hexdump_ascii(MSG_DEBUG,
     368             :                                   "EAP-PAX: EAP-PAX not enabled for CID",
     369           0 :                                   (u8 *) data->cid, data->cid_len);
     370           0 :                 data->state = FAILURE;
     371           0 :                 return;
     372             :         }
     373             : 
     374          28 :         if (sm->user->password == NULL ||
     375          14 :             sm->user->password_len != EAP_PAX_AK_LEN) {
     376           0 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: invalid password in "
     377             :                                   "user database for CID",
     378           0 :                                   (u8 *) data->cid, data->cid_len);
     379           0 :                 data->state = FAILURE;
     380           0 :                 return;
     381             :         }
     382          14 :         os_memcpy(data->ak, sm->user->password, EAP_PAX_AK_LEN);
     383             : 
     384          14 :         if (eap_pax_initial_key_derivation(data->mac_id, data->ak,
     385          14 :                                            data->rand.e, data->mk, data->ck,
     386          14 :                                            data->ick) < 0) {
     387           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Failed to complete initial "
     388             :                            "key derivation");
     389           0 :                 data->state = FAILURE;
     390           0 :                 return;
     391             :         }
     392          14 :         data->keys_set = 1;
     393             : 
     394          28 :         eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN,
     395          14 :                     data->rand.r.x, EAP_PAX_RAND_LEN,
     396          14 :                     data->rand.r.y, EAP_PAX_RAND_LEN,
     397          14 :                     (u8 *) data->cid, data->cid_len, mac);
     398          14 :         if (os_memcmp(mac, pos, EAP_PAX_MAC_LEN) != 0) {
     399           1 :                 wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(A, B, CID) in "
     400             :                            "PAX_STD-2");
     401           1 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected MAC_CK(A, B, CID)",
     402             :                             mac, EAP_PAX_MAC_LEN);
     403           1 :                 data->state = FAILURE;
     404           1 :                 return;
     405             :         }
     406             : 
     407          13 :         pos += EAP_PAX_MAC_LEN;
     408          13 :         left -= EAP_PAX_MAC_LEN;
     409             : 
     410          13 :         if (left < EAP_PAX_ICV_LEN) {
     411           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Too short ICV (%lu) in "
     412             :                            "PAX_STD-2", (unsigned long) left);
     413           0 :                 return;
     414             :         }
     415          13 :         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN);
     416          26 :         eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
     417          13 :                     wpabuf_head(respData),
     418          13 :                     wpabuf_len(respData) - EAP_PAX_ICV_LEN, NULL, 0, NULL, 0,
     419             :                     icvbuf);
     420          13 :         if (os_memcmp(icvbuf, pos, EAP_PAX_ICV_LEN) != 0) {
     421           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV in PAX_STD-2");
     422           0 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV",
     423             :                             icvbuf, EAP_PAX_ICV_LEN);
     424           0 :                 return;
     425             :         }
     426          13 :         pos += EAP_PAX_ICV_LEN;
     427          13 :         left -= EAP_PAX_ICV_LEN;
     428             : 
     429          13 :         if (left > 0) {
     430           0 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload",
     431             :                             pos, left);
     432             :         }
     433             : 
     434          13 :         data->state = PAX_STD_3;
     435             : }
     436             : 
     437             : 
     438          13 : static void eap_pax_process_ack(struct eap_sm *sm,
     439             :                                 struct eap_pax_data *data,
     440             :                                 struct wpabuf *respData)
     441             : {
     442          13 :         if (data->state != PAX_STD_3)
     443          13 :                 return;
     444             : 
     445          13 :         wpa_printf(MSG_DEBUG, "EAP-PAX: Received PAX-ACK - authentication "
     446             :                    "completed successfully");
     447          13 :         data->state = SUCCESS;
     448             : }
     449             : 
     450             : 
     451          27 : static void eap_pax_process(struct eap_sm *sm, void *priv,
     452             :                             struct wpabuf *respData)
     453             : {
     454          27 :         struct eap_pax_data *data = priv;
     455             :         struct eap_pax_hdr *resp;
     456             :         const u8 *pos;
     457             :         size_t len;
     458             : 
     459          27 :         if (sm->user == NULL || sm->user->password == NULL) {
     460           0 :                 wpa_printf(MSG_INFO, "EAP-PAX: Plaintext password not "
     461             :                            "configured");
     462           0 :                 data->state = FAILURE;
     463           0 :                 return;
     464             :         }
     465             : 
     466          27 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len);
     467          27 :         if (pos == NULL || len < sizeof(*resp))
     468           0 :                 return;
     469             : 
     470          27 :         resp = (struct eap_pax_hdr *) pos;
     471             : 
     472          27 :         switch (resp->op_code) {
     473             :         case EAP_PAX_OP_STD_2:
     474          14 :                 eap_pax_process_std_2(sm, data, respData);
     475          14 :                 break;
     476             :         case EAP_PAX_OP_ACK:
     477          13 :                 eap_pax_process_ack(sm, data, respData);
     478          13 :                 break;
     479             :         }
     480             : }
     481             : 
     482             : 
     483          28 : static Boolean eap_pax_isDone(struct eap_sm *sm, void *priv)
     484             : {
     485          28 :         struct eap_pax_data *data = priv;
     486          28 :         return data->state == SUCCESS || data->state == FAILURE;
     487             : }
     488             : 
     489             : 
     490          14 : static u8 * eap_pax_getKey(struct eap_sm *sm, void *priv, size_t *len)
     491             : {
     492          14 :         struct eap_pax_data *data = priv;
     493             :         u8 *key;
     494             : 
     495          14 :         if (data->state != SUCCESS)
     496           1 :                 return NULL;
     497             : 
     498          13 :         key = os_malloc(EAP_MSK_LEN);
     499          13 :         if (key == NULL)
     500           0 :                 return NULL;
     501             : 
     502          13 :         *len = EAP_MSK_LEN;
     503          13 :         eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
     504          13 :                     "Master Session Key", data->rand.e, 2 * EAP_PAX_RAND_LEN,
     505             :                     EAP_MSK_LEN, key);
     506             : 
     507          13 :         return key;
     508             : }
     509             : 
     510             : 
     511           0 : static u8 * eap_pax_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
     512             : {
     513           0 :         struct eap_pax_data *data = priv;
     514             :         u8 *key;
     515             : 
     516           0 :         if (data->state != SUCCESS)
     517           0 :                 return NULL;
     518             : 
     519           0 :         key = os_malloc(EAP_EMSK_LEN);
     520           0 :         if (key == NULL)
     521           0 :                 return NULL;
     522             : 
     523           0 :         *len = EAP_EMSK_LEN;
     524           0 :         eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
     525             :                     "Extended Master Session Key",
     526           0 :                     data->rand.e, 2 * EAP_PAX_RAND_LEN,
     527             :                     EAP_EMSK_LEN, key);
     528             : 
     529           0 :         return key;
     530             : }
     531             : 
     532             : 
     533          15 : static Boolean eap_pax_isSuccess(struct eap_sm *sm, void *priv)
     534             : {
     535          15 :         struct eap_pax_data *data = priv;
     536          15 :         return data->state == SUCCESS;
     537             : }
     538             : 
     539             : 
     540           2 : int eap_server_pax_register(void)
     541             : {
     542             :         struct eap_method *eap;
     543             :         int ret;
     544             : 
     545           2 :         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
     546             :                                       EAP_VENDOR_IETF, EAP_TYPE_PAX, "PAX");
     547           2 :         if (eap == NULL)
     548           0 :                 return -1;
     549             : 
     550           2 :         eap->init = eap_pax_init;
     551           2 :         eap->reset = eap_pax_reset;
     552           2 :         eap->buildReq = eap_pax_buildReq;
     553           2 :         eap->check = eap_pax_check;
     554           2 :         eap->process = eap_pax_process;
     555           2 :         eap->isDone = eap_pax_isDone;
     556           2 :         eap->getKey = eap_pax_getKey;
     557           2 :         eap->isSuccess = eap_pax_isSuccess;
     558           2 :         eap->get_emsk = eap_pax_get_emsk;
     559             : 
     560           2 :         ret = eap_server_method_register(eap);
     561           2 :         if (ret)
     562           0 :                 eap_server_method_free(eap);
     563           2 :         return ret;
     564             : }

Generated by: LCOV version 1.10