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 1443382998 Lines: 243 363 66.9 %
Date: 2015-09-27 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        1120 : static const char * eap_gpsk_state_txt(int state)
      40             : {
      41        1120 :         switch (state) {
      42             :         case GPSK_1:
      43         283 :                 return "GPSK-1";
      44             :         case GPSK_3:
      45         559 :                 return "GPSK-3";
      46             :         case SUCCESS:
      47         277 :                 return "SUCCESS";
      48             :         case FAILURE:
      49           1 :                 return "FAILURE";
      50             :         default:
      51           0 :                 return "?";
      52             :         }
      53             : }
      54             : 
      55             : 
      56         560 : static void eap_gpsk_state(struct eap_gpsk_data *data, int state)
      57             : {
      58        1120 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s",
      59         560 :                    eap_gpsk_state_txt(data->state),
      60             :                    eap_gpsk_state_txt(state));
      61         560 :         data->state = state;
      62         560 : }
      63             : 
      64             : 
      65         291 : static void * eap_gpsk_init(struct eap_sm *sm)
      66             : {
      67             :         struct eap_gpsk_data *data;
      68             : 
      69         291 :         data = os_zalloc(sizeof(*data));
      70         291 :         if (data == NULL)
      71           0 :                 return NULL;
      72         291 :         data->state = GPSK_1;
      73             : 
      74         291 :         data->csuite_count = 0;
      75         291 :         if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF,
      76             :                                            EAP_GPSK_CIPHER_AES)) {
      77         291 :                 WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor,
      78             :                              EAP_GPSK_VENDOR_IETF);
      79         291 :                 WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier,
      80             :                              EAP_GPSK_CIPHER_AES);
      81         291 :                 data->csuite_count++;
      82             :         }
      83         291 :         if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF,
      84             :                                            EAP_GPSK_CIPHER_SHA256)) {
      85         291 :                 WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor,
      86             :                              EAP_GPSK_VENDOR_IETF);
      87         291 :                 WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier,
      88             :                              EAP_GPSK_CIPHER_SHA256);
      89         291 :                 data->csuite_count++;
      90             :         }
      91             : 
      92         291 :         return data;
      93             : }
      94             : 
      95             : 
      96         291 : static void eap_gpsk_reset(struct eap_sm *sm, void *priv)
      97             : {
      98         291 :         struct eap_gpsk_data *data = priv;
      99         291 :         os_free(data->id_peer);
     100         291 :         bin_clear_free(data, sizeof(*data));
     101         291 : }
     102             : 
     103             : 
     104         291 : 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         291 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-1");
     111             : 
     112         291 :         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         291 :         wpa_hexdump(MSG_MSGDUMP, "EAP-GPSK: RAND_Server",
     118         291 :                     data->rand_server, EAP_GPSK_RAND_LEN);
     119             : 
     120         582 :         len = 1 + 2 + sm->server_id_len + EAP_GPSK_RAND_LEN + 2 +
     121         291 :                 data->csuite_count * sizeof(struct eap_gpsk_csuite);
     122         291 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
     123             :                             EAP_CODE_REQUEST, id);
     124         291 :         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         291 :         wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_1);
     132         291 :         wpabuf_put_be16(req, sm->server_id_len);
     133         291 :         wpabuf_put_data(req, sm->server_id, sm->server_id_len);
     134         291 :         wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
     135         291 :         wpabuf_put_be16(req,
     136         291 :                         data->csuite_count * sizeof(struct eap_gpsk_csuite));
     137         291 :         wpabuf_put_data(req, data->csuite_list,
     138         291 :                         data->csuite_count * sizeof(struct eap_gpsk_csuite));
     139             : 
     140         291 :         return req;
     141             : }
     142             : 
     143             : 
     144         282 : 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         282 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-3");
     153             : 
     154         282 :         miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
     155         564 :         len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + sm->server_id_len +
     156         282 :                 sizeof(struct eap_gpsk_csuite) + 2 + miclen;
     157         282 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
     158             :                             EAP_CODE_REQUEST, id);
     159         282 :         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         282 :         wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_3);
     167         282 :         start = wpabuf_put(req, 0);
     168             : 
     169         282 :         wpabuf_put_data(req, data->rand_peer, EAP_GPSK_RAND_LEN);
     170         282 :         wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
     171         282 :         wpabuf_put_be16(req, sm->server_id_len);
     172         282 :         wpabuf_put_data(req, sm->server_id, sm->server_id_len);
     173         282 :         csuite = wpabuf_put(req, sizeof(*csuite));
     174         282 :         WPA_PUT_BE32(csuite->vendor, data->vendor);
     175         282 :         WPA_PUT_BE16(csuite->specifier, data->specifier);
     176             : 
     177             :         /* no PD_Payload_2 */
     178         282 :         wpabuf_put_be16(req, 0);
     179             : 
     180         282 :         pos = wpabuf_put(req, miclen);
     181         282 :         if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
     182         282 :                                  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         282 :         return req;
     190             : }
     191             : 
     192             : 
     193         573 : static struct wpabuf * eap_gpsk_buildReq(struct eap_sm *sm, void *priv, u8 id)
     194             : {
     195         573 :         struct eap_gpsk_data *data = priv;
     196             : 
     197         573 :         switch (data->state) {
     198             :         case GPSK_1:
     199         291 :                 return eap_gpsk_build_gpsk_1(sm, data, id);
     200             :         case GPSK_3:
     201         282 :                 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         560 : static Boolean eap_gpsk_check(struct eap_sm *sm, void *priv,
     212             :                               struct wpabuf *respData)
     213             : {
     214         560 :         struct eap_gpsk_data *data = priv;
     215             :         const u8 *pos;
     216             :         size_t len;
     217             : 
     218         560 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len);
     219         560 :         if (pos == NULL || len < 1) {
     220           0 :                 wpa_printf(MSG_INFO, "EAP-GPSK: Invalid frame");
     221           0 :                 return TRUE;
     222             :         }
     223             : 
     224         560 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode=%d", *pos);
     225             : 
     226         560 :         if (data->state == GPSK_1 && *pos == EAP_GPSK_OPCODE_GPSK_2)
     227         283 :                 return FALSE;
     228             : 
     229         277 :         if (data->state == GPSK_3 && *pos == EAP_GPSK_OPCODE_GPSK_4)
     230         277 :                 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         283 : 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         283 :         if (data->state != GPSK_1)
     250           1 :                 return;
     251             : 
     252         283 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-2");
     253             : 
     254         283 :         pos = payload;
     255         283 :         end = payload + payloadlen;
     256             : 
     257         283 :         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         283 :         alen = WPA_GET_BE16(pos);
     264         283 :         pos += 2;
     265         283 :         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         283 :         os_free(data->id_peer);
     272         283 :         data->id_peer = os_malloc(alen);
     273         283 :         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         283 :         os_memcpy(data->id_peer, pos, alen);
     279         283 :         data->id_peer_len = alen;
     280         566 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer",
     281         283 :                           data->id_peer, data->id_peer_len);
     282         283 :         pos += alen;
     283             : 
     284         283 :         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         283 :         alen = WPA_GET_BE16(pos);
     291         283 :         pos += 2;
     292         283 :         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         566 :         if (alen != sm->server_id_len ||
     299         283 :             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         283 :         pos += alen;
     306             : 
     307         283 :         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         283 :         os_memcpy(data->rand_peer, pos, EAP_GPSK_RAND_LEN);
     314         283 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer",
     315         283 :                     data->rand_peer, EAP_GPSK_RAND_LEN);
     316         283 :         pos += EAP_GPSK_RAND_LEN;
     317             : 
     318         283 :         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         283 :         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         283 :         pos += EAP_GPSK_RAND_LEN;
     335             : 
     336         283 :         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         283 :         alen = WPA_GET_BE16(pos);
     343         283 :         pos += 2;
     344         283 :         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         566 :         if (alen != data->csuite_count * sizeof(struct eap_gpsk_csuite) ||
     351         283 :             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         283 :         pos += alen;
     358             : 
     359         283 :         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         283 :         csuite = (const struct eap_gpsk_csuite *) pos;
     366         284 :         for (i = 0; i < data->csuite_count; i++) {
     367         284 :                 if (os_memcmp(csuite, &data->csuite_list[i], sizeof(*csuite))
     368             :                     == 0)
     369         283 :                         break;
     370             :         }
     371         283 :         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         283 :         data->vendor = WPA_GET_BE32(csuite->vendor);
     380         283 :         data->specifier = WPA_GET_BE16(csuite->specifier);
     381         283 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel %d:%d",
     382             :                    data->vendor, data->specifier);
     383         283 :         pos += sizeof(*csuite); 
     384             : 
     385         283 :         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         283 :         alen = WPA_GET_BE16(pos);
     392         283 :         pos += 2;
     393         283 :         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         283 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen);
     400         283 :         pos += alen;
     401             : 
     402         283 :         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        1132 :         if (eap_gpsk_derive_keys(sm->user->password, sm->user->password_len,
     410             :                                  data->vendor, data->specifier,
     411         283 :                                  data->rand_peer, data->rand_server,
     412         283 :                                  data->id_peer, data->id_peer_len,
     413             :                                  sm->server_id, sm->server_id_len,
     414         283 :                                  data->msk, data->emsk,
     415         283 :                                  data->sk, &data->sk_len,
     416         283 :                                  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        1132 :         if (eap_gpsk_derive_session_id(sm->user->password,
     423         283 :                                        sm->user->password_len,
     424             :                                        data->vendor, data->specifier,
     425         283 :                                        data->rand_peer, data->rand_server,
     426         283 :                                        data->id_peer, data->id_peer_len,
     427             :                                        sm->server_id, sm->server_id_len,
     428             :                                        EAP_TYPE_GPSK,
     429         283 :                                        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         566 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Derived Session-Id",
     435         283 :                     data->session_id, data->id_len);
     436             : 
     437         283 :         miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
     438         283 :         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         283 :         if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
     447         283 :                                  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         283 :         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         282 :         pos += miclen;
     461             : 
     462         282 :         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         282 :         eap_gpsk_state(data, GPSK_3);
     469             : }
     470             : 
     471             : 
     472         277 : 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         277 :         if (data->state != GPSK_3)
     482           0 :                 return;
     483             : 
     484         277 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-4");
     485             : 
     486         277 :         pos = payload;
     487         277 :         end = payload + payloadlen;
     488             : 
     489         277 :         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         277 :         alen = WPA_GET_BE16(pos);
     496         277 :         pos += 2;
     497         277 :         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         277 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen);
     504         277 :         pos += alen;
     505             : 
     506         277 :         miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
     507         277 :         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         277 :         if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
     516         277 :                                  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         277 :         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         277 :         pos += miclen;
     530             : 
     531         277 :         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         277 :         eap_gpsk_state(data, SUCCESS);
     538             : }
     539             : 
     540             : 
     541         560 : static void eap_gpsk_process(struct eap_sm *sm, void *priv,
     542             :                              struct wpabuf *respData)
     543             : {
     544         560 :         struct eap_gpsk_data *data = priv;
     545             :         const u8 *pos;
     546             :         size_t len;
     547             : 
     548         560 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len);
     549         560 :         if (pos == NULL || len < 1)
     550         560 :                 return;
     551             : 
     552         560 :         switch (*pos) {
     553             :         case EAP_GPSK_OPCODE_GPSK_2:
     554         283 :                 eap_gpsk_process_gpsk_2(sm, data, pos + 1, len - 1);
     555         283 :                 break;
     556             :         case EAP_GPSK_OPCODE_GPSK_4:
     557         277 :                 eap_gpsk_process_gpsk_4(sm, data, pos + 1, len - 1);
     558         277 :                 break;
     559             :         }
     560             : }
     561             : 
     562             : 
     563         561 : static Boolean eap_gpsk_isDone(struct eap_sm *sm, void *priv)
     564             : {
     565         561 :         struct eap_gpsk_data *data = priv;
     566         561 :         return data->state == SUCCESS || data->state == FAILURE;
     567             : }
     568             : 
     569             : 
     570         278 : static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len)
     571             : {
     572         278 :         struct eap_gpsk_data *data = priv;
     573             :         u8 *key;
     574             : 
     575         278 :         if (data->state != SUCCESS)
     576           1 :                 return NULL;
     577             : 
     578         277 :         key = os_malloc(EAP_MSK_LEN);
     579         277 :         if (key == NULL)
     580           0 :                 return NULL;
     581         277 :         os_memcpy(key, data->msk, EAP_MSK_LEN);
     582         277 :         *len = EAP_MSK_LEN;
     583             : 
     584         277 :         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         279 : static Boolean eap_gpsk_isSuccess(struct eap_sm *sm, void *priv)
     607             : {
     608         279 :         struct eap_gpsk_data *data = priv;
     609         279 :         return data->state == SUCCESS;
     610             : }
     611             : 
     612             : 
     613         278 : static u8 * eap_gpsk_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
     614             : {
     615         278 :         struct eap_gpsk_data *data = priv;
     616             :         u8 *sid;
     617             : 
     618         278 :         if (data->state != SUCCESS)
     619           1 :                 return NULL;
     620             : 
     621         277 :         sid = os_malloc(data->id_len);
     622         277 :         if (sid == NULL)
     623           0 :                 return NULL;
     624         277 :         os_memcpy(sid, data->session_id, data->id_len);
     625         277 :         *len = data->id_len;
     626             : 
     627         277 :         return sid;
     628             : }
     629             : 
     630             : 
     631          25 : int eap_server_gpsk_register(void)
     632             : {
     633             :         struct eap_method *eap;
     634             :         int ret;
     635             : 
     636          25 :         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
     637             :                                       EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK");
     638          25 :         if (eap == NULL)
     639           0 :                 return -1;
     640             : 
     641          25 :         eap->init = eap_gpsk_init;
     642          25 :         eap->reset = eap_gpsk_reset;
     643          25 :         eap->buildReq = eap_gpsk_buildReq;
     644          25 :         eap->check = eap_gpsk_check;
     645          25 :         eap->process = eap_gpsk_process;
     646          25 :         eap->isDone = eap_gpsk_isDone;
     647          25 :         eap->getKey = eap_gpsk_getKey;
     648          25 :         eap->isSuccess = eap_gpsk_isSuccess;
     649          25 :         eap->get_emsk = eap_gpsk_get_emsk;
     650          25 :         eap->getSessionId = eap_gpsk_get_session_id;
     651             : 
     652          25 :         ret = eap_server_method_register(eap);
     653          25 :         if (ret)
     654           0 :                 eap_server_method_free(eap);
     655          25 :         return ret;
     656             : }

Generated by: LCOV version 1.10