1206b73d0SCy Schubert /*
2206b73d0SCy Schubert * EAP-TEAP common helper functions (RFC 7170)
3206b73d0SCy Schubert * Copyright (c) 2008-2019, Jouni Malinen <j@w1.fi>
4206b73d0SCy Schubert *
5206b73d0SCy Schubert * This software may be distributed under the terms of the BSD license.
6206b73d0SCy Schubert * See README for more details.
7206b73d0SCy Schubert */
8206b73d0SCy Schubert
9206b73d0SCy Schubert #include "includes.h"
10206b73d0SCy Schubert
11206b73d0SCy Schubert #include "common.h"
12206b73d0SCy Schubert #include "crypto/sha1.h"
13206b73d0SCy Schubert #include "crypto/sha256.h"
14206b73d0SCy Schubert #include "crypto/sha384.h"
15206b73d0SCy Schubert #include "crypto/tls.h"
16206b73d0SCy Schubert #include "eap_defs.h"
17206b73d0SCy Schubert #include "eap_teap_common.h"
18206b73d0SCy Schubert
19206b73d0SCy Schubert
20*c1d255d3SCy Schubert static int tls_cipher_suite_mac_sha384(u16 cs);
21*c1d255d3SCy Schubert
22*c1d255d3SCy Schubert
eap_teap_put_tlv_hdr(struct wpabuf * buf,u16 type,u16 len)23206b73d0SCy Schubert void eap_teap_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len)
24206b73d0SCy Schubert {
25206b73d0SCy Schubert struct teap_tlv_hdr hdr;
26206b73d0SCy Schubert
27206b73d0SCy Schubert hdr.tlv_type = host_to_be16(type);
28206b73d0SCy Schubert hdr.length = host_to_be16(len);
29206b73d0SCy Schubert wpabuf_put_data(buf, &hdr, sizeof(hdr));
30206b73d0SCy Schubert }
31206b73d0SCy Schubert
32206b73d0SCy Schubert
eap_teap_put_tlv(struct wpabuf * buf,u16 type,const void * data,u16 len)33206b73d0SCy Schubert void eap_teap_put_tlv(struct wpabuf *buf, u16 type, const void *data, u16 len)
34206b73d0SCy Schubert {
35206b73d0SCy Schubert eap_teap_put_tlv_hdr(buf, type, len);
36206b73d0SCy Schubert wpabuf_put_data(buf, data, len);
37206b73d0SCy Schubert }
38206b73d0SCy Schubert
39206b73d0SCy Schubert
eap_teap_put_tlv_buf(struct wpabuf * buf,u16 type,const struct wpabuf * data)40206b73d0SCy Schubert void eap_teap_put_tlv_buf(struct wpabuf *buf, u16 type,
41206b73d0SCy Schubert const struct wpabuf *data)
42206b73d0SCy Schubert {
43206b73d0SCy Schubert eap_teap_put_tlv_hdr(buf, type, wpabuf_len(data));
44206b73d0SCy Schubert wpabuf_put_buf(buf, data);
45206b73d0SCy Schubert }
46206b73d0SCy Schubert
47206b73d0SCy Schubert
eap_teap_tlv_eap_payload(struct wpabuf * buf)48206b73d0SCy Schubert struct wpabuf * eap_teap_tlv_eap_payload(struct wpabuf *buf)
49206b73d0SCy Schubert {
50206b73d0SCy Schubert struct wpabuf *e;
51206b73d0SCy Schubert
52206b73d0SCy Schubert if (!buf)
53206b73d0SCy Schubert return NULL;
54206b73d0SCy Schubert
55206b73d0SCy Schubert /* Encapsulate EAP packet in EAP-Payload TLV */
56206b73d0SCy Schubert wpa_printf(MSG_DEBUG, "EAP-TEAP: Add EAP-Payload TLV");
57206b73d0SCy Schubert e = wpabuf_alloc(sizeof(struct teap_tlv_hdr) + wpabuf_len(buf));
58206b73d0SCy Schubert if (!e) {
59206b73d0SCy Schubert wpa_printf(MSG_ERROR,
60206b73d0SCy Schubert "EAP-TEAP: Failed to allocate memory for TLV encapsulation");
61206b73d0SCy Schubert wpabuf_free(buf);
62206b73d0SCy Schubert return NULL;
63206b73d0SCy Schubert }
64206b73d0SCy Schubert eap_teap_put_tlv_buf(e, TEAP_TLV_MANDATORY | TEAP_TLV_EAP_PAYLOAD, buf);
65206b73d0SCy Schubert wpabuf_free(buf);
66206b73d0SCy Schubert
67206b73d0SCy Schubert /* TODO: followed by optional TLVs associated with the EAP packet */
68206b73d0SCy Schubert
69206b73d0SCy Schubert return e;
70206b73d0SCy Schubert }
71206b73d0SCy Schubert
72206b73d0SCy Schubert
eap_teap_tls_prf(u16 tls_cs,const u8 * secret,size_t secret_len,const char * label,const u8 * seed,size_t seed_len,u8 * out,size_t outlen)73*c1d255d3SCy Schubert static int eap_teap_tls_prf(u16 tls_cs, const u8 *secret, size_t secret_len,
74206b73d0SCy Schubert const char *label, const u8 *seed, size_t seed_len,
75206b73d0SCy Schubert u8 *out, size_t outlen)
76206b73d0SCy Schubert {
77206b73d0SCy Schubert /* TODO: TLS-PRF for TLSv1.3 */
78*c1d255d3SCy Schubert if (tls_cipher_suite_mac_sha384(tls_cs))
79*c1d255d3SCy Schubert return tls_prf_sha384(secret, secret_len, label, seed, seed_len,
80*c1d255d3SCy Schubert out, outlen);
81206b73d0SCy Schubert return tls_prf_sha256(secret, secret_len, label, seed, seed_len,
82206b73d0SCy Schubert out, outlen);
83206b73d0SCy Schubert }
84206b73d0SCy Schubert
85206b73d0SCy Schubert
eap_teap_derive_eap_msk(u16 tls_cs,const u8 * simck,u8 * msk)86*c1d255d3SCy Schubert int eap_teap_derive_eap_msk(u16 tls_cs, const u8 *simck, u8 *msk)
87206b73d0SCy Schubert {
88206b73d0SCy Schubert /*
89206b73d0SCy Schubert * RFC 7170, Section 5.4: EAP Master Session Key Generation
90206b73d0SCy Schubert * MSK = TLS-PRF(S-IMCK[j], "Session Key Generating Function", 64)
91206b73d0SCy Schubert */
92206b73d0SCy Schubert
93*c1d255d3SCy Schubert if (eap_teap_tls_prf(tls_cs, simck, EAP_TEAP_SIMCK_LEN,
94206b73d0SCy Schubert "Session Key Generating Function", (u8 *) "", 0,
95206b73d0SCy Schubert msk, EAP_TEAP_KEY_LEN) < 0)
96206b73d0SCy Schubert return -1;
97206b73d0SCy Schubert wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Derived key (MSK)",
98206b73d0SCy Schubert msk, EAP_TEAP_KEY_LEN);
99206b73d0SCy Schubert return 0;
100206b73d0SCy Schubert }
101206b73d0SCy Schubert
102206b73d0SCy Schubert
eap_teap_derive_eap_emsk(u16 tls_cs,const u8 * simck,u8 * emsk)103*c1d255d3SCy Schubert int eap_teap_derive_eap_emsk(u16 tls_cs, const u8 *simck, u8 *emsk)
104206b73d0SCy Schubert {
105206b73d0SCy Schubert /*
106206b73d0SCy Schubert * RFC 7170, Section 5.4: EAP Master Session Key Generation
107206b73d0SCy Schubert * EMSK = TLS-PRF(S-IMCK[j],
108206b73d0SCy Schubert * "Extended Session Key Generating Function", 64)
109206b73d0SCy Schubert */
110206b73d0SCy Schubert
111*c1d255d3SCy Schubert if (eap_teap_tls_prf(tls_cs, simck, EAP_TEAP_SIMCK_LEN,
112206b73d0SCy Schubert "Extended Session Key Generating Function",
113206b73d0SCy Schubert (u8 *) "", 0, emsk, EAP_EMSK_LEN) < 0)
114206b73d0SCy Schubert return -1;
115206b73d0SCy Schubert wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Derived key (EMSK)",
116206b73d0SCy Schubert emsk, EAP_EMSK_LEN);
117206b73d0SCy Schubert return 0;
118206b73d0SCy Schubert }
119206b73d0SCy Schubert
120206b73d0SCy Schubert
eap_teap_derive_cmk_basic_pw_auth(u16 tls_cs,const u8 * s_imck_msk,u8 * cmk)121*c1d255d3SCy Schubert int eap_teap_derive_cmk_basic_pw_auth(u16 tls_cs, const u8 *s_imck_msk, u8 *cmk)
122206b73d0SCy Schubert {
123206b73d0SCy Schubert u8 imsk[32], imck[EAP_TEAP_IMCK_LEN];
124206b73d0SCy Schubert int res;
125206b73d0SCy Schubert
126206b73d0SCy Schubert /* FIX: The Basic-Password-Auth (i.e., no inner EAP) case is
127206b73d0SCy Schubert * not fully defined in RFC 7170, so this CMK derivation may
128206b73d0SCy Schubert * need to be changed if a fixed definition is eventually
129206b73d0SCy Schubert * published. For now, derive CMK[0] based on S-IMCK[0] and
130206b73d0SCy Schubert * IMSK of 32 octets of zeros. */
131206b73d0SCy Schubert os_memset(imsk, 0, 32);
132*c1d255d3SCy Schubert res = eap_teap_tls_prf(tls_cs, s_imck_msk, EAP_TEAP_SIMCK_LEN,
133206b73d0SCy Schubert "Inner Methods Compound Keys",
134206b73d0SCy Schubert imsk, 32, imck, sizeof(imck));
135206b73d0SCy Schubert if (res < 0)
136206b73d0SCy Schubert return -1;
137206b73d0SCy Schubert os_memcpy(cmk, &imck[EAP_TEAP_SIMCK_LEN], EAP_TEAP_CMK_LEN);
138206b73d0SCy Schubert wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: CMK[no-inner-EAP]",
139206b73d0SCy Schubert cmk, EAP_TEAP_CMK_LEN);
140206b73d0SCy Schubert forced_memzero(imck, sizeof(imck));
141206b73d0SCy Schubert return 0;
142206b73d0SCy Schubert }
143206b73d0SCy Schubert
144206b73d0SCy Schubert
eap_teap_derive_imck(u16 tls_cs,const u8 * prev_s_imck_msk,const u8 * prev_s_imck_emsk,const u8 * msk,size_t msk_len,const u8 * emsk,size_t emsk_len,u8 * s_imck_msk,u8 * cmk_msk,u8 * s_imck_emsk,u8 * cmk_emsk)145*c1d255d3SCy Schubert int eap_teap_derive_imck(u16 tls_cs,
146*c1d255d3SCy Schubert const u8 *prev_s_imck_msk, const u8 *prev_s_imck_emsk,
147206b73d0SCy Schubert const u8 *msk, size_t msk_len,
148206b73d0SCy Schubert const u8 *emsk, size_t emsk_len,
149206b73d0SCy Schubert u8 *s_imck_msk, u8 *cmk_msk,
150206b73d0SCy Schubert u8 *s_imck_emsk, u8 *cmk_emsk)
151206b73d0SCy Schubert {
152206b73d0SCy Schubert u8 imsk[64], imck[EAP_TEAP_IMCK_LEN];
153206b73d0SCy Schubert int res;
154206b73d0SCy Schubert
155206b73d0SCy Schubert /*
156206b73d0SCy Schubert * RFC 7170, Section 5.2:
157206b73d0SCy Schubert * IMSK = First 32 octets of TLS-PRF(EMSK, "TEAPbindkey@ietf.org" |
158206b73d0SCy Schubert * "\0" | 64)
159206b73d0SCy Schubert * (if EMSK is not available, MSK is used instead; if neither is
160206b73d0SCy Schubert * available, IMSK is 32 octets of zeros; MSK is truncated to 32 octets
161206b73d0SCy Schubert * or padded to 32 octets, if needed)
162206b73d0SCy Schubert * (64 is encoded as a 2-octet field in network byte order)
163206b73d0SCy Schubert *
164206b73d0SCy Schubert * S-IMCK[0] = session_key_seed
165206b73d0SCy Schubert * IMCK[j] = TLS-PRF(S-IMCK[j-1], "Inner Methods Compound Keys",
166206b73d0SCy Schubert * IMSK[j], 60)
167206b73d0SCy Schubert * S-IMCK[j] = first 40 octets of IMCK[j]
168206b73d0SCy Schubert * CMK[j] = last 20 octets of IMCK[j]
169206b73d0SCy Schubert */
170206b73d0SCy Schubert
171206b73d0SCy Schubert wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK[j]", msk, msk_len);
172206b73d0SCy Schubert wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK[j]", emsk, emsk_len);
173206b73d0SCy Schubert
174206b73d0SCy Schubert if (emsk && emsk_len > 0) {
175206b73d0SCy Schubert u8 context[3];
176206b73d0SCy Schubert
177206b73d0SCy Schubert context[0] = 0;
178206b73d0SCy Schubert context[1] = 0;
179206b73d0SCy Schubert context[2] = 64;
180*c1d255d3SCy Schubert if (eap_teap_tls_prf(tls_cs, emsk, emsk_len,
181*c1d255d3SCy Schubert "TEAPbindkey@ietf.org",
182206b73d0SCy Schubert context, sizeof(context), imsk, 64) < 0)
183206b73d0SCy Schubert return -1;
184206b73d0SCy Schubert
185206b73d0SCy Schubert wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: IMSK from EMSK",
186206b73d0SCy Schubert imsk, 32);
187206b73d0SCy Schubert
188*c1d255d3SCy Schubert res = eap_teap_tls_prf(tls_cs,
189*c1d255d3SCy Schubert prev_s_imck_emsk, EAP_TEAP_SIMCK_LEN,
190206b73d0SCy Schubert "Inner Methods Compound Keys",
191206b73d0SCy Schubert imsk, 32, imck, EAP_TEAP_IMCK_LEN);
192206b73d0SCy Schubert forced_memzero(imsk, sizeof(imsk));
193206b73d0SCy Schubert if (res < 0)
194206b73d0SCy Schubert return -1;
195206b73d0SCy Schubert
196206b73d0SCy Schubert os_memcpy(s_imck_emsk, imck, EAP_TEAP_SIMCK_LEN);
197206b73d0SCy Schubert wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK S-IMCK[j]",
198206b73d0SCy Schubert s_imck_emsk, EAP_TEAP_SIMCK_LEN);
199206b73d0SCy Schubert os_memcpy(cmk_emsk, &imck[EAP_TEAP_SIMCK_LEN],
200206b73d0SCy Schubert EAP_TEAP_CMK_LEN);
201206b73d0SCy Schubert wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK CMK[j]",
202206b73d0SCy Schubert cmk_emsk, EAP_TEAP_CMK_LEN);
203206b73d0SCy Schubert forced_memzero(imck, EAP_TEAP_IMCK_LEN);
204206b73d0SCy Schubert }
205206b73d0SCy Schubert
206206b73d0SCy Schubert if (msk && msk_len > 0) {
207206b73d0SCy Schubert size_t copy_len = msk_len;
208206b73d0SCy Schubert
209206b73d0SCy Schubert os_memset(imsk, 0, 32); /* zero pad, if needed */
210206b73d0SCy Schubert if (copy_len > 32)
211206b73d0SCy Schubert copy_len = 32;
212206b73d0SCy Schubert os_memcpy(imsk, msk, copy_len);
213206b73d0SCy Schubert wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: IMSK from MSK", imsk, 32);
214206b73d0SCy Schubert } else {
215206b73d0SCy Schubert os_memset(imsk, 0, 32);
216206b73d0SCy Schubert wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Zero IMSK", imsk, 32);
217206b73d0SCy Schubert }
218206b73d0SCy Schubert
219*c1d255d3SCy Schubert res = eap_teap_tls_prf(tls_cs, prev_s_imck_msk, EAP_TEAP_SIMCK_LEN,
220206b73d0SCy Schubert "Inner Methods Compound Keys",
221206b73d0SCy Schubert imsk, 32, imck, EAP_TEAP_IMCK_LEN);
222206b73d0SCy Schubert forced_memzero(imsk, sizeof(imsk));
223206b73d0SCy Schubert if (res < 0)
224206b73d0SCy Schubert return -1;
225206b73d0SCy Schubert
226206b73d0SCy Schubert os_memcpy(s_imck_msk, imck, EAP_TEAP_SIMCK_LEN);
227206b73d0SCy Schubert wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK S-IMCK[j]",
228206b73d0SCy Schubert s_imck_msk, EAP_TEAP_SIMCK_LEN);
229206b73d0SCy Schubert os_memcpy(cmk_msk, &imck[EAP_TEAP_SIMCK_LEN], EAP_TEAP_CMK_LEN);
230206b73d0SCy Schubert wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK CMK[j]",
231206b73d0SCy Schubert cmk_msk, EAP_TEAP_CMK_LEN);
232206b73d0SCy Schubert forced_memzero(imck, EAP_TEAP_IMCK_LEN);
233206b73d0SCy Schubert
234206b73d0SCy Schubert return 0;
235206b73d0SCy Schubert }
236206b73d0SCy Schubert
237206b73d0SCy Schubert
tls_cipher_suite_match(const u16 * list,size_t count,u16 cs)238206b73d0SCy Schubert static int tls_cipher_suite_match(const u16 *list, size_t count, u16 cs)
239206b73d0SCy Schubert {
240206b73d0SCy Schubert size_t i;
241206b73d0SCy Schubert
242206b73d0SCy Schubert for (i = 0; i < count; i++) {
243206b73d0SCy Schubert if (list[i] == cs)
244206b73d0SCy Schubert return 1;
245206b73d0SCy Schubert }
246206b73d0SCy Schubert
247206b73d0SCy Schubert return 0;
248206b73d0SCy Schubert }
249206b73d0SCy Schubert
250206b73d0SCy Schubert
tls_cipher_suite_mac_sha1(u16 cs)251206b73d0SCy Schubert static int tls_cipher_suite_mac_sha1(u16 cs)
252206b73d0SCy Schubert {
253206b73d0SCy Schubert static const u16 sha1_cs[] = {
254206b73d0SCy Schubert 0x0005, 0x0007, 0x000a, 0x000d, 0x0010, 0x0013, 0x0016, 0x001b,
255206b73d0SCy Schubert 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036,
256206b73d0SCy Schubert 0x0037, 0x0038, 0x0039, 0x003a, 0x0041, 0x0042, 0x0043, 0x0044,
257206b73d0SCy Schubert 0x0045, 0x0046, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089,
258206b73d0SCy Schubert 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091,
259206b73d0SCy Schubert 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099,
260206b73d0SCy Schubert 0x009a, 0x009b,
261206b73d0SCy Schubert 0xc002, 0xc003, 0xc004, 0xc005, 0xc007, 0xc008, 0xc009, 0xc009,
262206b73d0SCy Schubert 0xc00a, 0xc00c, 0xc00d, 0xc00e, 0xc00f, 0xc011, 0xc012, 0xc013,
263206b73d0SCy Schubert 0xc014, 0xc016, 0xc017, 0xc018, 0xc019, 0xc01a, 0xc01b, 0xc01c,
264206b73d0SCy Schubert 0xc014, 0xc01e, 0xc01f, 0xc020, 0xc021, 0xc022, 0xc033, 0xc034,
265206b73d0SCy Schubert 0xc035, 0xc036
266206b73d0SCy Schubert };
267206b73d0SCy Schubert
268206b73d0SCy Schubert return tls_cipher_suite_match(sha1_cs, ARRAY_SIZE(sha1_cs), cs);
269206b73d0SCy Schubert }
270206b73d0SCy Schubert
271206b73d0SCy Schubert
tls_cipher_suite_mac_sha256(u16 cs)272206b73d0SCy Schubert static int tls_cipher_suite_mac_sha256(u16 cs)
273206b73d0SCy Schubert {
274206b73d0SCy Schubert static const u16 sha256_cs[] = {
275206b73d0SCy Schubert 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0067, 0x0068, 0x0069,
276206b73d0SCy Schubert 0x006a, 0x006b, 0x006c, 0x006d, 0x009c, 0x009e, 0x00a0, 0x00a2,
277206b73d0SCy Schubert 0x00a4, 0x00a6, 0x00a8, 0x00aa, 0x00ac, 0x00ae, 0x00b2, 0x00b6,
278206b73d0SCy Schubert 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bd, 0x00be, 0x00be,
279206b73d0SCy Schubert 0x00bf, 0x00bf, 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5,
280206b73d0SCy Schubert 0x1301, 0x1303, 0x1304, 0x1305,
281206b73d0SCy Schubert 0xc023, 0xc025, 0xc027, 0xc029, 0xc02b, 0xc02d, 0xc02f, 0xc031,
282206b73d0SCy Schubert 0xc037, 0xc03c, 0xc03e, 0xc040, 0xc040, 0xc042, 0xc044, 0xc046,
283206b73d0SCy Schubert 0xc048, 0xc04a, 0xc04c, 0xc04e, 0xc050, 0xc052, 0xc054, 0xc056,
284206b73d0SCy Schubert 0xc058, 0xc05a, 0xc05c, 0xc05e, 0xc060, 0xc062, 0xc064, 0xc066,
285206b73d0SCy Schubert 0xc068, 0xc06a, 0xc06c, 0xc06e, 0xc070, 0xc072, 0xc074, 0xc076,
286206b73d0SCy Schubert 0xc078, 0xc07a, 0xc07c, 0xc07e, 0xc080, 0xc082, 0xc084, 0xc086,
287206b73d0SCy Schubert 0xc088, 0xc08a, 0xc08c, 0xc08e, 0xc090, 0xc092, 0xc094, 0xc096,
288206b73d0SCy Schubert 0xc098, 0xc09a, 0xc0b0, 0xc0b2, 0xc0b4,
289206b73d0SCy Schubert 0xcca8, 0xcca9, 0xccaa, 0xccab, 0xccac, 0xccad, 0xccae,
290206b73d0SCy Schubert 0xd001, 0xd003, 0xd005
291206b73d0SCy Schubert };
292206b73d0SCy Schubert
293206b73d0SCy Schubert return tls_cipher_suite_match(sha256_cs, ARRAY_SIZE(sha256_cs), cs);
294206b73d0SCy Schubert }
295206b73d0SCy Schubert
296206b73d0SCy Schubert
tls_cipher_suite_mac_sha384(u16 cs)297206b73d0SCy Schubert static int tls_cipher_suite_mac_sha384(u16 cs)
298206b73d0SCy Schubert {
299206b73d0SCy Schubert static const u16 sha384_cs[] = {
300206b73d0SCy Schubert 0x009d, 0x009f, 0x00a1, 0x00a3, 0x00a5, 0x00a7, 0x00a9, 0x00ab,
301206b73d0SCy Schubert 0x00ad, 0x00af, 0x00b3, 0x00b7, 0x1302,
302206b73d0SCy Schubert 0xc024, 0xc026, 0xc028, 0xc02a, 0xc02c, 0xc02e, 0xc030, 0xc032,
303206b73d0SCy Schubert 0xc038, 0xc03d, 0xc03f, 0xc041, 0xc043, 0xc045, 0xc047, 0xc049,
304206b73d0SCy Schubert 0xc04b, 0xc04d, 0xc04f, 0xc051, 0xc053, 0xc055, 0xc057, 0xc059,
305206b73d0SCy Schubert 0xc05b, 0xc05d, 0xc05f, 0xc061, 0xc063, 0xc065, 0xc067, 0xc069,
306206b73d0SCy Schubert 0xc06b, 0xc06d, 0xc06f, 0xc071, 0xc073, 0xc075, 0xc077, 0xc079,
307206b73d0SCy Schubert 0xc07b, 0xc07d, 0xc07f, 0xc081, 0xc083, 0xc085, 0xc087, 0xc089,
308206b73d0SCy Schubert 0xc08b, 0xc08d, 0xc08f, 0xc091, 0xc093, 0xc095, 0xc097, 0xc099,
309206b73d0SCy Schubert 0xc09b, 0xc0b1, 0xc0b3, 0xc0b5,
310206b73d0SCy Schubert 0xd002
311206b73d0SCy Schubert };
312206b73d0SCy Schubert
313206b73d0SCy Schubert return tls_cipher_suite_match(sha384_cs, ARRAY_SIZE(sha384_cs), cs);
314206b73d0SCy Schubert }
315206b73d0SCy Schubert
316206b73d0SCy Schubert
eap_teap_tls_mac(u16 tls_cs,const u8 * cmk,size_t cmk_len,const u8 * buffer,size_t buffer_len,u8 * mac,size_t mac_len)317206b73d0SCy Schubert static int eap_teap_tls_mac(u16 tls_cs, const u8 *cmk, size_t cmk_len,
318206b73d0SCy Schubert const u8 *buffer, size_t buffer_len,
319206b73d0SCy Schubert u8 *mac, size_t mac_len)
320206b73d0SCy Schubert {
321206b73d0SCy Schubert int res;
322206b73d0SCy Schubert u8 tmp[48];
323206b73d0SCy Schubert
324206b73d0SCy Schubert os_memset(tmp, 0, sizeof(tmp));
325206b73d0SCy Schubert os_memset(mac, 0, mac_len);
326206b73d0SCy Schubert
327206b73d0SCy Schubert if (tls_cipher_suite_mac_sha1(tls_cs)) {
328206b73d0SCy Schubert wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA1");
329206b73d0SCy Schubert res = hmac_sha1(cmk, cmk_len, buffer, buffer_len, tmp);
330206b73d0SCy Schubert } else if (tls_cipher_suite_mac_sha256(tls_cs)) {
331206b73d0SCy Schubert wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA256");
332206b73d0SCy Schubert res = hmac_sha256(cmk, cmk_len, buffer, buffer_len, tmp);
333206b73d0SCy Schubert } else if (tls_cipher_suite_mac_sha384(tls_cs)) {
334206b73d0SCy Schubert wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA384");
335206b73d0SCy Schubert res = hmac_sha384(cmk, cmk_len, buffer, buffer_len, tmp);
336206b73d0SCy Schubert } else {
337206b73d0SCy Schubert wpa_printf(MSG_INFO,
338206b73d0SCy Schubert "EAP-TEAP: Unsupported TLS cipher suite 0x%04x",
339206b73d0SCy Schubert tls_cs);
340206b73d0SCy Schubert res = -1;
341206b73d0SCy Schubert }
342206b73d0SCy Schubert if (res < 0)
343206b73d0SCy Schubert return res;
344206b73d0SCy Schubert
345206b73d0SCy Schubert /* FIX: RFC 7170 does not describe how to handle truncation of the
346206b73d0SCy Schubert * Compound MAC or if the fields are supposed to be of variable length
347206b73d0SCy Schubert * based on the negotiated TLS cipher suite (they are defined as having
348206b73d0SCy Schubert * fixed size of 20 octets in the TLV description) */
349206b73d0SCy Schubert if (mac_len > sizeof(tmp))
350206b73d0SCy Schubert mac_len = sizeof(tmp);
351206b73d0SCy Schubert os_memcpy(mac, tmp, mac_len);
352206b73d0SCy Schubert return 0;
353206b73d0SCy Schubert }
354206b73d0SCy Schubert
355206b73d0SCy Schubert
eap_teap_compound_mac(u16 tls_cs,const struct teap_tlv_crypto_binding * cb,const struct wpabuf * server_outer_tlvs,const struct wpabuf * peer_outer_tlvs,const u8 * cmk,u8 * compound_mac)356206b73d0SCy Schubert int eap_teap_compound_mac(u16 tls_cs, const struct teap_tlv_crypto_binding *cb,
357206b73d0SCy Schubert const struct wpabuf *server_outer_tlvs,
358206b73d0SCy Schubert const struct wpabuf *peer_outer_tlvs,
359206b73d0SCy Schubert const u8 *cmk, u8 *compound_mac)
360206b73d0SCy Schubert {
361206b73d0SCy Schubert u8 *pos, *buffer;
362206b73d0SCy Schubert size_t bind_len, buffer_len;
363206b73d0SCy Schubert struct teap_tlv_crypto_binding *tmp_cb;
364206b73d0SCy Schubert int res;
365206b73d0SCy Schubert
366206b73d0SCy Schubert /* RFC 7170, Section 5.3 */
367206b73d0SCy Schubert bind_len = sizeof(struct teap_tlv_hdr) + be_to_host16(cb->length);
368206b73d0SCy Schubert buffer_len = bind_len + 1;
369206b73d0SCy Schubert if (server_outer_tlvs)
370206b73d0SCy Schubert buffer_len += wpabuf_len(server_outer_tlvs);
371206b73d0SCy Schubert if (peer_outer_tlvs)
372206b73d0SCy Schubert buffer_len += wpabuf_len(peer_outer_tlvs);
373206b73d0SCy Schubert buffer = os_malloc(buffer_len);
374206b73d0SCy Schubert if (!buffer)
375206b73d0SCy Schubert return -1;
376206b73d0SCy Schubert
377206b73d0SCy Schubert pos = buffer;
378206b73d0SCy Schubert /* 1. The entire Crypto-Binding TLV attribute with both the EMSK and MSK
379206b73d0SCy Schubert * Compound MAC fields zeroed out. */
380206b73d0SCy Schubert os_memcpy(pos, cb, bind_len);
381206b73d0SCy Schubert pos += bind_len;
382206b73d0SCy Schubert tmp_cb = (struct teap_tlv_crypto_binding *) buffer;
383206b73d0SCy Schubert os_memset(tmp_cb->emsk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN);
384206b73d0SCy Schubert os_memset(tmp_cb->msk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN);
385206b73d0SCy Schubert
386206b73d0SCy Schubert /* 2. The EAP Type sent by the other party in the first TEAP message. */
387206b73d0SCy Schubert /* This is supposed to be the EAP Type sent by the other party in the
388206b73d0SCy Schubert * first TEAP message, but since we cannot get here without having
389206b73d0SCy Schubert * successfully negotiated use of TEAP, this can only be the fixed EAP
390206b73d0SCy Schubert * Type of TEAP. */
391206b73d0SCy Schubert *pos++ = EAP_TYPE_TEAP;
392206b73d0SCy Schubert
393206b73d0SCy Schubert /* 3. All the Outer TLVs from the first TEAP message sent by EAP server
394206b73d0SCy Schubert * to peer. */
395206b73d0SCy Schubert if (server_outer_tlvs) {
396206b73d0SCy Schubert os_memcpy(pos, wpabuf_head(server_outer_tlvs),
397206b73d0SCy Schubert wpabuf_len(server_outer_tlvs));
398206b73d0SCy Schubert pos += wpabuf_len(server_outer_tlvs);
399206b73d0SCy Schubert }
400206b73d0SCy Schubert
401206b73d0SCy Schubert /* 4. All the Outer TLVs from the first TEAP message sent by the peer to
402206b73d0SCy Schubert * the EAP server. */
403206b73d0SCy Schubert if (peer_outer_tlvs) {
404206b73d0SCy Schubert os_memcpy(pos, wpabuf_head(peer_outer_tlvs),
405206b73d0SCy Schubert wpabuf_len(peer_outer_tlvs));
406206b73d0SCy Schubert pos += wpabuf_len(peer_outer_tlvs);
407206b73d0SCy Schubert }
408206b73d0SCy Schubert
409206b73d0SCy Schubert buffer_len = pos - buffer;
410206b73d0SCy Schubert
411206b73d0SCy Schubert wpa_hexdump_key(MSG_MSGDUMP,
412206b73d0SCy Schubert "EAP-TEAP: CMK for Compound MAC calculation",
413206b73d0SCy Schubert cmk, EAP_TEAP_CMK_LEN);
414206b73d0SCy Schubert wpa_hexdump(MSG_MSGDUMP,
415206b73d0SCy Schubert "EAP-TEAP: BUFFER for Compound MAC calculation",
416206b73d0SCy Schubert buffer, buffer_len);
417206b73d0SCy Schubert res = eap_teap_tls_mac(tls_cs, cmk, EAP_TEAP_CMK_LEN,
418206b73d0SCy Schubert buffer, buffer_len,
419206b73d0SCy Schubert compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
420206b73d0SCy Schubert os_free(buffer);
421206b73d0SCy Schubert
422206b73d0SCy Schubert return res;
423206b73d0SCy Schubert }
424206b73d0SCy Schubert
425206b73d0SCy Schubert
eap_teap_parse_tlv(struct eap_teap_tlv_parse * tlv,int tlv_type,u8 * pos,size_t len)426206b73d0SCy Schubert int eap_teap_parse_tlv(struct eap_teap_tlv_parse *tlv,
427206b73d0SCy Schubert int tlv_type, u8 *pos, size_t len)
428206b73d0SCy Schubert {
429206b73d0SCy Schubert switch (tlv_type) {
430*c1d255d3SCy Schubert case TEAP_TLV_IDENTITY_TYPE:
431*c1d255d3SCy Schubert if (len < 2) {
432*c1d255d3SCy Schubert wpa_printf(MSG_INFO,
433*c1d255d3SCy Schubert "EAP-TEAP: Too short Identity-Type TLV");
434*c1d255d3SCy Schubert tlv->result = TEAP_STATUS_FAILURE;
435*c1d255d3SCy Schubert break;
436*c1d255d3SCy Schubert }
437*c1d255d3SCy Schubert tlv->identity_type = WPA_GET_BE16(pos);
438*c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "EAP-TEAP: Identity-Type: %u",
439*c1d255d3SCy Schubert tlv->identity_type);
440*c1d255d3SCy Schubert break;
441206b73d0SCy Schubert case TEAP_TLV_RESULT:
442206b73d0SCy Schubert wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Result TLV", pos, len);
443206b73d0SCy Schubert if (tlv->result) {
444206b73d0SCy Schubert wpa_printf(MSG_INFO,
445206b73d0SCy Schubert "EAP-TEAP: More than one Result TLV in the message");
446206b73d0SCy Schubert tlv->result = TEAP_STATUS_FAILURE;
447206b73d0SCy Schubert return -2;
448206b73d0SCy Schubert }
449206b73d0SCy Schubert if (len < 2) {
450206b73d0SCy Schubert wpa_printf(MSG_INFO, "EAP-TEAP: Too short Result TLV");
451206b73d0SCy Schubert tlv->result = TEAP_STATUS_FAILURE;
452206b73d0SCy Schubert break;
453206b73d0SCy Schubert }
454206b73d0SCy Schubert tlv->result = WPA_GET_BE16(pos);
455206b73d0SCy Schubert if (tlv->result != TEAP_STATUS_SUCCESS &&
456206b73d0SCy Schubert tlv->result != TEAP_STATUS_FAILURE) {
457206b73d0SCy Schubert wpa_printf(MSG_INFO, "EAP-TEAP: Unknown Result %d",
458206b73d0SCy Schubert tlv->result);
459206b73d0SCy Schubert tlv->result = TEAP_STATUS_FAILURE;
460206b73d0SCy Schubert }
461206b73d0SCy Schubert wpa_printf(MSG_DEBUG, "EAP-TEAP: Result: %s",
462206b73d0SCy Schubert tlv->result == TEAP_STATUS_SUCCESS ?
463206b73d0SCy Schubert "Success" : "Failure");
464206b73d0SCy Schubert break;
465206b73d0SCy Schubert case TEAP_TLV_NAK:
466206b73d0SCy Schubert wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: NAK TLV", pos, len);
467206b73d0SCy Schubert if (len < 6) {
468206b73d0SCy Schubert wpa_printf(MSG_INFO, "EAP-TEAP: Too short NAK TLV");
469206b73d0SCy Schubert tlv->result = TEAP_STATUS_FAILURE;
470206b73d0SCy Schubert break;
471206b73d0SCy Schubert }
472206b73d0SCy Schubert tlv->nak = pos;
473206b73d0SCy Schubert tlv->nak_len = len;
474206b73d0SCy Schubert break;
475*c1d255d3SCy Schubert case TEAP_TLV_ERROR:
476*c1d255d3SCy Schubert if (len < 4) {
477*c1d255d3SCy Schubert wpa_printf(MSG_INFO, "EAP-TEAP: Too short Error TLV");
478*c1d255d3SCy Schubert tlv->result = TEAP_STATUS_FAILURE;
479*c1d255d3SCy Schubert break;
480*c1d255d3SCy Schubert }
481*c1d255d3SCy Schubert tlv->error_code = WPA_GET_BE32(pos);
482*c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "EAP-TEAP: Error: %u", tlv->error_code);
483*c1d255d3SCy Schubert break;
484206b73d0SCy Schubert case TEAP_TLV_REQUEST_ACTION:
485206b73d0SCy Schubert wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Request-Action TLV",
486206b73d0SCy Schubert pos, len);
487206b73d0SCy Schubert if (tlv->request_action) {
488206b73d0SCy Schubert wpa_printf(MSG_INFO,
489206b73d0SCy Schubert "EAP-TEAP: More than one Request-Action TLV in the message");
490206b73d0SCy Schubert tlv->iresult = TEAP_STATUS_FAILURE;
491206b73d0SCy Schubert return -2;
492206b73d0SCy Schubert }
493206b73d0SCy Schubert if (len < 2) {
494206b73d0SCy Schubert wpa_printf(MSG_INFO,
495206b73d0SCy Schubert "EAP-TEAP: Too short Request-Action TLV");
496206b73d0SCy Schubert tlv->iresult = TEAP_STATUS_FAILURE;
497206b73d0SCy Schubert break;
498206b73d0SCy Schubert }
499206b73d0SCy Schubert tlv->request_action_status = pos[0];
500206b73d0SCy Schubert tlv->request_action = pos[1];
501206b73d0SCy Schubert wpa_printf(MSG_DEBUG,
502206b73d0SCy Schubert "EAP-TEAP: Request-Action: Status=%u Action=%u",
503206b73d0SCy Schubert tlv->request_action_status, tlv->request_action);
504206b73d0SCy Schubert break;
505206b73d0SCy Schubert case TEAP_TLV_EAP_PAYLOAD:
506206b73d0SCy Schubert wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: EAP-Payload TLV",
507206b73d0SCy Schubert pos, len);
508206b73d0SCy Schubert if (tlv->eap_payload_tlv) {
509206b73d0SCy Schubert wpa_printf(MSG_INFO,
510206b73d0SCy Schubert "EAP-TEAP: More than one EAP-Payload TLV in the message");
511206b73d0SCy Schubert tlv->iresult = TEAP_STATUS_FAILURE;
512206b73d0SCy Schubert return -2;
513206b73d0SCy Schubert }
514206b73d0SCy Schubert tlv->eap_payload_tlv = pos;
515206b73d0SCy Schubert tlv->eap_payload_tlv_len = len;
516206b73d0SCy Schubert break;
517206b73d0SCy Schubert case TEAP_TLV_INTERMEDIATE_RESULT:
518206b73d0SCy Schubert wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Intermediate-Result TLV",
519206b73d0SCy Schubert pos, len);
520206b73d0SCy Schubert if (len < 2) {
521206b73d0SCy Schubert wpa_printf(MSG_INFO,
522206b73d0SCy Schubert "EAP-TEAP: Too short Intermediate-Result TLV");
523206b73d0SCy Schubert tlv->iresult = TEAP_STATUS_FAILURE;
524206b73d0SCy Schubert break;
525206b73d0SCy Schubert }
526206b73d0SCy Schubert if (tlv->iresult) {
527206b73d0SCy Schubert wpa_printf(MSG_INFO,
528206b73d0SCy Schubert "EAP-TEAP: More than one Intermediate-Result TLV in the message");
529206b73d0SCy Schubert tlv->iresult = TEAP_STATUS_FAILURE;
530206b73d0SCy Schubert return -2;
531206b73d0SCy Schubert }
532206b73d0SCy Schubert tlv->iresult = WPA_GET_BE16(pos);
533206b73d0SCy Schubert if (tlv->iresult != TEAP_STATUS_SUCCESS &&
534206b73d0SCy Schubert tlv->iresult != TEAP_STATUS_FAILURE) {
535206b73d0SCy Schubert wpa_printf(MSG_INFO,
536206b73d0SCy Schubert "EAP-TEAP: Unknown Intermediate Result %d",
537206b73d0SCy Schubert tlv->iresult);
538206b73d0SCy Schubert tlv->iresult = TEAP_STATUS_FAILURE;
539206b73d0SCy Schubert }
540206b73d0SCy Schubert wpa_printf(MSG_DEBUG, "EAP-TEAP: Intermediate Result: %s",
541206b73d0SCy Schubert tlv->iresult == TEAP_STATUS_SUCCESS ?
542206b73d0SCy Schubert "Success" : "Failure");
543206b73d0SCy Schubert break;
544206b73d0SCy Schubert case TEAP_TLV_PAC:
545206b73d0SCy Schubert wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: PAC TLV", pos, len);
546206b73d0SCy Schubert if (tlv->pac) {
547206b73d0SCy Schubert wpa_printf(MSG_INFO,
548206b73d0SCy Schubert "EAP-TEAP: More than one PAC TLV in the message");
549206b73d0SCy Schubert tlv->iresult = TEAP_STATUS_FAILURE;
550206b73d0SCy Schubert return -2;
551206b73d0SCy Schubert }
552206b73d0SCy Schubert tlv->pac = pos;
553206b73d0SCy Schubert tlv->pac_len = len;
554206b73d0SCy Schubert break;
555206b73d0SCy Schubert case TEAP_TLV_CRYPTO_BINDING:
556206b73d0SCy Schubert wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Crypto-Binding TLV",
557206b73d0SCy Schubert pos, len);
558206b73d0SCy Schubert if (tlv->crypto_binding) {
559206b73d0SCy Schubert wpa_printf(MSG_INFO,
560206b73d0SCy Schubert "EAP-TEAP: More than one Crypto-Binding TLV in the message");
561206b73d0SCy Schubert tlv->iresult = TEAP_STATUS_FAILURE;
562206b73d0SCy Schubert return -2;
563206b73d0SCy Schubert }
564206b73d0SCy Schubert tlv->crypto_binding_len = sizeof(struct teap_tlv_hdr) + len;
565206b73d0SCy Schubert if (tlv->crypto_binding_len < sizeof(*tlv->crypto_binding)) {
566206b73d0SCy Schubert wpa_printf(MSG_INFO,
567206b73d0SCy Schubert "EAP-TEAP: Too short Crypto-Binding TLV");
568206b73d0SCy Schubert tlv->iresult = TEAP_STATUS_FAILURE;
569206b73d0SCy Schubert return -2;
570206b73d0SCy Schubert }
571206b73d0SCy Schubert tlv->crypto_binding = (struct teap_tlv_crypto_binding *)
572206b73d0SCy Schubert (pos - sizeof(struct teap_tlv_hdr));
573206b73d0SCy Schubert break;
574206b73d0SCy Schubert case TEAP_TLV_BASIC_PASSWORD_AUTH_REQ:
575206b73d0SCy Schubert wpa_hexdump_ascii(MSG_MSGDUMP,
576206b73d0SCy Schubert "EAP-TEAP: Basic-Password-Auth-Req TLV",
577206b73d0SCy Schubert pos, len);
578206b73d0SCy Schubert if (tlv->basic_auth_req) {
579206b73d0SCy Schubert wpa_printf(MSG_INFO,
580206b73d0SCy Schubert "EAP-TEAP: More than one Basic-Password-Auth-Req TLV in the message");
581206b73d0SCy Schubert tlv->iresult = TEAP_STATUS_FAILURE;
582206b73d0SCy Schubert return -2;
583206b73d0SCy Schubert }
584206b73d0SCy Schubert tlv->basic_auth_req = pos;
585206b73d0SCy Schubert tlv->basic_auth_req_len = len;
586206b73d0SCy Schubert break;
587206b73d0SCy Schubert case TEAP_TLV_BASIC_PASSWORD_AUTH_RESP:
588206b73d0SCy Schubert wpa_hexdump_ascii(MSG_MSGDUMP,
589206b73d0SCy Schubert "EAP-TEAP: Basic-Password-Auth-Resp TLV",
590206b73d0SCy Schubert pos, len);
591206b73d0SCy Schubert if (tlv->basic_auth_resp) {
592206b73d0SCy Schubert wpa_printf(MSG_INFO,
593206b73d0SCy Schubert "EAP-TEAP: More than one Basic-Password-Auth-Resp TLV in the message");
594206b73d0SCy Schubert tlv->iresult = TEAP_STATUS_FAILURE;
595206b73d0SCy Schubert return -2;
596206b73d0SCy Schubert }
597206b73d0SCy Schubert tlv->basic_auth_resp = pos;
598206b73d0SCy Schubert tlv->basic_auth_resp_len = len;
599206b73d0SCy Schubert break;
600206b73d0SCy Schubert default:
601206b73d0SCy Schubert /* Unknown TLV */
602206b73d0SCy Schubert return -1;
603206b73d0SCy Schubert }
604206b73d0SCy Schubert
605206b73d0SCy Schubert return 0;
606206b73d0SCy Schubert }
607206b73d0SCy Schubert
608206b73d0SCy Schubert
eap_teap_tlv_type_str(enum teap_tlv_types type)609206b73d0SCy Schubert const char * eap_teap_tlv_type_str(enum teap_tlv_types type)
610206b73d0SCy Schubert {
611206b73d0SCy Schubert switch (type) {
612206b73d0SCy Schubert case TEAP_TLV_AUTHORITY_ID:
613206b73d0SCy Schubert return "Authority-ID";
614206b73d0SCy Schubert case TEAP_TLV_IDENTITY_TYPE:
615206b73d0SCy Schubert return "Identity-Type";
616206b73d0SCy Schubert case TEAP_TLV_RESULT:
617206b73d0SCy Schubert return "Result";
618206b73d0SCy Schubert case TEAP_TLV_NAK:
619206b73d0SCy Schubert return "NAK";
620206b73d0SCy Schubert case TEAP_TLV_ERROR:
621206b73d0SCy Schubert return "Error";
622206b73d0SCy Schubert case TEAP_TLV_CHANNEL_BINDING:
623206b73d0SCy Schubert return "Channel-Binding";
624206b73d0SCy Schubert case TEAP_TLV_VENDOR_SPECIFIC:
625206b73d0SCy Schubert return "Vendor-Specific";
626206b73d0SCy Schubert case TEAP_TLV_REQUEST_ACTION:
627206b73d0SCy Schubert return "Request-Action";
628206b73d0SCy Schubert case TEAP_TLV_EAP_PAYLOAD:
629206b73d0SCy Schubert return "EAP-Payload";
630206b73d0SCy Schubert case TEAP_TLV_INTERMEDIATE_RESULT:
631206b73d0SCy Schubert return "Intermediate-Result";
632206b73d0SCy Schubert case TEAP_TLV_PAC:
633206b73d0SCy Schubert return "PAC";
634206b73d0SCy Schubert case TEAP_TLV_CRYPTO_BINDING:
635206b73d0SCy Schubert return "Crypto-Binding";
636206b73d0SCy Schubert case TEAP_TLV_BASIC_PASSWORD_AUTH_REQ:
637206b73d0SCy Schubert return "Basic-Password-Auth-Req";
638206b73d0SCy Schubert case TEAP_TLV_BASIC_PASSWORD_AUTH_RESP:
639206b73d0SCy Schubert return "Basic-Password-Auth-Resp";
640206b73d0SCy Schubert case TEAP_TLV_PKCS7:
641206b73d0SCy Schubert return "PKCS#7";
642206b73d0SCy Schubert case TEAP_TLV_PKCS10:
643206b73d0SCy Schubert return "PKCS#10";
644206b73d0SCy Schubert case TEAP_TLV_TRUSTED_SERVER_ROOT:
645206b73d0SCy Schubert return "Trusted-Server-Root";
646206b73d0SCy Schubert }
647206b73d0SCy Schubert
648206b73d0SCy Schubert return "?";
649206b73d0SCy Schubert }
650206b73d0SCy Schubert
651206b73d0SCy Schubert
eap_teap_tlv_result(int status,int intermediate)652206b73d0SCy Schubert struct wpabuf * eap_teap_tlv_result(int status, int intermediate)
653206b73d0SCy Schubert {
654206b73d0SCy Schubert struct wpabuf *buf;
655206b73d0SCy Schubert struct teap_tlv_result *result;
656206b73d0SCy Schubert
657206b73d0SCy Schubert if (status != TEAP_STATUS_FAILURE && status != TEAP_STATUS_SUCCESS)
658206b73d0SCy Schubert return NULL;
659206b73d0SCy Schubert
660206b73d0SCy Schubert buf = wpabuf_alloc(sizeof(*result));
661206b73d0SCy Schubert if (!buf)
662206b73d0SCy Schubert return NULL;
663206b73d0SCy Schubert wpa_printf(MSG_DEBUG, "EAP-TEAP: Add %sResult TLV(status=%s)",
664206b73d0SCy Schubert intermediate ? "Intermediate-" : "",
665206b73d0SCy Schubert status == TEAP_STATUS_SUCCESS ? "Success" : "Failure");
666206b73d0SCy Schubert result = wpabuf_put(buf, sizeof(*result));
667206b73d0SCy Schubert result->tlv_type = host_to_be16(TEAP_TLV_MANDATORY |
668206b73d0SCy Schubert (intermediate ?
669206b73d0SCy Schubert TEAP_TLV_INTERMEDIATE_RESULT :
670206b73d0SCy Schubert TEAP_TLV_RESULT));
671206b73d0SCy Schubert result->length = host_to_be16(2);
672206b73d0SCy Schubert result->status = host_to_be16(status);
673206b73d0SCy Schubert return buf;
674206b73d0SCy Schubert }
675206b73d0SCy Schubert
676206b73d0SCy Schubert
eap_teap_tlv_error(enum teap_error_codes error)677206b73d0SCy Schubert struct wpabuf * eap_teap_tlv_error(enum teap_error_codes error)
678206b73d0SCy Schubert {
679206b73d0SCy Schubert struct wpabuf *buf;
680206b73d0SCy Schubert
681206b73d0SCy Schubert buf = wpabuf_alloc(4 + 4);
682206b73d0SCy Schubert if (!buf)
683206b73d0SCy Schubert return NULL;
684206b73d0SCy Schubert wpa_printf(MSG_DEBUG, "EAP-TEAP: Add Error TLV(Error Code=%d)",
685206b73d0SCy Schubert error);
686206b73d0SCy Schubert wpabuf_put_be16(buf, TEAP_TLV_MANDATORY | TEAP_TLV_ERROR);
687206b73d0SCy Schubert wpabuf_put_be16(buf, 4);
688206b73d0SCy Schubert wpabuf_put_be32(buf, error);
689206b73d0SCy Schubert return buf;
690206b73d0SCy Schubert }
691206b73d0SCy Schubert
692206b73d0SCy Schubert
eap_teap_tlv_identity_type(enum teap_identity_types id)693*c1d255d3SCy Schubert struct wpabuf * eap_teap_tlv_identity_type(enum teap_identity_types id)
694*c1d255d3SCy Schubert {
695*c1d255d3SCy Schubert struct wpabuf *buf;
696*c1d255d3SCy Schubert
697*c1d255d3SCy Schubert buf = wpabuf_alloc(4 + 2);
698*c1d255d3SCy Schubert if (!buf)
699*c1d255d3SCy Schubert return NULL;
700*c1d255d3SCy Schubert wpa_printf(MSG_DEBUG,
701*c1d255d3SCy Schubert "EAP-TEAP: Add Identity-Type TLV(Identity-Type=%d)", id);
702*c1d255d3SCy Schubert wpabuf_put_be16(buf, TEAP_TLV_IDENTITY_TYPE);
703*c1d255d3SCy Schubert wpabuf_put_be16(buf, 2);
704*c1d255d3SCy Schubert wpabuf_put_be16(buf, id);
705*c1d255d3SCy Schubert return buf;
706*c1d255d3SCy Schubert }
707*c1d255d3SCy Schubert
708*c1d255d3SCy Schubert
eap_teap_allowed_anon_prov_phase2_method(int vendor,enum eap_type type)709*c1d255d3SCy Schubert int eap_teap_allowed_anon_prov_phase2_method(int vendor, enum eap_type type)
710206b73d0SCy Schubert {
711206b73d0SCy Schubert /* RFC 7170, Section 3.8.3: MUST provide mutual authentication,
712206b73d0SCy Schubert * provide key generation, and be resistant to dictionary attack.
713206b73d0SCy Schubert * Section 3.8 also mentions requirement for using EMSK Compound MAC. */
714*c1d255d3SCy Schubert return vendor == EAP_VENDOR_IETF &&
715*c1d255d3SCy Schubert (type == EAP_TYPE_PWD || type == EAP_TYPE_EKE);
716206b73d0SCy Schubert }
717206b73d0SCy Schubert
718206b73d0SCy Schubert
eap_teap_allowed_anon_prov_cipher_suite(u16 cs)719206b73d0SCy Schubert int eap_teap_allowed_anon_prov_cipher_suite(u16 cs)
720206b73d0SCy Schubert {
721206b73d0SCy Schubert /* RFC 7170, Section 3.8.3: anonymous ciphersuites MAY be supported as
722206b73d0SCy Schubert * long as the TLS pre-master secret is generated form contribution from
723206b73d0SCy Schubert * both peers. Accept the recommended TLS_DH_anon_WITH_AES_128_CBC_SHA
724206b73d0SCy Schubert * cipher suite and other ciphersuites that use DH in some form, have
725206b73d0SCy Schubert * SHA-1 or stronger MAC function, and use reasonable strong cipher. */
726206b73d0SCy Schubert static const u16 ok_cs[] = {
727206b73d0SCy Schubert /* DH-anon */
728206b73d0SCy Schubert 0x0034, 0x003a, 0x006c, 0x006d, 0x00a6, 0x00a7,
729206b73d0SCy Schubert /* DHE-RSA */
730206b73d0SCy Schubert 0x0033, 0x0039, 0x0067, 0x006b, 0x009e, 0x009f,
731206b73d0SCy Schubert /* ECDH-anon */
732206b73d0SCy Schubert 0xc018, 0xc019,
733206b73d0SCy Schubert /* ECDH-RSA */
734206b73d0SCy Schubert 0xc003, 0xc00f, 0xc029, 0xc02a, 0xc031, 0xc032,
735206b73d0SCy Schubert /* ECDH-ECDSA */
736206b73d0SCy Schubert 0xc004, 0xc005, 0xc025, 0xc026, 0xc02d, 0xc02e,
737206b73d0SCy Schubert /* ECDHE-RSA */
738206b73d0SCy Schubert 0xc013, 0xc014, 0xc027, 0xc028, 0xc02f, 0xc030,
739206b73d0SCy Schubert /* ECDHE-ECDSA */
740206b73d0SCy Schubert 0xc009, 0xc00a, 0xc023, 0xc024, 0xc02b, 0xc02c,
741206b73d0SCy Schubert };
742206b73d0SCy Schubert
743206b73d0SCy Schubert return tls_cipher_suite_match(ok_cs, ARRAY_SIZE(ok_cs), cs);
744206b73d0SCy Schubert }
745