eap_gpsk.c revision 845e0124d42b67ef926fbae32a7f61d2e5109ebd
1845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
2845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * EAP peer method: EAP-GPSK (draft-ietf-emu-eap-gpsk-08.txt)
3845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
4845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
5845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This program is free software; you can redistribute it and/or modify
6845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * it under the terms of the GNU General Public License version 2 as
7845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * published by the Free Software Foundation.
8845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
9845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Alternatively, this software may be distributed under the terms of BSD
10845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * license.
11845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
12845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * See README and COPYING for more details.
13845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
14845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
15845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "includes.h"
16845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
17845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "common.h"
18845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "eap_i.h"
19845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "config_ssid.h"
20845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "eap_gpsk_common.h"
21845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
22845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct eap_gpsk_data {
23845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state;
24845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 rand_server[EAP_GPSK_RAND_LEN];
25845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 rand_peer[EAP_GPSK_RAND_LEN];
26845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 msk[EAP_MSK_LEN];
27845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 emsk[EAP_EMSK_LEN];
28845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 sk[EAP_GPSK_MAX_SK_LEN];
29845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t sk_len;
30845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 pk[EAP_GPSK_MAX_PK_LEN];
31845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t pk_len;
32845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 session_id;
33845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int session_id_set;
34845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *id_peer;
35845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t id_peer_len;
36845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *id_server;
37845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t id_server_len;
38845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int vendor; /* CSuite/Specifier */
39845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int specifier; /* CSuite/Specifier */
40845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *psk;
41845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t psk_len;
42845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project};
43845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
44845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
45845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, u8 identifier,
46845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 const u8 *csuite_list, size_t csuite_list_len,
47845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 size_t *respDataLen);
48845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, u8 identifier,
49845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 size_t *respDataLen);
50845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
51845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
52845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#ifndef CONFIG_NO_STDOUT_DEBUG
53845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic const char * eap_gpsk_state_txt(int state)
54845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
55845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	switch (state) {
56845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case GPSK_1:
57845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "GPSK-1";
58845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case GPSK_3:
59845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "GPSK-3";
60845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case SUCCESS:
61845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "SUCCESS";
62845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case FAILURE:
63845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "FAILURE";
64845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	default:
65845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "?";
66845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
67845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
68845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#endif /* CONFIG_NO_STDOUT_DEBUG */
69845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
70845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
71845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void eap_gpsk_state(struct eap_gpsk_data *data, int state)
72845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
73845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s",
74845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   eap_gpsk_state_txt(data->state),
75845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   eap_gpsk_state_txt(state));
76845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	data->state = state;
77845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
78845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
79845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
80845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void eap_gpsk_deinit(struct eap_sm *sm, void *priv);
81845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
82845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
83845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void * eap_gpsk_init(struct eap_sm *sm)
84845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
85845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ssid *config = eap_get_config(sm);
86845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_gpsk_data *data;
87845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
88845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config == NULL) {
89845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_INFO, "EAP-GPSK: No configuration found");
90845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
91845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
92845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
93845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config->eappsk == NULL) {
94845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_INFO, "EAP-GPSK: No key (eappsk) configured");
95845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
96845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
97845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
98845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	data = os_zalloc(sizeof(*data));
99845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (data == NULL)
100845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
101845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	data->state = GPSK_1;
102845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
103845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config->nai) {
104845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		data->id_peer = os_malloc(config->nai_len);
105845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (data->id_peer == NULL) {
106845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			eap_gpsk_deinit(sm, data);
107845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return NULL;
108845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
109845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_memcpy(data->id_peer, config->nai, config->nai_len);
110845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		data->id_peer_len = config->nai_len;
111845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
112845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
113845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	data->psk = os_malloc(config->eappsk_len);
114845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (data->psk == NULL) {
115845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_gpsk_deinit(sm, data);
116845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
117845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
118845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(data->psk, config->eappsk, config->eappsk_len);
119845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	data->psk_len = config->eappsk_len;
120845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
121845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return data;
122845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
123845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
124845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
125845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void eap_gpsk_deinit(struct eap_sm *sm, void *priv)
126845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
127845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_gpsk_data *data = priv;
128845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(data->id_server);
129845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(data->id_peer);
130845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(data->psk);
131845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(data);
132845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
133845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
134845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
135845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst u8 * eap_gpsk_process_id_server(struct eap_gpsk_data *data,
136845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				      const u8 *pos, const u8 *end)
137845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
138845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u16 alen;
139845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
140845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (end - pos < 2) {
141845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet");
142845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
143845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
144845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	alen = WPA_GET_BE16(pos);
145845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += 2;
146845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (end - pos < alen) {
147845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server overflow");
148845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
149845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
150845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(data->id_server);
151845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	data->id_server = os_malloc(alen);
152845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (data->id_server == NULL) {
153845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: No memory for ID_Server");
154845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
155845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
156845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(data->id_server, pos, alen);
157845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	data->id_server_len = alen;
158845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server",
159845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  data->id_server, data->id_server_len);
160845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += alen;
161845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
162845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return pos;
163845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
164845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
165845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
166845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst u8 * eap_gpsk_process_rand_server(struct eap_gpsk_data *data,
167845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					const u8 *pos, const u8 *end)
168845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
169845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pos == NULL)
170845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
171845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
172845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (end - pos < EAP_GPSK_RAND_LEN) {
173845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server overflow");
174845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
175845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
176845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(data->rand_server, pos, EAP_GPSK_RAND_LEN);
177845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server",
178845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    data->rand_server, EAP_GPSK_RAND_LEN);
179845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += EAP_GPSK_RAND_LEN;
180845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
181845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return pos;
182845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
183845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
184845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
185845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int eap_gpsk_select_csuite(struct eap_sm *sm,
186845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  struct eap_gpsk_data *data,
187845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  const u8 *csuite_list,
188845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  size_t csuite_list_len)
189845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
190845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_gpsk_csuite *csuite;
191845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int i, count;
192845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
193845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	count = csuite_list_len / sizeof(struct eap_gpsk_csuite);
194845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	data->vendor = EAP_GPSK_VENDOR_IETF;
195845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	data->specifier = EAP_GPSK_CIPHER_RESERVED;
196845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	csuite = (struct eap_gpsk_csuite *) csuite_list;
197845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	for (i = 0; i < count; i++) {
198845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		int vendor, specifier;
199845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		vendor = WPA_GET_BE32(csuite->vendor);
200845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		specifier = WPA_GET_BE16(csuite->specifier);
201845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite[%d]: %d:%d",
202845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   i, vendor, specifier);
203845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (data->vendor == EAP_GPSK_VENDOR_IETF &&
204845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    data->specifier == EAP_GPSK_CIPHER_RESERVED &&
205845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    eap_gpsk_supported_ciphersuite(vendor, specifier)) {
206845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			data->vendor = vendor;
207845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			data->specifier = specifier;
208845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
209845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		csuite++;
210845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
211845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (data->vendor == EAP_GPSK_VENDOR_IETF &&
212845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    data->specifier == EAP_GPSK_CIPHER_RESERVED) {
213845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_msg(sm->msg_ctx, MSG_INFO, "EAP-GPSK: No supported "
214845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			"ciphersuite found");
215845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return -1;
216845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
217845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP-GPSK: Selected ciphersuite %d:%d",
218845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   data->vendor, data->specifier);
219845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
220845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return 0;
221845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
222845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
223845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
224845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst u8 * eap_gpsk_process_csuite_list(struct eap_sm *sm,
225845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					struct eap_gpsk_data *data,
226845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					const u8 **list, size_t *list_len,
227845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					const u8 *pos, const u8 *end)
228845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
229845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pos == NULL)
230845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
231845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
232845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (end - pos < 2) {
233845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet");
234845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
235845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
236845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*list_len = WPA_GET_BE16(pos);
237845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += 2;
238845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (end - pos < (int) *list_len) {
239845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List overflow");
240845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
241845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
242845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (*list_len == 0 || (*list_len % sizeof(struct eap_gpsk_csuite))) {
243845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %d",
244845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   *list_len);
245845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
246845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
247845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*list = pos;
248845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += *list_len;
249845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
250845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eap_gpsk_select_csuite(sm, data, *list, *list_len) < 0)
251845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
252845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
253845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return pos;
254845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
255845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
256845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
257845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eap_gpsk_process_gpsk_1(struct eap_sm *sm,
258845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				    struct eap_gpsk_data *data,
259845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				    struct eap_method_ret *ret,
260845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				    const u8 *reqData, size_t reqDataLen,
261845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				    const u8 *payload, size_t payload_len,
262845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				    size_t *respDataLen)
263845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
264845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t csuite_list_len;
265845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *csuite_list, *pos, *end;
266845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const struct eap_hdr *req;
267845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *resp;
268845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
269845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (data->state != GPSK_1) {
270845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		ret->ignore = TRUE;
271845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
272845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
273845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
274845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-1");
275845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
276845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	end = payload + payload_len;
277845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
278845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = eap_gpsk_process_id_server(data, payload, end);
279845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = eap_gpsk_process_rand_server(data, pos, end);
280845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = eap_gpsk_process_csuite_list(sm, data, &csuite_list,
281845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   &csuite_list_len, pos, end);
282845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pos == NULL) {
283845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_gpsk_state(data, FAILURE);
284845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
285845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
286845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
287845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	req = (const struct eap_hdr *) reqData;
288845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp = eap_gpsk_send_gpsk_2(data, req->identifier,
289845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				    csuite_list, csuite_list_len,
290845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				    respDataLen);
291845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (resp == NULL)
292845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
293845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
294845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap_gpsk_state(data, GPSK_3);
295845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
296845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return (u8 *) resp;
297845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
298845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
299845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
300845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, u8 identifier,
301845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 const u8 *csuite_list, size_t csuite_list_len,
302845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 size_t *respDataLen)
303845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
304845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_hdr *resp;
305845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t len, miclen;
306845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *rpos, *start;
307845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_gpsk_csuite *csuite;
308845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
309845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-2");
310845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
311845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
312845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len = 1 + 2 + data->id_peer_len + 2 + data->id_server_len +
313845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		2 * EAP_GPSK_RAND_LEN + 2 + csuite_list_len +
314845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sizeof(struct eap_gpsk_csuite) + 2 + miclen;
315845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
316845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respDataLen, len,
317845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			     EAP_CODE_RESPONSE, identifier, &rpos);
318845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (resp == NULL)
319845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
320845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
321845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*rpos++ = EAP_GPSK_OPCODE_GPSK_2;
322845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	start = rpos;
323845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
324845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer",
325845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  data->id_peer, data->id_peer_len);
326845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	WPA_PUT_BE16(rpos, data->id_peer_len);
327845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	rpos += 2;
328845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (data->id_peer)
329845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_memcpy(rpos, data->id_peer, data->id_peer_len);
330845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	rpos += data->id_peer_len;
331845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
332845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	WPA_PUT_BE16(rpos, data->id_server_len);
333845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	rpos += 2;
334845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (data->id_server)
335845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_memcpy(rpos, data->id_server, data->id_server_len);
336845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	rpos += data->id_server_len;
337845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
338845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (os_get_random(data->rand_peer, EAP_GPSK_RAND_LEN)) {
339845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data "
340845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "for RAND_Peer");
341845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_gpsk_state(data, FAILURE);
342845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(resp);
343845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
344845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
345845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer",
346845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    data->rand_peer, EAP_GPSK_RAND_LEN);
347845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(rpos, data->rand_peer, EAP_GPSK_RAND_LEN);
348845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	rpos += EAP_GPSK_RAND_LEN;
349845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
350845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(rpos, data->rand_server, EAP_GPSK_RAND_LEN);
351845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	rpos += EAP_GPSK_RAND_LEN;
352845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
353845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	WPA_PUT_BE16(rpos, csuite_list_len);
354845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	rpos += 2;
355845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(rpos, csuite_list, csuite_list_len);
356845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	rpos += csuite_list_len;
357845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
358845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	csuite = (struct eap_gpsk_csuite *) rpos;
359845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	WPA_PUT_BE32(csuite->vendor, data->vendor);
360845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	WPA_PUT_BE16(csuite->specifier, data->specifier);
361845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	rpos = (u8 *) (csuite + 1);
362845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
363845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eap_gpsk_derive_keys(data->psk, data->psk_len,
364845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 data->vendor, data->specifier,
365845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 data->rand_peer, data->rand_server,
366845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 data->id_peer, data->id_peer_len,
367845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 data->id_server, data->id_server_len,
368845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 data->msk, data->emsk,
369845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 data->sk, &data->sk_len,
370845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 data->pk, &data->pk_len) < 0) {
371845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys");
372845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_gpsk_state(data, FAILURE);
373845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(resp);
374845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
375845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
376845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
377845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/* No PD_Payload_1 */
378845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	WPA_PUT_BE16(rpos, 0);
379845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	rpos += 2;
380845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
381845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
382845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 data->specifier, start, rpos - start, rpos) <
383845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    0) {
384845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_gpsk_state(data, FAILURE);
385845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(resp);
386845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
387845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
388845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
389845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return (u8 *) resp;
390845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
391845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
392845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
393845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst u8 * eap_gpsk_validate_rand(struct eap_gpsk_data *data, const u8 *pos,
394845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  const u8 *end)
395845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
396845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (end - pos < EAP_GPSK_RAND_LEN) {
397845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
398845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "RAND_Peer");
399845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
400845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
401845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (os_memcmp(pos, data->rand_peer, EAP_GPSK_RAND_LEN) != 0) {
402845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2 and "
403845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "GPSK-3 did not match");
404845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2",
405845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    data->rand_peer, EAP_GPSK_RAND_LEN);
406845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-3",
407845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    pos, EAP_GPSK_RAND_LEN);
408845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
409845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
410845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += EAP_GPSK_RAND_LEN;
411845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
412845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (end - pos < EAP_GPSK_RAND_LEN) {
413845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
414845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "RAND_Server");
415845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
416845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
417845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (os_memcmp(pos, data->rand_server, EAP_GPSK_RAND_LEN) != 0) {
418845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and "
419845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "GPSK-3 did not match");
420845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1",
421845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    data->rand_server, EAP_GPSK_RAND_LEN);
422845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-3",
423845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    pos, EAP_GPSK_RAND_LEN);
424845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
425845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
426845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += EAP_GPSK_RAND_LEN;
427845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
428845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return pos;
429845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
430845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
431845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
432845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst u8 * eap_gpsk_validate_id_server(struct eap_gpsk_data *data,
433845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				       const u8 *pos, const u8 *end)
434845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
435845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t len;
436845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
437845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pos == NULL)
438845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
439845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
440845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (end - pos < (int) 2) {
441845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
442845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "length(ID_Server)");
443845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
444845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
445845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
446845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len = WPA_GET_BE16(pos);
447845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += 2;
448845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
449845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (end - pos < (int) len) {
450845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
451845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "ID_Server");
452845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
453845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
454845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
455845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (len != data->id_server_len ||
456845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    os_memcmp(pos, data->id_server, len) != 0) {
457845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_INFO, "EAP-GPSK: ID_Server did not match with "
458845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "the one used in GPSK-1");
459845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1",
460845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  data->id_server, data->id_server_len);
461845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-3",
462845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  pos, len);
463845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
464845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
465845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += len;
466845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
467845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return pos;
468845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
469845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
470845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
471845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst u8 * eap_gpsk_validate_csuite(struct eap_gpsk_data *data, const u8 *pos,
472845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				    const u8 *end)
473845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
474845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int vendor, specifier;
475845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const struct eap_gpsk_csuite *csuite;
476845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
477845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pos == NULL)
478845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
479845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
480845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (end - pos < (int) sizeof(*csuite)) {
481845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
482845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "CSuite_Sel");
483845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
484845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
485845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	csuite = (const struct eap_gpsk_csuite *) pos;
486845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	vendor = WPA_GET_BE32(csuite->vendor);
487845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	specifier = WPA_GET_BE16(csuite->specifier);
488845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += sizeof(*csuite);
489845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (vendor != data->vendor || specifier != data->specifier) {
490845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel (%d:%d) does not "
491845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "match with the one sent in GPSK-2 (%d:%d)",
492845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   vendor, specifier, data->vendor, data->specifier);
493845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
494845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
495845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
496845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return pos;
497845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
498845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
499845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
500845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst u8 * eap_gpsk_validate_pd_payload_2(struct eap_gpsk_data *data,
501845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					  const u8 *pos, const u8 *end)
502845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
503845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u16 alen;
504845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
505845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pos == NULL)
506845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
507845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
508845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (end - pos < 2) {
509845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
510845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "PD_Payload_2 length");
511845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
512845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
513845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	alen = WPA_GET_BE16(pos);
514845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += 2;
515845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (end - pos < alen) {
516845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
517845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "%d-octet PD_Payload_2", alen);
518845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
519845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
520845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_2", pos, alen);
521845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += alen;
522845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
523845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return pos;
524845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
525845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
526845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
527845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst u8 * eap_gpsk_validate_gpsk_3_mic(struct eap_gpsk_data *data,
528845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					const u8 *payload,
529845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					const u8 *pos, const u8 *end)
530845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
531845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t miclen;
532845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 mic[EAP_GPSK_MAX_MIC_LEN];
533845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
534845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pos == NULL)
535845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
536845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
537845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
538845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (end - pos < (int) miclen) {
539845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
540845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "(left=%d miclen=%d)", end - pos, miclen);
541845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
542845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
543845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
544845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 data->specifier, payload, pos - payload, mic)
545845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    < 0) {
546845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
547845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
548845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
549845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (os_memcmp(mic, pos, miclen) != 0) {
550845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-3");
551845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
552845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
553845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
554845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
555845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += miclen;
556845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
557845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return pos;
558845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
559845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
560845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
561845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eap_gpsk_process_gpsk_3(struct eap_sm *sm,
562845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				    struct eap_gpsk_data *data,
563845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				    struct eap_method_ret *ret,
564845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				    const u8 *reqData, size_t reqDataLen,
565845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				    const u8 *payload, size_t payload_len,
566845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				    size_t *respDataLen)
567845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
568845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *resp;
569845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const struct eap_hdr *req;
570845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *pos, *end;
571845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
572845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (data->state != GPSK_3) {
573845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		ret->ignore = TRUE;
574845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
575845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
576845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
577845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-3");
578845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
579845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	end = payload + payload_len;
580845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
581845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = eap_gpsk_validate_rand(data, payload, end);
582845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = eap_gpsk_validate_id_server(data, pos, end);
583845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = eap_gpsk_validate_csuite(data, pos, end);
584845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = eap_gpsk_validate_pd_payload_2(data, pos, end);
585845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = eap_gpsk_validate_gpsk_3_mic(data, payload, pos, end);
586845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
587845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pos == NULL) {
588845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_gpsk_state(data, FAILURE);
589845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
590845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
591845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pos != end) {
592845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %d bytes of extra "
593845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "data in the end of GPSK-2", end - pos);
594845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
595845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
596845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	req = (const struct eap_hdr *) reqData;
597845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp = eap_gpsk_send_gpsk_4(data, req->identifier, respDataLen);
598845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (resp == NULL)
599845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
600845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
601845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap_gpsk_state(data, SUCCESS);
602845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	ret->methodState = METHOD_DONE;
603845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	ret->decision = DECISION_UNCOND_SUCC;
604845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
605845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return (u8 *) resp;
606845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
607845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
608845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
609845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, u8 identifier,
610845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 size_t *respDataLen)
611845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
612845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_hdr *resp;
613845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *rpos, *start;
614845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t len;
615845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
616845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-4");
617845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
618845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len = 1 + 2 + eap_gpsk_mic_len(data->vendor, data->specifier);
619845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
620845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respDataLen, len,
621845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			     EAP_CODE_RESPONSE, identifier, &rpos);
622845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (resp == NULL)
623845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
624845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
625845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*rpos++ = EAP_GPSK_OPCODE_GPSK_4;
626845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	start = rpos;
627845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
628845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/* No PD_Payload_3 */
629845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	WPA_PUT_BE16(rpos, 0);
630845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	rpos += 2;
631845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
632845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
633845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 data->specifier, start, rpos - start, rpos) <
634845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    0) {
635845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_gpsk_state(data, FAILURE);
636845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(resp);
637845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
638845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
639845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
640845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return (u8 *) resp;
641845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
642845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
643845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
644845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eap_gpsk_process(struct eap_sm *sm, void *priv,
645845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    struct eap_method_ret *ret,
646845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    const u8 *reqData, size_t reqDataLen,
647845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    size_t *respDataLen)
648845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
649845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_gpsk_data *data = priv;
650845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *resp;
651845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *pos;
652845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t len;
653845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
654845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK,
655845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			       reqData, reqDataLen, &len);
656845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pos == NULL || len < 1) {
657845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		ret->ignore = TRUE;
658845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
659845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
660845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
661845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", *pos);
662845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
663845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	ret->ignore = FALSE;
664845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	ret->methodState = METHOD_MAY_CONT;
665845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	ret->decision = DECISION_FAIL;
666845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	ret->allowNotifications = FALSE;
667845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
668845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	switch (*pos) {
669845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_GPSK_OPCODE_GPSK_1:
670845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		resp = eap_gpsk_process_gpsk_1(sm, data, ret, reqData,
671845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					       reqDataLen, pos + 1, len - 1,
672845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					       respDataLen);
673845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
674845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_GPSK_OPCODE_GPSK_3:
675845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		resp = eap_gpsk_process_gpsk_3(sm, data, ret, reqData,
676845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					       reqDataLen, pos + 1, len - 1,
677845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					       respDataLen);
678845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
679845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	default:
680845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignoring message with "
681845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "unknown opcode %d", *pos);
682845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		ret->ignore = TRUE;
683845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
684845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
685845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
686845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return resp;
687845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
688845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
689845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
690845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic Boolean eap_gpsk_isKeyAvailable(struct eap_sm *sm, void *priv)
691845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
692845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_gpsk_data *data = priv;
693845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return data->state == SUCCESS;
694845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
695845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
696845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
697845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len)
698845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
699845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_gpsk_data *data = priv;
700845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *key;
701845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
702845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (data->state != SUCCESS)
703845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
704845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
705845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	key = os_malloc(EAP_MSK_LEN);
706845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (key == NULL)
707845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
708845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(key, data->msk, EAP_MSK_LEN);
709845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*len = EAP_MSK_LEN;
710845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
711845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return key;
712845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
713845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
714845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
715845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
716845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
717845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_gpsk_data *data = priv;
718845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *key;
719845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
720845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (data->state != SUCCESS)
721845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
722845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
723845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	key = os_malloc(EAP_EMSK_LEN);
724845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (key == NULL)
725845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
726845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
727845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*len = EAP_EMSK_LEN;
728845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
729845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return key;
730845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
731845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
732845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
733845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectint eap_peer_gpsk_register(void)
734845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
735845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_method *eap;
736845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int ret;
737845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
738845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
739845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				    EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK");
740845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eap == NULL)
741845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return -1;
742845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
743845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap->init = eap_gpsk_init;
744845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap->deinit = eap_gpsk_deinit;
745845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap->process = eap_gpsk_process;
746845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap->isKeyAvailable = eap_gpsk_isKeyAvailable;
747845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap->getKey = eap_gpsk_getKey;
748845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap->get_emsk = eap_gpsk_get_emsk;
749845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
750845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	ret = eap_peer_method_register(eap);
751845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (ret)
752845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_peer_method_free(eap);
753845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return ret;
754845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
755