LCOV - code coverage report
Current view: top level - src/eap_server - eap_server_gpsk.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1422976643 Lines: 243 363 66.9 %
Date: 2015-02-03 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /*
       2             :  * hostapd / EAP-GPSK (RFC 5433) server
       3             :  * Copyright (c) 2006-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_gpsk_common.h"
      15             : 
      16             : 
      17             : struct eap_gpsk_data {
      18             :         enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state;
      19             :         u8 rand_server[EAP_GPSK_RAND_LEN];
      20             :         u8 rand_peer[EAP_GPSK_RAND_LEN];
      21             :         u8 msk[EAP_MSK_LEN];
      22             :         u8 emsk[EAP_EMSK_LEN];
      23             :         u8 sk[EAP_GPSK_MAX_SK_LEN];
      24             :         size_t sk_len;
      25             :         u8 pk[EAP_GPSK_MAX_PK_LEN];
      26             :         size_t pk_len;
      27             :         u8 session_id[128];
      28             :         size_t id_len;
      29             :         u8 *id_peer;
      30             :         size_t id_peer_len;
      31             : #define MAX_NUM_CSUITES 2
      32             :         struct eap_gpsk_csuite csuite_list[MAX_NUM_CSUITES];
      33             :         size_t csuite_count;
      34             :         int vendor; /* CSuite/Vendor */
      35             :         int specifier; /* CSuite/Specifier */
      36             : };
      37             : 
      38             : 
      39        1052 : static const char * eap_gpsk_state_txt(int state)
      40             : {
      41        1052 :         switch (state) {
      42             :         case GPSK_1:
      43         266 :                 return "GPSK-1";
      44             :         case GPSK_3:
      45         525 :                 return "GPSK-3";
      46             :         case SUCCESS:
      47         260 :                 return "SUCCESS";
      48             :         case FAILURE:
      49           1 :                 return "FAILURE";
      50             :         default:
      51           0 :                 return "?";
      52             :         }
      53             : }
      54             : 
      55             : 
      56         526 : static void eap_gpsk_state(struct eap_gpsk_data *data, int state)
      57             : {
      58        1052 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s",
      59         526 :                    eap_gpsk_state_txt(data->state),
      60             :                    eap_gpsk_state_txt(state));
      61         526 :         data->state = state;
      62         526 : }
      63             : 
      64             : 
      65         277 : static void * eap_gpsk_init(struct eap_sm *sm)
      66             : {
      67             :         struct eap_gpsk_data *data;
      68             : 
      69         277 :         data = os_zalloc(sizeof(*data));
      70         277 :         if (data == NULL)
      71           0 :                 return NULL;
      72         277 :         data->state = GPSK_1;
      73             : 
      74         277 :         data->csuite_count = 0;
      75         277 :         if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF,
      76             :                                            EAP_GPSK_CIPHER_AES)) {
      77         277 :                 WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor,
      78             :                              EAP_GPSK_VENDOR_IETF);
      79         277 :                 WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier,
      80             :                              EAP_GPSK_CIPHER_AES);
      81         277 :                 data->csuite_count++;
      82             :         }
      83         277 :         if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF,
      84             :                                            EAP_GPSK_CIPHER_SHA256)) {
      85         277 :                 WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor,
      86             :                              EAP_GPSK_VENDOR_IETF);
      87         277 :                 WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier,
      88             :                              EAP_GPSK_CIPHER_SHA256);
      89         277 :                 data->csuite_count++;
      90             :         }
      91             : 
      92         277 :         return data;
      93             : }
      94             : 
      95             : 
      96         277 : static void eap_gpsk_reset(struct eap_sm *sm, void *priv)
      97             : {
      98         277 :         struct eap_gpsk_data *data = priv;
      99         277 :         os_free(data->id_peer);
     100         277 :         bin_clear_free(data, sizeof(*data));
     101         277 : }
     102             : 
     103             : 
     104         277 : static struct wpabuf * eap_gpsk_build_gpsk_1(struct eap_sm *sm,
     105             :                                              struct eap_gpsk_data *data, u8 id)
     106             : {
     107             :         size_t len;
     108             :         struct wpabuf *req;
     109             : 
     110         277 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-1");
     111             : 
     112         277 :         if (random_get_bytes(data->rand_server, EAP_GPSK_RAND_LEN)) {
     113           0 :                 wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to get random data");
     114           0 :                 eap_gpsk_state(data, FAILURE);
     115           0 :                 return NULL;
     116             :         }
     117         277 :         wpa_hexdump(MSG_MSGDUMP, "EAP-GPSK: RAND_Server",
     118         277 :                     data->rand_server, EAP_GPSK_RAND_LEN);
     119             : 
     120         554 :         len = 1 + 2 + sm->server_id_len + EAP_GPSK_RAND_LEN + 2 +
     121         277 :                 data->csuite_count * sizeof(struct eap_gpsk_csuite);
     122         277 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
     123             :                             EAP_CODE_REQUEST, id);
     124         277 :         if (req == NULL) {
     125           0 :                 wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory "
     126             :                            "for request/GPSK-1");
     127           0 :                 eap_gpsk_state(data, FAILURE);
     128           0 :                 return NULL;
     129             :         }
     130             : 
     131         277 :         wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_1);
     132         277 :         wpabuf_put_be16(req, sm->server_id_len);
     133         277 :         wpabuf_put_data(req, sm->server_id, sm->server_id_len);
     134         277 :         wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
     135         277 :         wpabuf_put_be16(req,
     136         277 :                         data->csuite_count * sizeof(struct eap_gpsk_csuite));
     137         277 :         wpabuf_put_data(req, data->csuite_list,
     138         277 :                         data->csuite_count * sizeof(struct eap_gpsk_csuite));
     139             : 
     140         277 :         return req;
     141             : }
     142             : 
     143             : 
     144         265 : static struct wpabuf * eap_gpsk_build_gpsk_3(struct eap_sm *sm,
     145             :                                              struct eap_gpsk_data *data, u8 id)
     146             : {
     147             :         u8 *pos, *start;
     148             :         size_t len, miclen;
     149             :         struct eap_gpsk_csuite *csuite;
     150             :         struct wpabuf *req;
     151             : 
     152         265 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-3");
     153             : 
     154         265 :         miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
     155         530 :         len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + sm->server_id_len +
     156         265 :                 sizeof(struct eap_gpsk_csuite) + 2 + miclen;
     157         265 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
     158             :                             EAP_CODE_REQUEST, id);
     159         265 :         if (req == NULL) {
     160           0 :                 wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory "
     161             :                            "for request/GPSK-3");
     162           0 :                 eap_gpsk_state(data, FAILURE);
     163           0 :                 return NULL;
     164             :         }
     165             : 
     166         265 :         wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_3);
     167         265 :         start = wpabuf_put(req, 0);
     168             : 
     169         265 :         wpabuf_put_data(req, data->rand_peer, EAP_GPSK_RAND_LEN);
     170         265 :         wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
     171         265 :         wpabuf_put_be16(req, sm->server_id_len);
     172         265 :         wpabuf_put_data(req, sm->server_id, sm->server_id_len);
     173         265 :         csuite = wpabuf_put(req, sizeof(*csuite));
     174         265 :         WPA_PUT_BE32(csuite->vendor, data->vendor);
     175         265 :         WPA_PUT_BE16(csuite->specifier, data->specifier);
     176             : 
     177             :         /* no PD_Payload_2 */
     178         265 :         wpabuf_put_be16(req, 0);
     179             : 
     180         265 :         pos = wpabuf_put(req, miclen);
     181         265 :         if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
     182         265 :                                  data->specifier, start, pos - start, pos) < 0)
     183             :         {
     184           0 :                 os_free(req);
     185           0 :                 eap_gpsk_state(data, FAILURE);
     186           0 :                 return NULL;
     187             :         }
     188             : 
     189         265 :         return req;
     190             : }
     191             : 
     192             : 
     193         542 : static struct wpabuf * eap_gpsk_buildReq(struct eap_sm *sm, void *priv, u8 id)
     194             : {
     195         542 :         struct eap_gpsk_data *data = priv;
     196             : 
     197         542 :         switch (data->state) {
     198             :         case GPSK_1:
     199         277 :                 return eap_gpsk_build_gpsk_1(sm, data, id);
     200             :         case GPSK_3:
     201         265 :                 return eap_gpsk_build_gpsk_3(sm, data, id);
     202             :         default:
     203           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown state %d in buildReq",
     204           0 :                            data->state);
     205           0 :                 break;
     206             :         }
     207           0 :         return NULL;
     208             : }
     209             : 
     210             : 
     211         526 : static Boolean eap_gpsk_check(struct eap_sm *sm, void *priv,
     212             :                               struct wpabuf *respData)
     213             : {
     214         526 :         struct eap_gpsk_data *data = priv;
     215             :         const u8 *pos;
     216             :         size_t len;
     217             : 
     218         526 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len);
     219         526 :         if (pos == NULL || len < 1) {
     220           0 :                 wpa_printf(MSG_INFO, "EAP-GPSK: Invalid frame");
     221           0 :                 return TRUE;
     222             :         }
     223             : 
     224         526 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode=%d", *pos);
     225             : 
     226         526 :         if (data->state == GPSK_1 && *pos == EAP_GPSK_OPCODE_GPSK_2)
     227         266 :                 return FALSE;
     228             : 
     229         260 :         if (data->state == GPSK_3 && *pos == EAP_GPSK_OPCODE_GPSK_4)
     230         260 :                 return FALSE;
     231             : 
     232           0 :         wpa_printf(MSG_INFO, "EAP-GPSK: Unexpected opcode=%d in state=%d",
     233           0 :                    *pos, data->state);
     234             : 
     235           0 :         return TRUE;
     236             : }
     237             : 
     238             : 
     239         266 : static void eap_gpsk_process_gpsk_2(struct eap_sm *sm,
     240             :                                     struct eap_gpsk_data *data,
     241             :                                     const u8 *payload, size_t payloadlen)
     242             : {
     243             :         const u8 *pos, *end;
     244             :         u16 alen;
     245             :         const struct eap_gpsk_csuite *csuite;
     246             :         size_t i, miclen;
     247             :         u8 mic[EAP_GPSK_MAX_MIC_LEN];
     248             : 
     249         266 :         if (data->state != GPSK_1)
     250           1 :                 return;
     251             : 
     252         266 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-2");
     253             : 
     254         266 :         pos = payload;
     255         266 :         end = payload + payloadlen;
     256             : 
     257         266 :         if (end - pos < 2) {
     258           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
     259             :                            "ID_Peer length");
     260           0 :                 eap_gpsk_state(data, FAILURE);
     261           0 :                 return;
     262             :         }
     263         266 :         alen = WPA_GET_BE16(pos);
     264         266 :         pos += 2;
     265         266 :         if (end - pos < alen) {
     266           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
     267             :                            "ID_Peer");
     268           0 :                 eap_gpsk_state(data, FAILURE);
     269           0 :                 return;
     270             :         }
     271         266 :         os_free(data->id_peer);
     272         266 :         data->id_peer = os_malloc(alen);
     273         266 :         if (data->id_peer == NULL) {
     274           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Not enough memory to store "
     275             :                            "%d-octet ID_Peer", alen);
     276           0 :                 return;
     277             :         }
     278         266 :         os_memcpy(data->id_peer, pos, alen);
     279         266 :         data->id_peer_len = alen;
     280         532 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer",
     281         266 :                           data->id_peer, data->id_peer_len);
     282         266 :         pos += alen;
     283             : 
     284         266 :         if (end - pos < 2) {
     285           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
     286             :                            "ID_Server length");
     287           0 :                 eap_gpsk_state(data, FAILURE);
     288           0 :                 return;
     289             :         }
     290         266 :         alen = WPA_GET_BE16(pos);
     291         266 :         pos += 2;
     292         266 :         if (end - pos < alen) {
     293           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
     294             :                            "ID_Server");
     295           0 :                 eap_gpsk_state(data, FAILURE);
     296           0 :                 return;
     297             :         }
     298         532 :         if (alen != sm->server_id_len ||
     299         266 :             os_memcmp(pos, sm->server_id, alen) != 0) {
     300           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1 and "
     301             :                            "GPSK-2 did not match");
     302           0 :                 eap_gpsk_state(data, FAILURE);
     303           0 :                 return;
     304             :         }
     305         266 :         pos += alen;
     306             : 
     307         266 :         if (end - pos < EAP_GPSK_RAND_LEN) {
     308           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
     309             :                            "RAND_Peer");
     310           0 :                 eap_gpsk_state(data, FAILURE);
     311           0 :                 return;
     312             :         }
     313         266 :         os_memcpy(data->rand_peer, pos, EAP_GPSK_RAND_LEN);
     314         266 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer",
     315         266 :                     data->rand_peer, EAP_GPSK_RAND_LEN);
     316         266 :         pos += EAP_GPSK_RAND_LEN;
     317             : 
     318         266 :         if (end - pos < EAP_GPSK_RAND_LEN) {
     319           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
     320             :                            "RAND_Server");
     321           0 :                 eap_gpsk_state(data, FAILURE);
     322           0 :                 return;
     323             :         }
     324         266 :         if (os_memcmp(data->rand_server, pos, EAP_GPSK_RAND_LEN) != 0) {
     325           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and "
     326             :                            "GPSK-2 did not match");
     327           0 :                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1",
     328           0 :                             data->rand_server, EAP_GPSK_RAND_LEN);
     329           0 :                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-2",
     330             :                             pos, EAP_GPSK_RAND_LEN);
     331           0 :                 eap_gpsk_state(data, FAILURE);
     332           0 :                 return;
     333             :         }
     334         266 :         pos += EAP_GPSK_RAND_LEN;
     335             : 
     336         266 :         if (end - pos < 2) {
     337           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
     338             :                            "CSuite_List length");
     339           0 :                 eap_gpsk_state(data, FAILURE);
     340           0 :                 return;
     341             :         }
     342         266 :         alen = WPA_GET_BE16(pos);
     343         266 :         pos += 2;
     344         266 :         if (end - pos < alen) {
     345           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
     346             :                            "CSuite_List");
     347           0 :                 eap_gpsk_state(data, FAILURE);
     348           0 :                 return;
     349             :         }
     350         532 :         if (alen != data->csuite_count * sizeof(struct eap_gpsk_csuite) ||
     351         266 :             os_memcmp(pos, data->csuite_list, alen) != 0) {
     352           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List in GPSK-1 and "
     353             :                            "GPSK-2 did not match");
     354           0 :                 eap_gpsk_state(data, FAILURE);
     355           0 :                 return;
     356             :         }
     357         266 :         pos += alen;
     358             : 
     359         266 :         if (end - pos < (int) sizeof(*csuite)) {
     360           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
     361             :                            "CSuite_Sel");
     362           0 :                 eap_gpsk_state(data, FAILURE);
     363           0 :                 return;
     364             :         }
     365         266 :         csuite = (const struct eap_gpsk_csuite *) pos;
     366         267 :         for (i = 0; i < data->csuite_count; i++) {
     367         267 :                 if (os_memcmp(csuite, &data->csuite_list[i], sizeof(*csuite))
     368             :                     == 0)
     369         266 :                         break;
     370             :         }
     371         266 :         if (i == data->csuite_count) {
     372           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Peer selected unsupported "
     373             :                            "ciphersuite %d:%d",
     374           0 :                            WPA_GET_BE32(csuite->vendor),
     375           0 :                            WPA_GET_BE16(csuite->specifier));
     376           0 :                 eap_gpsk_state(data, FAILURE);
     377           0 :                 return;
     378             :         }
     379         266 :         data->vendor = WPA_GET_BE32(csuite->vendor);
     380         266 :         data->specifier = WPA_GET_BE16(csuite->specifier);
     381         266 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel %d:%d",
     382             :                    data->vendor, data->specifier);
     383         266 :         pos += sizeof(*csuite); 
     384             : 
     385         266 :         if (end - pos < 2) {
     386           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
     387             :                            "PD_Payload_1 length");
     388           0 :                 eap_gpsk_state(data, FAILURE);
     389           0 :                 return;
     390             :         }
     391         266 :         alen = WPA_GET_BE16(pos);
     392         266 :         pos += 2;
     393         266 :         if (end - pos < alen) {
     394           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
     395             :                            "PD_Payload_1");
     396           0 :                 eap_gpsk_state(data, FAILURE);
     397           0 :                 return;
     398             :         }
     399         266 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen);
     400         266 :         pos += alen;
     401             : 
     402         266 :         if (sm->user == NULL || sm->user->password == NULL) {
     403           0 :                 wpa_printf(MSG_INFO, "EAP-GPSK: No PSK/password configured "
     404             :                            "for the user");
     405           0 :                 eap_gpsk_state(data, FAILURE);
     406           0 :                 return;
     407             :         }
     408             : 
     409        1064 :         if (eap_gpsk_derive_keys(sm->user->password, sm->user->password_len,
     410             :                                  data->vendor, data->specifier,
     411         266 :                                  data->rand_peer, data->rand_server,
     412         266 :                                  data->id_peer, data->id_peer_len,
     413             :                                  sm->server_id, sm->server_id_len,
     414         266 :                                  data->msk, data->emsk,
     415         266 :                                  data->sk, &data->sk_len,
     416         266 :                                  data->pk, &data->pk_len) < 0) {
     417           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys");
     418           0 :                 eap_gpsk_state(data, FAILURE);
     419           0 :                 return;
     420             :         }
     421             : 
     422        1064 :         if (eap_gpsk_derive_session_id(sm->user->password,
     423         266 :                                        sm->user->password_len,
     424             :                                        data->vendor, data->specifier,
     425         266 :                                        data->rand_peer, data->rand_server,
     426         266 :                                        data->id_peer, data->id_peer_len,
     427             :                                        sm->server_id, sm->server_id_len,
     428             :                                        EAP_TYPE_GPSK,
     429         266 :                                        data->session_id, &data->id_len) < 0) {
     430           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive Session-Id");
     431           0 :                 eap_gpsk_state(data, FAILURE);
     432           0 :                 return;
     433             :         }
     434         532 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Derived Session-Id",
     435         266 :                     data->session_id, data->id_len);
     436             : 
     437         266 :         miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
     438         266 :         if (end - pos < (int) miclen) {
     439           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
     440             :                            "(left=%lu miclen=%lu)",
     441           0 :                            (unsigned long) (end - pos),
     442             :                            (unsigned long) miclen);
     443           0 :                 eap_gpsk_state(data, FAILURE);
     444           0 :                 return;
     445             :         }
     446         266 :         if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
     447         266 :                                  data->specifier, payload, pos - payload, mic)
     448             :             < 0) {
     449           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
     450           0 :                 eap_gpsk_state(data, FAILURE);
     451           0 :                 return;
     452             :         }
     453         266 :         if (os_memcmp_const(mic, pos, miclen) != 0) {
     454           1 :                 wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-2");
     455           1 :                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
     456           1 :                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
     457           1 :                 eap_gpsk_state(data, FAILURE);
     458           1 :                 return;
     459             :         }
     460         265 :         pos += miclen;
     461             : 
     462         265 :         if (pos != end) {
     463           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra "
     464             :                            "data in the end of GPSK-2",
     465           0 :                            (unsigned long) (end - pos));
     466             :         }
     467             : 
     468         265 :         eap_gpsk_state(data, GPSK_3);
     469             : }
     470             : 
     471             : 
     472         260 : static void eap_gpsk_process_gpsk_4(struct eap_sm *sm,
     473             :                                     struct eap_gpsk_data *data,
     474             :                                     const u8 *payload, size_t payloadlen)
     475             : {
     476             :         const u8 *pos, *end;
     477             :         u16 alen;
     478             :         size_t miclen;
     479             :         u8 mic[EAP_GPSK_MAX_MIC_LEN];
     480             : 
     481         260 :         if (data->state != GPSK_3)
     482           0 :                 return;
     483             : 
     484         260 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-4");
     485             : 
     486         260 :         pos = payload;
     487         260 :         end = payload + payloadlen;
     488             : 
     489         260 :         if (end - pos < 2) {
     490           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
     491             :                            "PD_Payload_1 length");
     492           0 :                 eap_gpsk_state(data, FAILURE);
     493           0 :                 return;
     494             :         }
     495         260 :         alen = WPA_GET_BE16(pos);
     496         260 :         pos += 2;
     497         260 :         if (end - pos < alen) {
     498           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
     499             :                            "PD_Payload_1");
     500           0 :                 eap_gpsk_state(data, FAILURE);
     501           0 :                 return;
     502             :         }
     503         260 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen);
     504         260 :         pos += alen;
     505             : 
     506         260 :         miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
     507         260 :         if (end - pos < (int) miclen) {
     508           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
     509             :                            "(left=%lu miclen=%lu)",
     510           0 :                            (unsigned long) (end - pos),
     511             :                            (unsigned long) miclen);
     512           0 :                 eap_gpsk_state(data, FAILURE);
     513           0 :                 return;
     514             :         }
     515         260 :         if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
     516         260 :                                  data->specifier, payload, pos - payload, mic)
     517             :             < 0) {
     518           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
     519           0 :                 eap_gpsk_state(data, FAILURE);
     520           0 :                 return;
     521             :         }
     522         260 :         if (os_memcmp_const(mic, pos, miclen) != 0) {
     523           0 :                 wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-4");
     524           0 :                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
     525           0 :                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
     526           0 :                 eap_gpsk_state(data, FAILURE);
     527           0 :                 return;
     528             :         }
     529         260 :         pos += miclen;
     530             : 
     531         260 :         if (pos != end) {
     532           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra "
     533             :                            "data in the end of GPSK-4",
     534           0 :                            (unsigned long) (end - pos));
     535             :         }
     536             : 
     537         260 :         eap_gpsk_state(data, SUCCESS);
     538             : }
     539             : 
     540             : 
     541         526 : static void eap_gpsk_process(struct eap_sm *sm, void *priv,
     542             :                              struct wpabuf *respData)
     543             : {
     544         526 :         struct eap_gpsk_data *data = priv;
     545             :         const u8 *pos;
     546             :         size_t len;
     547             : 
     548         526 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len);
     549         526 :         if (pos == NULL || len < 1)
     550         526 :                 return;
     551             : 
     552         526 :         switch (*pos) {
     553             :         case EAP_GPSK_OPCODE_GPSK_2:
     554         266 :                 eap_gpsk_process_gpsk_2(sm, data, pos + 1, len - 1);
     555         266 :                 break;
     556             :         case EAP_GPSK_OPCODE_GPSK_4:
     557         260 :                 eap_gpsk_process_gpsk_4(sm, data, pos + 1, len - 1);
     558         260 :                 break;
     559             :         }
     560             : }
     561             : 
     562             : 
     563         527 : static Boolean eap_gpsk_isDone(struct eap_sm *sm, void *priv)
     564             : {
     565         527 :         struct eap_gpsk_data *data = priv;
     566         527 :         return data->state == SUCCESS || data->state == FAILURE;
     567             : }
     568             : 
     569             : 
     570         261 : static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len)
     571             : {
     572         261 :         struct eap_gpsk_data *data = priv;
     573             :         u8 *key;
     574             : 
     575         261 :         if (data->state != SUCCESS)
     576           1 :                 return NULL;
     577             : 
     578         260 :         key = os_malloc(EAP_MSK_LEN);
     579         260 :         if (key == NULL)
     580           0 :                 return NULL;
     581         260 :         os_memcpy(key, data->msk, EAP_MSK_LEN);
     582         260 :         *len = EAP_MSK_LEN;
     583             : 
     584         260 :         return key;
     585             : }
     586             : 
     587             : 
     588           1 : static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
     589             : {
     590           1 :         struct eap_gpsk_data *data = priv;
     591             :         u8 *key;
     592             : 
     593           1 :         if (data->state != SUCCESS)
     594           0 :                 return NULL;
     595             : 
     596           1 :         key = os_malloc(EAP_EMSK_LEN);
     597           1 :         if (key == NULL)
     598           0 :                 return NULL;
     599           1 :         os_memcpy(key, data->emsk, EAP_EMSK_LEN);
     600           1 :         *len = EAP_EMSK_LEN;
     601             : 
     602           1 :         return key;
     603             : }
     604             : 
     605             : 
     606         262 : static Boolean eap_gpsk_isSuccess(struct eap_sm *sm, void *priv)
     607             : {
     608         262 :         struct eap_gpsk_data *data = priv;
     609         262 :         return data->state == SUCCESS;
     610             : }
     611             : 
     612             : 
     613         261 : static u8 * eap_gpsk_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
     614             : {
     615         261 :         struct eap_gpsk_data *data = priv;
     616             :         u8 *sid;
     617             : 
     618         261 :         if (data->state != SUCCESS)
     619           1 :                 return NULL;
     620             : 
     621         260 :         sid = os_malloc(data->id_len);
     622         260 :         if (sid == NULL)
     623           0 :                 return NULL;
     624         260 :         os_memcpy(sid, data->session_id, data->id_len);
     625         260 :         *len = data->id_len;
     626             : 
     627         260 :         return sid;
     628             : }
     629             : 
     630             : 
     631          10 : int eap_server_gpsk_register(void)
     632             : {
     633             :         struct eap_method *eap;
     634             :         int ret;
     635             : 
     636          10 :         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
     637             :                                       EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK");
     638          10 :         if (eap == NULL)
     639           0 :                 return -1;
     640             : 
     641          10 :         eap->init = eap_gpsk_init;
     642          10 :         eap->reset = eap_gpsk_reset;
     643          10 :         eap->buildReq = eap_gpsk_buildReq;
     644          10 :         eap->check = eap_gpsk_check;
     645          10 :         eap->process = eap_gpsk_process;
     646          10 :         eap->isDone = eap_gpsk_isDone;
     647          10 :         eap->getKey = eap_gpsk_getKey;
     648          10 :         eap->isSuccess = eap_gpsk_isSuccess;
     649          10 :         eap->get_emsk = eap_gpsk_get_emsk;
     650          10 :         eap->getSessionId = eap_gpsk_get_session_id;
     651             : 
     652          10 :         ret = eap_server_method_register(eap);
     653          10 :         if (ret)
     654           0 :                 eap_server_method_free(eap);
     655          10 :         return ret;
     656             : }

Generated by: LCOV version 1.10