eap_ttls.c revision c5ec7f57ead87efa365800228aa0b09a12d9e6c4
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * EAP peer method: EAP-TTLS (RFC 5281)
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This software may be distributed under the terms of the BSD license.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See README for more details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "includes.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "common.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/ms_funcs.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "crypto/sha1.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/tls.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "eap_common/chap.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "eap_common/eap_ttls.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "mschapv2.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "eap_i.h"
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "eap_tls_common.h"
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "eap_config.h"
2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#define EAP_TTLS_VERSION 0
2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static void eap_ttls_deinit(struct eap_sm *sm, void *priv);
2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochstruct eap_ttls_data {
30558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch	struct eap_ssl_data ssl;
31558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int ttls_version;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	const struct eap_method *phase2_method;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	void *phase2_priv;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int phase2_success;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int phase2_start;
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	enum phase2_types {
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		EAP_TTLS_PHASE2_EAP,
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		EAP_TTLS_PHASE2_MSCHAPV2,
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		EAP_TTLS_PHASE2_MSCHAP,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		EAP_TTLS_PHASE2_PAP,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		EAP_TTLS_PHASE2_CHAP
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} phase2_type;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct eap_method_type phase2_eap_type;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct eap_method_type *phase2_eap_types;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	size_t num_phase2_eap_types;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN];
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int auth_response_valid;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; /* MSCHAPv2 master key */
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	u8 ident;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int resuming; /* starting a resumed session */
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int reauth; /* reauthentication */
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	u8 *key_data;
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	struct wpabuf *pending_phase2_req;
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#ifdef EAP_TNC
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	int ready_for_tnc;
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	int tnc_started;
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif /* EAP_TNC */
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void * eap_ttls_init(struct eap_sm *sm)
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	struct eap_ttls_data *data;
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	struct eap_peer_config *config = eap_get_config(sm);
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	char *selected;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	data = os_zalloc(sizeof(*data));
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (data == NULL)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return NULL;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	data->ttls_version = EAP_TTLS_VERSION;
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	selected = "EAP";
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	data->phase2_type = EAP_TTLS_PHASE2_EAP;
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (config && config->phase2) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (os_strstr(config->phase2, "autheap=")) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			selected = "EAP";
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			data->phase2_type = EAP_TTLS_PHASE2_EAP;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		} else if (os_strstr(config->phase2, "auth=MSCHAPV2")) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			selected = "MSCHAPV2";
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		} else if (os_strstr(config->phase2, "auth=MSCHAP")) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			selected = "MSCHAP";
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			data->phase2_type = EAP_TTLS_PHASE2_MSCHAP;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		} else if (os_strstr(config->phase2, "auth=PAP")) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			selected = "PAP";
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			data->phase2_type = EAP_TTLS_PHASE2_PAP;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		} else if (os_strstr(config->phase2, "auth=CHAP")) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			selected = "CHAP";
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			data->phase2_type = EAP_TTLS_PHASE2_CHAP;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)	if (data->phase2_type == EAP_TTLS_PHASE2_EAP) {
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)		if (eap_peer_select_phase2_methods(config, "autheap=",
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)						   &data->phase2_eap_types,
10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)						   &data->num_phase2_eap_types)
10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)		    < 0) {
10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)			eap_ttls_deinit(sm, data);
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)			return NULL;
10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)		}
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)		data->phase2_eap_type.vendor = EAP_VENDOR_IETF;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		data->phase2_eap_type.method = EAP_TYPE_NONE;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL.");
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		eap_ttls_deinit(sm, data);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return NULL;
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	}
118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	return data;
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static void eap_ttls_phase2_eap_deinit(struct eap_sm *sm,
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)				       struct eap_ttls_data *data)
12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles){
12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	if (data->phase2_priv && data->phase2_method) {
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		data->phase2_method->deinit(sm, data->phase2_priv);
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		data->phase2_method = NULL;
12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		data->phase2_priv = NULL;
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	}
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct eap_ttls_data *data = priv;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (data == NULL)
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)		return;
139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	eap_ttls_phase2_eap_deinit(sm, data);
140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	os_free(data->phase2_eap_types);
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	eap_peer_tls_ssl_deinit(sm, &data->ssl);
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	os_free(data->key_data);
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	wpabuf_free(data->pending_phase2_req);
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	os_free(data);
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
147558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id,
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			     int mandatory, size_t len)
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles){
151558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch	struct ttls_avp_vendor *avp;
152558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch	u8 flags;
153558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch	size_t hdrlen;
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
155558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch	avp = (struct ttls_avp_vendor *) avphdr;
156558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch	flags = mandatory ? AVP_FLAGS_MANDATORY : 0;
157558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch	if (vendor_id) {
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		flags |= AVP_FLAGS_VENDOR;
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		hdrlen = sizeof(*avp);
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		avp->vendor_id = host_to_be32(vendor_id);
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	} else {
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		hdrlen = sizeof(struct ttls_avp);
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	}
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	avp->avp_code = host_to_be32(avp_code);
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	avp->avp_length = host_to_be32((flags << 24) | (u32) (hdrlen + len));
167558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
168558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch	return avphdr + hdrlen;
169558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
170558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
171558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
172558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochstatic u8 * eap_ttls_avp_add(u8 *start, u8 *avphdr, u32 avp_code,
173558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch			     u32 vendor_id, int mandatory,
174558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch			     const u8 *data, size_t len)
175558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch{
176558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch	u8 *pos;
177558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch	pos = eap_ttls_avp_hdr(avphdr, avp_code, vendor_id, mandatory, len);
178558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch	os_memcpy(pos, data, len);
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	pos += len;
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	AVP_PAD(start, pos);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return pos;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    int mandatory)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct wpabuf *msg;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	u8 *avp, *pos;
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (msg == NULL) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpabuf_free(*resp);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*resp = NULL;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return -1;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	avp = wpabuf_mhead(msg);
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, wpabuf_len(*resp));
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp));
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	pos += wpabuf_len(*resp);
20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	AVP_PAD(avp, pos);
20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	wpabuf_free(*resp);
20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	wpabuf_put(msg, pos - avp);
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	*resp = msg;
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	return 0;
20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static int eap_ttls_v0_derive_key(struct eap_sm *sm,
21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)				  struct eap_ttls_data *data)
21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles){
21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	os_free(data->key_data);
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)						 "ttls keying material",
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)						 EAP_TLS_KEY_LEN);
21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	if (!data->key_data) {
21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to derive key");
21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		return -1;
22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	}
22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			data->key_data, EAP_TLS_KEY_LEN);
22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	return 0;
22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)					struct eap_ttls_data *data, size_t len)
23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles){
23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len);
23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data,
23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)					      u8 method)
23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles){
23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	size_t i;
24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	for (i = 0; i < data->num_phase2_eap_types; i++) {
24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF ||
24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		    data->phase2_eap_types[i].method != method)
24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			continue;
24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		data->phase2_eap_type.vendor =
24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			data->phase2_eap_types[i].vendor;
24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		data->phase2_eap_type.method =
24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			data->phase2_eap_types[i].method;
24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			   "Phase 2 EAP vendor %d method %d",
25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			   data->phase2_eap_type.vendor,
25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			   data->phase2_eap_type.method);
25358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		break;
25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	}
25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static int eap_ttls_phase2_eap_process(struct eap_sm *sm,
25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)				       struct eap_ttls_data *data,
26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)				       struct eap_method_ret *ret,
26158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)				       struct eap_hdr *hdr, size_t len,
26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)				       struct wpabuf **resp)
26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles){
26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	struct wpabuf msg;
26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	struct eap_method_ret iret;
26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	os_memset(&iret, 0, sizeof(iret));
26858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	wpabuf_set(&msg, hdr, len);
26958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	*resp = data->phase2_method->process(sm, data->phase2_priv, &iret,
27058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)					     &msg);
27158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	if ((iret.methodState == METHOD_DONE ||
27258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	     iret.methodState == METHOD_MAY_CONT) &&
27358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	    (iret.decision == DECISION_UNCOND_SUCC ||
27458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	     iret.decision == DECISION_COND_SUCC ||
27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	     iret.decision == DECISION_FAIL)) {
27658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		ret->methodState = iret.methodState;
27758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		ret->decision = iret.decision;
27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	}
27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
28058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	return 0;
28158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
28258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
28358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
28458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)					      struct eap_ttls_data *data,
28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)					      struct eap_method_ret *ret,
28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)					      struct eap_hdr *hdr, size_t len,
28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)					      u8 method, struct wpabuf **resp)
28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles){
29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#ifdef EAP_TNC
29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	if (data->tnc_started && data->phase2_method &&
29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	    data->phase2_priv && method == EAP_TYPE_TNC &&
29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	    data->phase2_eap_type.method == EAP_TYPE_TNC)
29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len,
29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)						   resp);
29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	if (data->ready_for_tnc && !data->tnc_started &&
29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	    method == EAP_TYPE_TNC) {
29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed "
30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			   "EAP method");
30158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		data->tnc_started = 1;
30258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	}
30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	if (data->tnc_started) {
30558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		if (data->phase2_eap_type.vendor != EAP_VENDOR_IETF ||
30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		    data->phase2_eap_type.method == EAP_TYPE_TNC) {
30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected EAP "
30858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)				   "type %d for TNC", method);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return -1;
310		}
311
312		data->phase2_eap_type.vendor = EAP_VENDOR_IETF;
313		data->phase2_eap_type.method = method;
314		wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
315			   "Phase 2 EAP vendor %d method %d (TNC)",
316			   data->phase2_eap_type.vendor,
317			   data->phase2_eap_type.method);
318
319		if (data->phase2_type == EAP_TTLS_PHASE2_EAP)
320			eap_ttls_phase2_eap_deinit(sm, data);
321	}
322#endif /* EAP_TNC */
323
324	if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF &&
325	    data->phase2_eap_type.method == EAP_TYPE_NONE)
326		eap_ttls_phase2_select_eap_method(data, method);
327
328	if (method != data->phase2_eap_type.method || method == EAP_TYPE_NONE)
329	{
330		if (eap_peer_tls_phase2_nak(data->phase2_eap_types,
331					    data->num_phase2_eap_types,
332					    hdr, resp))
333			return -1;
334		return 0;
335	}
336
337	if (data->phase2_priv == NULL) {
338		data->phase2_method = eap_peer_get_eap_method(
339			EAP_VENDOR_IETF, method);
340		if (data->phase2_method) {
341			sm->init_phase2 = 1;
342			data->phase2_priv = data->phase2_method->init(sm);
343			sm->init_phase2 = 0;
344		}
345	}
346	if (data->phase2_priv == NULL || data->phase2_method == NULL) {
347		wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize "
348			   "Phase 2 EAP method %d", method);
349		return -1;
350	}
351
352	return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, resp);
353}
354
355
356static int eap_ttls_phase2_request_eap(struct eap_sm *sm,
357				       struct eap_ttls_data *data,
358				       struct eap_method_ret *ret,
359				       struct eap_hdr *hdr,
360				       struct wpabuf **resp)
361{
362	size_t len = be_to_host16(hdr->length);
363	u8 *pos;
364	struct eap_peer_config *config = eap_get_config(sm);
365
366	if (len <= sizeof(struct eap_hdr)) {
367		wpa_printf(MSG_INFO, "EAP-TTLS: too short "
368			   "Phase 2 request (len=%lu)", (unsigned long) len);
369		return -1;
370	}
371	pos = (u8 *) (hdr + 1);
372	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP Request: type=%d", *pos);
373	switch (*pos) {
374	case EAP_TYPE_IDENTITY:
375		*resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
376		break;
377	default:
378		if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len,
379						       *pos, resp) < 0)
380			return -1;
381		break;
382	}
383
384	if (*resp == NULL &&
385	    (config->pending_req_identity || config->pending_req_password ||
386	     config->pending_req_otp)) {
387		return 0;
388	}
389
390	if (*resp == NULL)
391		return -1;
392
393	wpa_hexdump_buf(MSG_DEBUG, "EAP-TTLS: AVP encapsulate EAP Response",
394			*resp);
395	return eap_ttls_avp_encapsulate(resp, RADIUS_ATTR_EAP_MESSAGE, 1);
396}
397
398
399static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
400					    struct eap_ttls_data *data,
401					    struct eap_method_ret *ret,
402					    struct wpabuf **resp)
403{
404	struct wpabuf *msg;
405	u8 *buf, *pos, *challenge, *peer_challenge;
406	const u8 *identity, *password;
407	size_t identity_len, password_len;
408	int pwhash;
409
410	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request");
411
412	identity = eap_get_config_identity(sm, &identity_len);
413	password = eap_get_config_password2(sm, &password_len, &pwhash);
414	if (identity == NULL || password == NULL)
415		return -1;
416
417	msg = wpabuf_alloc(identity_len + 1000);
418	if (msg == NULL) {
419		wpa_printf(MSG_ERROR,
420			   "EAP-TTLS/MSCHAPV2: Failed to allocate memory");
421		return -1;
422	}
423	pos = buf = wpabuf_mhead(msg);
424
425	/* User-Name */
426	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
427			       identity, identity_len);
428
429	/* MS-CHAP-Challenge */
430	challenge = eap_ttls_implicit_challenge(
431		sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1);
432	if (challenge == NULL) {
433		wpabuf_free(msg);
434		wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
435			   "implicit challenge");
436		return -1;
437	}
438	peer_challenge = challenge + 1 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN;
439
440	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE,
441			       RADIUS_VENDOR_ID_MICROSOFT, 1,
442			       challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
443
444	/* MS-CHAP2-Response */
445	pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_RESPONSE,
446			       RADIUS_VENDOR_ID_MICROSOFT, 1,
447			       EAP_TTLS_MSCHAPV2_RESPONSE_LEN);
448	data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN];
449	*pos++ = data->ident;
450	*pos++ = 0; /* Flags */
451	os_memcpy(pos, peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
452	pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN;
453	os_memset(pos, 0, 8); /* Reserved, must be zero */
454	pos += 8;
455	if (mschapv2_derive_response(identity, identity_len, password,
456				     password_len, pwhash, challenge,
457				     peer_challenge, pos, data->auth_response,
458				     data->master_key)) {
459		wpabuf_free(msg);
460		wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
461			   "response");
462		return -1;
463	}
464	data->auth_response_valid = 1;
465
466	pos += 24;
467	os_free(challenge);
468	AVP_PAD(buf, pos);
469
470	wpabuf_put(msg, pos - buf);
471	*resp = msg;
472
473	if (sm->workaround) {
474		/* At least FreeRADIUS seems to be terminating
475		 * EAP-TTLS/MSHCAPV2 without the expected MS-CHAP-v2 Success
476		 * packet. */
477		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: EAP workaround - "
478			   "allow success without tunneled response");
479		ret->methodState = METHOD_MAY_CONT;
480		ret->decision = DECISION_COND_SUCC;
481	}
482
483	return 0;
484}
485
486
487static int eap_ttls_phase2_request_mschap(struct eap_sm *sm,
488					  struct eap_ttls_data *data,
489					  struct eap_method_ret *ret,
490					  struct wpabuf **resp)
491{
492	struct wpabuf *msg;
493	u8 *buf, *pos, *challenge;
494	const u8 *identity, *password;
495	size_t identity_len, password_len;
496	int pwhash;
497
498	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request");
499
500	identity = eap_get_config_identity(sm, &identity_len);
501	password = eap_get_config_password2(sm, &password_len, &pwhash);
502	if (identity == NULL || password == NULL)
503		return -1;
504
505	msg = wpabuf_alloc(identity_len + 1000);
506	if (msg == NULL) {
507		wpa_printf(MSG_ERROR,
508			   "EAP-TTLS/MSCHAP: Failed to allocate memory");
509		return -1;
510	}
511	pos = buf = wpabuf_mhead(msg);
512
513	/* User-Name */
514	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
515			       identity, identity_len);
516
517	/* MS-CHAP-Challenge */
518	challenge = eap_ttls_implicit_challenge(
519		sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1);
520	if (challenge == NULL) {
521		wpabuf_free(msg);
522		wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive "
523			   "implicit challenge");
524		return -1;
525	}
526
527	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE,
528			       RADIUS_VENDOR_ID_MICROSOFT, 1,
529			       challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN);
530
531	/* MS-CHAP-Response */
532	pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_RESPONSE,
533			       RADIUS_VENDOR_ID_MICROSOFT, 1,
534			       EAP_TTLS_MSCHAP_RESPONSE_LEN);
535	data->ident = challenge[EAP_TTLS_MSCHAP_CHALLENGE_LEN];
536	*pos++ = data->ident;
537	*pos++ = 1; /* Flags: Use NT style passwords */
538	os_memset(pos, 0, 24); /* LM-Response */
539	pos += 24;
540	if (pwhash) {
541		challenge_response(challenge, password, pos); /* NT-Response */
542		wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password hash",
543				password, 16);
544	} else {
545		nt_challenge_response(challenge, password, password_len,
546				      pos); /* NT-Response */
547		wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password",
548				      password, password_len);
549	}
550	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP implicit challenge",
551		    challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN);
552	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP response", pos, 24);
553	pos += 24;
554	os_free(challenge);
555	AVP_PAD(buf, pos);
556
557	wpabuf_put(msg, pos - buf);
558	*resp = msg;
559
560	/* EAP-TTLS/MSCHAP does not provide tunneled success
561	 * notification, so assume that Phase2 succeeds. */
562	ret->methodState = METHOD_DONE;
563	ret->decision = DECISION_COND_SUCC;
564
565	return 0;
566}
567
568
569static int eap_ttls_phase2_request_pap(struct eap_sm *sm,
570				       struct eap_ttls_data *data,
571				       struct eap_method_ret *ret,
572				       struct wpabuf **resp)
573{
574	struct wpabuf *msg;
575	u8 *buf, *pos;
576	size_t pad;
577	const u8 *identity, *password;
578	size_t identity_len, password_len;
579
580	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 PAP Request");
581
582	identity = eap_get_config_identity(sm, &identity_len);
583	password = eap_get_config_password(sm, &password_len);
584	if (identity == NULL || password == NULL)
585		return -1;
586
587	msg = wpabuf_alloc(identity_len + password_len + 100);
588	if (msg == NULL) {
589		wpa_printf(MSG_ERROR,
590			   "EAP-TTLS/PAP: Failed to allocate memory");
591		return -1;
592	}
593	pos = buf = wpabuf_mhead(msg);
594
595	/* User-Name */
596	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
597			       identity, identity_len);
598
599	/* User-Password; in RADIUS, this is encrypted, but EAP-TTLS encrypts
600	 * the data, so no separate encryption is used in the AVP itself.
601	 * However, the password is padded to obfuscate its length. */
602	pad = password_len == 0 ? 16 : (16 - (password_len & 15)) & 15;
603	pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_USER_PASSWORD, 0, 1,
604			       password_len + pad);
605	os_memcpy(pos, password, password_len);
606	pos += password_len;
607	os_memset(pos, 0, pad);
608	pos += pad;
609	AVP_PAD(buf, pos);
610
611	wpabuf_put(msg, pos - buf);
612	*resp = msg;
613
614	/* EAP-TTLS/PAP does not provide tunneled success notification,
615	 * so assume that Phase2 succeeds. */
616	ret->methodState = METHOD_DONE;
617	ret->decision = DECISION_COND_SUCC;
618
619	return 0;
620}
621
622
623static int eap_ttls_phase2_request_chap(struct eap_sm *sm,
624					struct eap_ttls_data *data,
625					struct eap_method_ret *ret,
626					struct wpabuf **resp)
627{
628	struct wpabuf *msg;
629	u8 *buf, *pos, *challenge;
630	const u8 *identity, *password;
631	size_t identity_len, password_len;
632
633	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request");
634
635	identity = eap_get_config_identity(sm, &identity_len);
636	password = eap_get_config_password(sm, &password_len);
637	if (identity == NULL || password == NULL)
638		return -1;
639
640	msg = wpabuf_alloc(identity_len + 1000);
641	if (msg == NULL) {
642		wpa_printf(MSG_ERROR,
643			   "EAP-TTLS/CHAP: Failed to allocate memory");
644		return -1;
645	}
646	pos = buf = wpabuf_mhead(msg);
647
648	/* User-Name */
649	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
650			       identity, identity_len);
651
652	/* CHAP-Challenge */
653	challenge = eap_ttls_implicit_challenge(
654		sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1);
655	if (challenge == NULL) {
656		wpabuf_free(msg);
657		wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive "
658			   "implicit challenge");
659		return -1;
660	}
661
662	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_CHAP_CHALLENGE, 0, 1,
663			       challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);
664
665	/* CHAP-Password */
666	pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_CHAP_PASSWORD, 0, 1,
667			       1 + EAP_TTLS_CHAP_PASSWORD_LEN);
668	data->ident = challenge[EAP_TTLS_CHAP_CHALLENGE_LEN];
669	*pos++ = data->ident;
670
671	/* MD5(Ident + Password + Challenge) */
672	chap_md5(data->ident, password, password_len, challenge,
673		 EAP_TTLS_CHAP_CHALLENGE_LEN, pos);
674
675	wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: CHAP username",
676			  identity, identity_len);
677	wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: CHAP password",
678			      password, password_len);
679	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP implicit challenge",
680		    challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);
681	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP password",
682		    pos, EAP_TTLS_CHAP_PASSWORD_LEN);
683	pos += EAP_TTLS_CHAP_PASSWORD_LEN;
684	os_free(challenge);
685	AVP_PAD(buf, pos);
686
687	wpabuf_put(msg, pos - buf);
688	*resp = msg;
689
690	/* EAP-TTLS/CHAP does not provide tunneled success
691	 * notification, so assume that Phase2 succeeds. */
692	ret->methodState = METHOD_DONE;
693	ret->decision = DECISION_COND_SUCC;
694
695	return 0;
696}
697
698
699static int eap_ttls_phase2_request(struct eap_sm *sm,
700				   struct eap_ttls_data *data,
701				   struct eap_method_ret *ret,
702				   struct eap_hdr *hdr,
703				   struct wpabuf **resp)
704{
705	int res = 0;
706	size_t len;
707	enum phase2_types phase2_type = data->phase2_type;
708
709#ifdef EAP_TNC
710	if (data->tnc_started) {
711		wpa_printf(MSG_DEBUG, "EAP-TTLS: Processing TNC");
712		phase2_type = EAP_TTLS_PHASE2_EAP;
713	}
714#endif /* EAP_TNC */
715
716	if (phase2_type == EAP_TTLS_PHASE2_MSCHAPV2 ||
717	    phase2_type == EAP_TTLS_PHASE2_MSCHAP ||
718	    phase2_type == EAP_TTLS_PHASE2_PAP ||
719	    phase2_type == EAP_TTLS_PHASE2_CHAP) {
720		if (eap_get_config_identity(sm, &len) == NULL) {
721			wpa_printf(MSG_INFO,
722				   "EAP-TTLS: Identity not configured");
723			eap_sm_request_identity(sm);
724			if (eap_get_config_password(sm, &len) == NULL)
725				eap_sm_request_password(sm);
726			return 0;
727		}
728
729		if (eap_get_config_password(sm, &len) == NULL) {
730			wpa_printf(MSG_INFO,
731				   "EAP-TTLS: Password not configured");
732			eap_sm_request_password(sm);
733			return 0;
734		}
735	}
736
737	switch (phase2_type) {
738	case EAP_TTLS_PHASE2_EAP:
739		res = eap_ttls_phase2_request_eap(sm, data, ret, hdr, resp);
740		break;
741	case EAP_TTLS_PHASE2_MSCHAPV2:
742		res = eap_ttls_phase2_request_mschapv2(sm, data, ret, resp);
743		break;
744	case EAP_TTLS_PHASE2_MSCHAP:
745		res = eap_ttls_phase2_request_mschap(sm, data, ret, resp);
746		break;
747	case EAP_TTLS_PHASE2_PAP:
748		res = eap_ttls_phase2_request_pap(sm, data, ret, resp);
749		break;
750	case EAP_TTLS_PHASE2_CHAP:
751		res = eap_ttls_phase2_request_chap(sm, data, ret, resp);
752		break;
753	default:
754		wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 - Unknown");
755		res = -1;
756		break;
757	}
758
759	if (res < 0) {
760		ret->methodState = METHOD_DONE;
761		ret->decision = DECISION_FAIL;
762	}
763
764	return res;
765}
766
767
768struct ttls_parse_avp {
769	u8 *mschapv2;
770	u8 *eapdata;
771	size_t eap_len;
772	int mschapv2_error;
773};
774
775
776static int eap_ttls_parse_attr_eap(const u8 *dpos, size_t dlen,
777				   struct ttls_parse_avp *parse)
778{
779	wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message");
780	if (parse->eapdata == NULL) {
781		parse->eapdata = os_malloc(dlen);
782		if (parse->eapdata == NULL) {
783			wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate "
784				   "memory for Phase 2 EAP data");
785			return -1;
786		}
787		os_memcpy(parse->eapdata, dpos, dlen);
788		parse->eap_len = dlen;
789	} else {
790		u8 *neweap = os_realloc(parse->eapdata, parse->eap_len + dlen);
791		if (neweap == NULL) {
792			wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate "
793				   "memory for Phase 2 EAP data");
794			return -1;
795		}
796		os_memcpy(neweap + parse->eap_len, dpos, dlen);
797		parse->eapdata = neweap;
798		parse->eap_len += dlen;
799	}
800
801	return 0;
802}
803
804
805static int eap_ttls_parse_avp(u8 *pos, size_t left,
806			      struct ttls_parse_avp *parse)
807{
808	struct ttls_avp *avp;
809	u32 avp_code, avp_length, vendor_id = 0;
810	u8 avp_flags, *dpos;
811	size_t dlen;
812
813	avp = (struct ttls_avp *) pos;
814	avp_code = be_to_host32(avp->avp_code);
815	avp_length = be_to_host32(avp->avp_length);
816	avp_flags = (avp_length >> 24) & 0xff;
817	avp_length &= 0xffffff;
818	wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x "
819		   "length=%d", (int) avp_code, avp_flags,
820		   (int) avp_length);
821
822	if (avp_length > left) {
823		wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow "
824			   "(len=%d, left=%lu) - dropped",
825			   (int) avp_length, (unsigned long) left);
826		return -1;
827	}
828
829	if (avp_length < sizeof(*avp)) {
830		wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length %d",
831			   avp_length);
832		return -1;
833	}
834
835	dpos = (u8 *) (avp + 1);
836	dlen = avp_length - sizeof(*avp);
837	if (avp_flags & AVP_FLAGS_VENDOR) {
838		if (dlen < 4) {
839			wpa_printf(MSG_WARNING, "EAP-TTLS: Vendor AVP "
840				   "underflow");
841			return -1;
842		}
843		vendor_id = WPA_GET_BE32(dpos);
844		wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d",
845			   (int) vendor_id);
846		dpos += 4;
847		dlen -= 4;
848	}
849
850	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen);
851
852	if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) {
853		if (eap_ttls_parse_attr_eap(dpos, dlen, parse) < 0)
854			return -1;
855	} else if (vendor_id == 0 && avp_code == RADIUS_ATTR_REPLY_MESSAGE) {
856		/* This is an optional message that can be displayed to
857		 * the user. */
858		wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: AVP - Reply-Message",
859				  dpos, dlen);
860	} else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
861		   avp_code == RADIUS_ATTR_MS_CHAP2_SUCCESS) {
862		wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MS-CHAP2-Success",
863				  dpos, dlen);
864		if (dlen != 43) {
865			wpa_printf(MSG_WARNING, "EAP-TTLS: Unexpected "
866				   "MS-CHAP2-Success length "
867				   "(len=%lu, expected 43)",
868				   (unsigned long) dlen);
869			return -1;
870		}
871		parse->mschapv2 = dpos;
872	} else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
873		   avp_code == RADIUS_ATTR_MS_CHAP_ERROR) {
874		wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MS-CHAP-Error",
875				  dpos, dlen);
876		parse->mschapv2_error = 1;
877	} else if (avp_flags & AVP_FLAGS_MANDATORY) {
878		wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported mandatory AVP "
879			   "code %d vendor_id %d - dropped",
880			   (int) avp_code, (int) vendor_id);
881		return -1;
882	} else {
883		wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported AVP "
884			   "code %d vendor_id %d",
885			   (int) avp_code, (int) vendor_id);
886	}
887
888	return avp_length;
889}
890
891
892static int eap_ttls_parse_avps(struct wpabuf *in_decrypted,
893			       struct ttls_parse_avp *parse)
894{
895	u8 *pos;
896	size_t left, pad;
897	int avp_length;
898
899	pos = wpabuf_mhead(in_decrypted);
900	left = wpabuf_len(in_decrypted);
901	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 AVPs", pos, left);
902	if (left < sizeof(struct ttls_avp)) {
903		wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 AVP frame"
904			   " len=%lu expected %lu or more - dropped",
905			   (unsigned long) left,
906			   (unsigned long) sizeof(struct ttls_avp));
907		return -1;
908	}
909
910	/* Parse AVPs */
911	os_memset(parse, 0, sizeof(*parse));
912
913	while (left > 0) {
914		avp_length = eap_ttls_parse_avp(pos, left, parse);
915		if (avp_length < 0)
916			return -1;
917
918		pad = (4 - (avp_length & 3)) & 3;
919		pos += avp_length + pad;
920		if (left < avp_length + pad)
921			left = 0;
922		else
923			left -= avp_length + pad;
924	}
925
926	return 0;
927}
928
929
930static u8 * eap_ttls_fake_identity_request(void)
931{
932	struct eap_hdr *hdr;
933	u8 *buf;
934
935	wpa_printf(MSG_DEBUG, "EAP-TTLS: empty data in beginning of "
936		   "Phase 2 - use fake EAP-Request Identity");
937	buf = os_malloc(sizeof(*hdr) + 1);
938	if (buf == NULL) {
939		wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate "
940			   "memory for fake EAP-Identity Request");
941		return NULL;
942	}
943
944	hdr = (struct eap_hdr *) buf;
945	hdr->code = EAP_CODE_REQUEST;
946	hdr->identifier = 0;
947	hdr->length = host_to_be16(sizeof(*hdr) + 1);
948	buf[sizeof(*hdr)] = EAP_TYPE_IDENTITY;
949
950	return buf;
951}
952
953
954static int eap_ttls_encrypt_response(struct eap_sm *sm,
955				     struct eap_ttls_data *data,
956				     struct wpabuf *resp, u8 identifier,
957				     struct wpabuf **out_data)
958{
959	if (resp == NULL)
960		return 0;
961
962	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Encrypting Phase 2 data",
963			    resp);
964	if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS,
965				 data->ttls_version, identifier,
966				 resp, out_data)) {
967		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt a Phase 2 "
968			   "frame");
969		return -1;
970	}
971	wpabuf_free(resp);
972
973	return 0;
974}
975
976
977static int eap_ttls_process_phase2_eap(struct eap_sm *sm,
978				       struct eap_ttls_data *data,
979				       struct eap_method_ret *ret,
980				       struct ttls_parse_avp *parse,
981				       struct wpabuf **resp)
982{
983	struct eap_hdr *hdr;
984	size_t len;
985
986	if (parse->eapdata == NULL) {
987		wpa_printf(MSG_WARNING, "EAP-TTLS: No EAP Message in the "
988			   "packet - dropped");
989		return -1;
990	}
991
992	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP",
993		    parse->eapdata, parse->eap_len);
994	hdr = (struct eap_hdr *) parse->eapdata;
995
996	if (parse->eap_len < sizeof(*hdr)) {
997		wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 EAP "
998			   "frame (len=%lu, expected %lu or more) - dropped",
999			   (unsigned long) parse->eap_len,
1000			   (unsigned long) sizeof(*hdr));
1001		return -1;
1002	}
1003	len = be_to_host16(hdr->length);
1004	if (len > parse->eap_len) {
1005		wpa_printf(MSG_INFO, "EAP-TTLS: Length mismatch in Phase 2 "
1006			   "EAP frame (EAP hdr len=%lu, EAP data len in "
1007			   "AVP=%lu)",
1008			   (unsigned long) len,
1009			   (unsigned long) parse->eap_len);
1010		return -1;
1011	}
1012	wpa_printf(MSG_DEBUG, "EAP-TTLS: received Phase 2: code=%d "
1013		   "identifier=%d length=%lu",
1014		   hdr->code, hdr->identifier, (unsigned long) len);
1015	switch (hdr->code) {
1016	case EAP_CODE_REQUEST:
1017		if (eap_ttls_phase2_request(sm, data, ret, hdr, resp)) {
1018			wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request "
1019				   "processing failed");
1020			return -1;
1021		}
1022		break;
1023	default:
1024		wpa_printf(MSG_INFO, "EAP-TTLS: Unexpected code=%d in "
1025			   "Phase 2 EAP header", hdr->code);
1026		return -1;
1027	}
1028
1029	return 0;
1030}
1031
1032
1033static int eap_ttls_process_phase2_mschapv2(struct eap_sm *sm,
1034					    struct eap_ttls_data *data,
1035					    struct eap_method_ret *ret,
1036					    struct ttls_parse_avp *parse)
1037{
1038	if (parse->mschapv2_error) {
1039		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Received "
1040			   "MS-CHAP-Error - failed");
1041		ret->methodState = METHOD_DONE;
1042		ret->decision = DECISION_FAIL;
1043		/* Reply with empty data to ACK error */
1044		return 1;
1045	}
1046
1047	if (parse->mschapv2 == NULL) {
1048#ifdef EAP_TNC
1049		if (data->phase2_success && parse->eapdata) {
1050			/*
1051			 * Allow EAP-TNC to be started after successfully
1052			 * completed MSCHAPV2.
1053			 */
1054			return 1;
1055		}
1056#endif /* EAP_TNC */
1057		wpa_printf(MSG_WARNING, "EAP-TTLS: no MS-CHAP2-Success AVP "
1058			   "received for Phase2 MSCHAPV2");
1059		return -1;
1060	}
1061	if (parse->mschapv2[0] != data->ident) {
1062		wpa_printf(MSG_WARNING, "EAP-TTLS: Ident mismatch for Phase 2 "
1063			   "MSCHAPV2 (received Ident 0x%02x, expected 0x%02x)",
1064			   parse->mschapv2[0], data->ident);
1065		return -1;
1066	}
1067	if (!data->auth_response_valid ||
1068	    mschapv2_verify_auth_response(data->auth_response,
1069					  parse->mschapv2 + 1, 42)) {
1070		wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid authenticator "
1071			   "response in Phase 2 MSCHAPV2 success request");
1072		return -1;
1073	}
1074
1075	wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 MSCHAPV2 "
1076		   "authentication succeeded");
1077	ret->methodState = METHOD_DONE;
1078	ret->decision = DECISION_UNCOND_SUCC;
1079	data->phase2_success = 1;
1080
1081	/*
1082	 * Reply with empty data; authentication server will reply
1083	 * with EAP-Success after this.
1084	 */
1085	return 1;
1086}
1087
1088
1089#ifdef EAP_TNC
1090static int eap_ttls_process_tnc_start(struct eap_sm *sm,
1091				      struct eap_ttls_data *data,
1092				      struct eap_method_ret *ret,
1093				      struct ttls_parse_avp *parse,
1094				      struct wpabuf **resp)
1095{
1096	/* TNC uses inner EAP method after non-EAP TTLS phase 2. */
1097	if (parse->eapdata == NULL) {
1098		wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received "
1099			   "unexpected tunneled data (no EAP)");
1100		return -1;
1101	}
1102
1103	if (!data->ready_for_tnc) {
1104		wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received "
1105			   "EAP after non-EAP, but not ready for TNC");
1106		return -1;
1107	}
1108
1109	wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed "
1110		   "non-EAP method");
1111	data->tnc_started = 1;
1112
1113	if (eap_ttls_process_phase2_eap(sm, data, ret, parse, resp) < 0)
1114		return -1;
1115
1116	return 0;
1117}
1118#endif /* EAP_TNC */
1119
1120
1121static int eap_ttls_process_decrypted(struct eap_sm *sm,
1122				      struct eap_ttls_data *data,
1123				      struct eap_method_ret *ret,
1124				      u8 identifier,
1125				      struct ttls_parse_avp *parse,
1126				      struct wpabuf *in_decrypted,
1127				      struct wpabuf **out_data)
1128{
1129	struct wpabuf *resp = NULL;
1130	struct eap_peer_config *config = eap_get_config(sm);
1131	int res;
1132	enum phase2_types phase2_type = data->phase2_type;
1133
1134#ifdef EAP_TNC
1135	if (data->tnc_started)
1136		phase2_type = EAP_TTLS_PHASE2_EAP;
1137#endif /* EAP_TNC */
1138
1139	switch (phase2_type) {
1140	case EAP_TTLS_PHASE2_EAP:
1141		if (eap_ttls_process_phase2_eap(sm, data, ret, parse, &resp) <
1142		    0)
1143			return -1;
1144		break;
1145	case EAP_TTLS_PHASE2_MSCHAPV2:
1146		res = eap_ttls_process_phase2_mschapv2(sm, data, ret, parse);
1147#ifdef EAP_TNC
1148		if (res == 1 && parse->eapdata && data->phase2_success) {
1149			/*
1150			 * TNC may be required as the next
1151			 * authentication method within the tunnel.
1152			 */
1153			ret->methodState = METHOD_MAY_CONT;
1154			data->ready_for_tnc = 1;
1155			if (eap_ttls_process_tnc_start(sm, data, ret, parse,
1156						       &resp) == 0)
1157				break;
1158		}
1159#endif /* EAP_TNC */
1160		return res;
1161	case EAP_TTLS_PHASE2_MSCHAP:
1162	case EAP_TTLS_PHASE2_PAP:
1163	case EAP_TTLS_PHASE2_CHAP:
1164#ifdef EAP_TNC
1165		if (eap_ttls_process_tnc_start(sm, data, ret, parse, &resp) <
1166		    0)
1167			return -1;
1168		break;
1169#else /* EAP_TNC */
1170		/* EAP-TTLS/{MSCHAP,PAP,CHAP} should not send any TLS tunneled
1171		 * requests to the supplicant */
1172		wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received unexpected "
1173			   "tunneled data");
1174		return -1;
1175#endif /* EAP_TNC */
1176	}
1177
1178	if (resp) {
1179		if (eap_ttls_encrypt_response(sm, data, resp, identifier,
1180					      out_data) < 0)
1181			return -1;
1182	} else if (config->pending_req_identity ||
1183		   config->pending_req_password ||
1184		   config->pending_req_otp ||
1185		   config->pending_req_new_password) {
1186		wpabuf_free(data->pending_phase2_req);
1187		data->pending_phase2_req = wpabuf_dup(in_decrypted);
1188	}
1189
1190	return 0;
1191}
1192
1193
1194static int eap_ttls_implicit_identity_request(struct eap_sm *sm,
1195					      struct eap_ttls_data *data,
1196					      struct eap_method_ret *ret,
1197					      u8 identifier,
1198					      struct wpabuf **out_data)
1199{
1200	int retval = 0;
1201	struct eap_hdr *hdr;
1202	struct wpabuf *resp;
1203
1204	hdr = (struct eap_hdr *) eap_ttls_fake_identity_request();
1205	if (hdr == NULL) {
1206		ret->methodState = METHOD_DONE;
1207		ret->decision = DECISION_FAIL;
1208		return -1;
1209	}
1210
1211	resp = NULL;
1212	if (eap_ttls_phase2_request(sm, data, ret, hdr, &resp)) {
1213		wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request "
1214			   "processing failed");
1215		retval = -1;
1216	} else {
1217		struct eap_peer_config *config = eap_get_config(sm);
1218		if (resp == NULL &&
1219		    (config->pending_req_identity ||
1220		     config->pending_req_password ||
1221		     config->pending_req_otp ||
1222		     config->pending_req_new_password)) {
1223			/*
1224			 * Use empty buffer to force implicit request
1225			 * processing when EAP request is re-processed after
1226			 * user input.
1227			 */
1228			wpabuf_free(data->pending_phase2_req);
1229			data->pending_phase2_req = wpabuf_alloc(0);
1230		}
1231
1232		retval = eap_ttls_encrypt_response(sm, data, resp, identifier,
1233						   out_data);
1234	}
1235
1236	os_free(hdr);
1237
1238	if (retval < 0) {
1239		ret->methodState = METHOD_DONE;
1240		ret->decision = DECISION_FAIL;
1241	}
1242
1243	return retval;
1244}
1245
1246
1247static int eap_ttls_phase2_start(struct eap_sm *sm, struct eap_ttls_data *data,
1248				 struct eap_method_ret *ret, u8 identifier,
1249				 struct wpabuf **out_data)
1250{
1251	data->phase2_start = 0;
1252
1253	/*
1254	 * EAP-TTLS does not use Phase2 on fast re-auth; this must be done only
1255	 * if TLS part was indeed resuming a previous session. Most
1256	 * Authentication Servers terminate EAP-TTLS before reaching this
1257	 * point, but some do not. Make wpa_supplicant stop phase 2 here, if
1258	 * needed.
1259	 */
1260	if (data->reauth &&
1261	    tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {
1262		wpa_printf(MSG_DEBUG, "EAP-TTLS: Session resumption - "
1263			   "skip phase 2");
1264		*out_data = eap_peer_tls_build_ack(identifier, EAP_TYPE_TTLS,
1265						   data->ttls_version);
1266		ret->methodState = METHOD_DONE;
1267		ret->decision = DECISION_UNCOND_SUCC;
1268		data->phase2_success = 1;
1269		return 0;
1270	}
1271
1272	return eap_ttls_implicit_identity_request(sm, data, ret, identifier,
1273						  out_data);
1274}
1275
1276
1277static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
1278			    struct eap_method_ret *ret, u8 identifier,
1279			    const struct wpabuf *in_data,
1280			    struct wpabuf **out_data)
1281{
1282	struct wpabuf *in_decrypted = NULL;
1283	int retval = 0;
1284	struct ttls_parse_avp parse;
1285
1286	os_memset(&parse, 0, sizeof(parse));
1287
1288	wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
1289		   " Phase 2",
1290		   in_data ? (unsigned long) wpabuf_len(in_data) : 0);
1291
1292	if (data->pending_phase2_req) {
1293		wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 request - "
1294			   "skip decryption and use old data");
1295		/* Clear TLS reassembly state. */
1296		eap_peer_tls_reset_input(&data->ssl);
1297
1298		in_decrypted = data->pending_phase2_req;
1299		data->pending_phase2_req = NULL;
1300		if (wpabuf_len(in_decrypted) == 0) {
1301			wpabuf_free(in_decrypted);
1302			return eap_ttls_implicit_identity_request(
1303				sm, data, ret, identifier, out_data);
1304		}
1305		goto continue_req;
1306	}
1307
1308	if ((in_data == NULL || wpabuf_len(in_data) == 0) &&
1309	    data->phase2_start) {
1310		return eap_ttls_phase2_start(sm, data, ret, identifier,
1311					     out_data);
1312	}
1313
1314	if (in_data == NULL || wpabuf_len(in_data) == 0) {
1315		/* Received TLS ACK - requesting more fragments */
1316		return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS,
1317					    data->ttls_version,
1318					    identifier, NULL, out_data);
1319	}
1320
1321	retval = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
1322	if (retval)
1323		goto done;
1324
1325continue_req:
1326	data->phase2_start = 0;
1327
1328	if (eap_ttls_parse_avps(in_decrypted, &parse) < 0) {
1329		retval = -1;
1330		goto done;
1331	}
1332
1333	retval = eap_ttls_process_decrypted(sm, data, ret, identifier,
1334					    &parse, in_decrypted, out_data);
1335
1336done:
1337	wpabuf_free(in_decrypted);
1338	os_free(parse.eapdata);
1339
1340	if (retval < 0) {
1341		ret->methodState = METHOD_DONE;
1342		ret->decision = DECISION_FAIL;
1343	}
1344
1345	return retval;
1346}
1347
1348
1349static int eap_ttls_process_handshake(struct eap_sm *sm,
1350				      struct eap_ttls_data *data,
1351				      struct eap_method_ret *ret,
1352				      u8 identifier,
1353				      const u8 *in_data, size_t in_len,
1354				      struct wpabuf **out_data)
1355{
1356	int res;
1357
1358	res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS,
1359					  data->ttls_version, identifier,
1360					  in_data, in_len, out_data);
1361
1362	if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
1363		wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to "
1364			   "Phase 2");
1365		if (data->resuming) {
1366			wpa_printf(MSG_DEBUG, "EAP-TTLS: fast reauth - may "
1367				   "skip Phase 2");
1368			ret->decision = DECISION_COND_SUCC;
1369			ret->methodState = METHOD_MAY_CONT;
1370		}
1371		data->phase2_start = 1;
1372		eap_ttls_v0_derive_key(sm, data);
1373
1374		if (*out_data == NULL || wpabuf_len(*out_data) == 0) {
1375			if (eap_ttls_decrypt(sm, data, ret, identifier,
1376					     NULL, out_data)) {
1377				wpa_printf(MSG_WARNING, "EAP-TTLS: "
1378					   "failed to process early "
1379					   "start for Phase 2");
1380			}
1381			res = 0;
1382		}
1383		data->resuming = 0;
1384	}
1385
1386	if (res == 2) {
1387		struct wpabuf msg;
1388		/*
1389		 * Application data included in the handshake message.
1390		 */
1391		wpabuf_free(data->pending_phase2_req);
1392		data->pending_phase2_req = *out_data;
1393		*out_data = NULL;
1394		wpabuf_set(&msg, in_data, in_len);
1395		res = eap_ttls_decrypt(sm, data, ret, identifier, &msg,
1396				       out_data);
1397	}
1398
1399	return res;
1400}
1401
1402
1403static void eap_ttls_check_auth_status(struct eap_sm *sm,
1404				       struct eap_ttls_data *data,
1405				       struct eap_method_ret *ret)
1406{
1407	if (ret->methodState == METHOD_DONE) {
1408		ret->allowNotifications = FALSE;
1409		if (ret->decision == DECISION_UNCOND_SUCC ||
1410		    ret->decision == DECISION_COND_SUCC) {
1411			wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
1412				   "completed successfully");
1413			data->phase2_success = 1;
1414#ifdef EAP_TNC
1415			if (!data->ready_for_tnc && !data->tnc_started) {
1416				/*
1417				 * TNC may be required as the next
1418				 * authentication method within the tunnel.
1419				 */
1420				ret->methodState = METHOD_MAY_CONT;
1421				data->ready_for_tnc = 1;
1422			}
1423#endif /* EAP_TNC */
1424		}
1425	} else if (ret->methodState == METHOD_MAY_CONT &&
1426		   (ret->decision == DECISION_UNCOND_SUCC ||
1427		    ret->decision == DECISION_COND_SUCC)) {
1428			wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
1429				   "completed successfully (MAY_CONT)");
1430			data->phase2_success = 1;
1431	}
1432}
1433
1434
1435static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv,
1436					struct eap_method_ret *ret,
1437					const struct wpabuf *reqData)
1438{
1439	size_t left;
1440	int res;
1441	u8 flags, id;
1442	struct wpabuf *resp;
1443	const u8 *pos;
1444	struct eap_ttls_data *data = priv;
1445
1446	pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TTLS, ret,
1447					reqData, &left, &flags);
1448	if (pos == NULL)
1449		return NULL;
1450	id = eap_get_id(reqData);
1451
1452	if (flags & EAP_TLS_FLAGS_START) {
1453		wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own "
1454			   "ver=%d)", flags & EAP_TLS_VERSION_MASK,
1455			   data->ttls_version);
1456
1457		/* RFC 5281, Ch. 9.2:
1458		 * "This packet MAY contain additional information in the form
1459		 * of AVPs, which may provide useful hints to the client"
1460		 * For now, ignore any potential extra data.
1461		 */
1462		left = 0;
1463	}
1464
1465	resp = NULL;
1466	if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
1467	    !data->resuming) {
1468		struct wpabuf msg;
1469		wpabuf_set(&msg, pos, left);
1470		res = eap_ttls_decrypt(sm, data, ret, id, &msg, &resp);
1471	} else {
1472		res = eap_ttls_process_handshake(sm, data, ret, id,
1473						 pos, left, &resp);
1474	}
1475
1476	eap_ttls_check_auth_status(sm, data, ret);
1477
1478	/* FIX: what about res == -1? Could just move all error processing into
1479	 * the other functions and get rid of this res==1 case here. */
1480	if (res == 1) {
1481		wpabuf_free(resp);
1482		return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS,
1483					      data->ttls_version);
1484	}
1485	return resp;
1486}
1487
1488
1489static Boolean eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv)
1490{
1491	struct eap_ttls_data *data = priv;
1492	return tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
1493		data->phase2_success;
1494}
1495
1496
1497static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
1498{
1499	struct eap_ttls_data *data = priv;
1500	wpabuf_free(data->pending_phase2_req);
1501	data->pending_phase2_req = NULL;
1502#ifdef EAP_TNC
1503	data->ready_for_tnc = 0;
1504	data->tnc_started = 0;
1505#endif /* EAP_TNC */
1506}
1507
1508
1509static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv)
1510{
1511	struct eap_ttls_data *data = priv;
1512	os_free(data->key_data);
1513	data->key_data = NULL;
1514	if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
1515		os_free(data);
1516		return NULL;
1517	}
1518	if (data->phase2_priv && data->phase2_method &&
1519	    data->phase2_method->init_for_reauth)
1520		data->phase2_method->init_for_reauth(sm, data->phase2_priv);
1521	data->phase2_start = 0;
1522	data->phase2_success = 0;
1523	data->resuming = 1;
1524	data->reauth = 1;
1525	return priv;
1526}
1527
1528
1529static int eap_ttls_get_status(struct eap_sm *sm, void *priv, char *buf,
1530			       size_t buflen, int verbose)
1531{
1532	struct eap_ttls_data *data = priv;
1533	int len, ret;
1534
1535	len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
1536	ret = os_snprintf(buf + len, buflen - len,
1537			  "EAP-TTLSv%d Phase2 method=",
1538			  data->ttls_version);
1539	if (ret < 0 || (size_t) ret >= buflen - len)
1540		return len;
1541	len += ret;
1542	switch (data->phase2_type) {
1543	case EAP_TTLS_PHASE2_EAP:
1544		ret = os_snprintf(buf + len, buflen - len, "EAP-%s\n",
1545				  data->phase2_method ?
1546				  data->phase2_method->name : "?");
1547		break;
1548	case EAP_TTLS_PHASE2_MSCHAPV2:
1549		ret = os_snprintf(buf + len, buflen - len, "MSCHAPV2\n");
1550		break;
1551	case EAP_TTLS_PHASE2_MSCHAP:
1552		ret = os_snprintf(buf + len, buflen - len, "MSCHAP\n");
1553		break;
1554	case EAP_TTLS_PHASE2_PAP:
1555		ret = os_snprintf(buf + len, buflen - len, "PAP\n");
1556		break;
1557	case EAP_TTLS_PHASE2_CHAP:
1558		ret = os_snprintf(buf + len, buflen - len, "CHAP\n");
1559		break;
1560	default:
1561		ret = 0;
1562		break;
1563	}
1564	if (ret < 0 || (size_t) ret >= buflen - len)
1565		return len;
1566	len += ret;
1567
1568	return len;
1569}
1570
1571
1572static Boolean eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv)
1573{
1574	struct eap_ttls_data *data = priv;
1575	return data->key_data != NULL && data->phase2_success;
1576}
1577
1578
1579static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
1580{
1581	struct eap_ttls_data *data = priv;
1582	u8 *key;
1583
1584	if (data->key_data == NULL || !data->phase2_success)
1585		return NULL;
1586
1587	key = os_malloc(EAP_TLS_KEY_LEN);
1588	if (key == NULL)
1589		return NULL;
1590
1591	*len = EAP_TLS_KEY_LEN;
1592	os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
1593
1594	return key;
1595}
1596
1597
1598int eap_peer_ttls_register(void)
1599{
1600	struct eap_method *eap;
1601	int ret;
1602
1603	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1604				    EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS");
1605	if (eap == NULL)
1606		return -1;
1607
1608	eap->init = eap_ttls_init;
1609	eap->deinit = eap_ttls_deinit;
1610	eap->process = eap_ttls_process;
1611	eap->isKeyAvailable = eap_ttls_isKeyAvailable;
1612	eap->getKey = eap_ttls_getKey;
1613	eap->get_status = eap_ttls_get_status;
1614	eap->has_reauth_data = eap_ttls_has_reauth_data;
1615	eap->deinit_for_reauth = eap_ttls_deinit_for_reauth;
1616	eap->init_for_reauth = eap_ttls_init_for_reauth;
1617
1618	ret = eap_peer_method_register(eap);
1619	if (ret)
1620		eap_peer_method_free(eap);
1621	return ret;
1622}
1623