1*a1157835SDaniel Fojt /*
2*a1157835SDaniel Fojt * EAP-TEAP common helper functions (RFC 7170)
3*a1157835SDaniel Fojt * Copyright (c) 2008-2019, Jouni Malinen <j@w1.fi>
4*a1157835SDaniel Fojt *
5*a1157835SDaniel Fojt * This software may be distributed under the terms of the BSD license.
6*a1157835SDaniel Fojt * See README for more details.
7*a1157835SDaniel Fojt */
8*a1157835SDaniel Fojt
9*a1157835SDaniel Fojt #include "includes.h"
10*a1157835SDaniel Fojt
11*a1157835SDaniel Fojt #include "common.h"
12*a1157835SDaniel Fojt #include "crypto/sha1.h"
13*a1157835SDaniel Fojt #include "crypto/sha256.h"
14*a1157835SDaniel Fojt #include "crypto/sha384.h"
15*a1157835SDaniel Fojt #include "crypto/tls.h"
16*a1157835SDaniel Fojt #include "eap_defs.h"
17*a1157835SDaniel Fojt #include "eap_teap_common.h"
18*a1157835SDaniel Fojt
19*a1157835SDaniel Fojt
eap_teap_put_tlv_hdr(struct wpabuf * buf,u16 type,u16 len)20*a1157835SDaniel Fojt void eap_teap_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len)
21*a1157835SDaniel Fojt {
22*a1157835SDaniel Fojt struct teap_tlv_hdr hdr;
23*a1157835SDaniel Fojt
24*a1157835SDaniel Fojt hdr.tlv_type = host_to_be16(type);
25*a1157835SDaniel Fojt hdr.length = host_to_be16(len);
26*a1157835SDaniel Fojt wpabuf_put_data(buf, &hdr, sizeof(hdr));
27*a1157835SDaniel Fojt }
28*a1157835SDaniel Fojt
29*a1157835SDaniel Fojt
eap_teap_put_tlv(struct wpabuf * buf,u16 type,const void * data,u16 len)30*a1157835SDaniel Fojt void eap_teap_put_tlv(struct wpabuf *buf, u16 type, const void *data, u16 len)
31*a1157835SDaniel Fojt {
32*a1157835SDaniel Fojt eap_teap_put_tlv_hdr(buf, type, len);
33*a1157835SDaniel Fojt wpabuf_put_data(buf, data, len);
34*a1157835SDaniel Fojt }
35*a1157835SDaniel Fojt
36*a1157835SDaniel Fojt
eap_teap_put_tlv_buf(struct wpabuf * buf,u16 type,const struct wpabuf * data)37*a1157835SDaniel Fojt void eap_teap_put_tlv_buf(struct wpabuf *buf, u16 type,
38*a1157835SDaniel Fojt const struct wpabuf *data)
39*a1157835SDaniel Fojt {
40*a1157835SDaniel Fojt eap_teap_put_tlv_hdr(buf, type, wpabuf_len(data));
41*a1157835SDaniel Fojt wpabuf_put_buf(buf, data);
42*a1157835SDaniel Fojt }
43*a1157835SDaniel Fojt
44*a1157835SDaniel Fojt
eap_teap_tlv_eap_payload(struct wpabuf * buf)45*a1157835SDaniel Fojt struct wpabuf * eap_teap_tlv_eap_payload(struct wpabuf *buf)
46*a1157835SDaniel Fojt {
47*a1157835SDaniel Fojt struct wpabuf *e;
48*a1157835SDaniel Fojt
49*a1157835SDaniel Fojt if (!buf)
50*a1157835SDaniel Fojt return NULL;
51*a1157835SDaniel Fojt
52*a1157835SDaniel Fojt /* Encapsulate EAP packet in EAP-Payload TLV */
53*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "EAP-TEAP: Add EAP-Payload TLV");
54*a1157835SDaniel Fojt e = wpabuf_alloc(sizeof(struct teap_tlv_hdr) + wpabuf_len(buf));
55*a1157835SDaniel Fojt if (!e) {
56*a1157835SDaniel Fojt wpa_printf(MSG_ERROR,
57*a1157835SDaniel Fojt "EAP-TEAP: Failed to allocate memory for TLV encapsulation");
58*a1157835SDaniel Fojt wpabuf_free(buf);
59*a1157835SDaniel Fojt return NULL;
60*a1157835SDaniel Fojt }
61*a1157835SDaniel Fojt eap_teap_put_tlv_buf(e, TEAP_TLV_MANDATORY | TEAP_TLV_EAP_PAYLOAD, buf);
62*a1157835SDaniel Fojt wpabuf_free(buf);
63*a1157835SDaniel Fojt
64*a1157835SDaniel Fojt /* TODO: followed by optional TLVs associated with the EAP packet */
65*a1157835SDaniel Fojt
66*a1157835SDaniel Fojt return e;
67*a1157835SDaniel Fojt }
68*a1157835SDaniel Fojt
69*a1157835SDaniel Fojt
eap_teap_tls_prf(const u8 * secret,size_t secret_len,const char * label,const u8 * seed,size_t seed_len,u8 * out,size_t outlen)70*a1157835SDaniel Fojt static int eap_teap_tls_prf(const u8 *secret, size_t secret_len,
71*a1157835SDaniel Fojt const char *label, const u8 *seed, size_t seed_len,
72*a1157835SDaniel Fojt u8 *out, size_t outlen)
73*a1157835SDaniel Fojt {
74*a1157835SDaniel Fojt /* TODO: TLS-PRF for TLSv1.3 */
75*a1157835SDaniel Fojt return tls_prf_sha256(secret, secret_len, label, seed, seed_len,
76*a1157835SDaniel Fojt out, outlen);
77*a1157835SDaniel Fojt }
78*a1157835SDaniel Fojt
79*a1157835SDaniel Fojt
eap_teap_derive_eap_msk(const u8 * simck,u8 * msk)80*a1157835SDaniel Fojt int eap_teap_derive_eap_msk(const u8 *simck, u8 *msk)
81*a1157835SDaniel Fojt {
82*a1157835SDaniel Fojt /*
83*a1157835SDaniel Fojt * RFC 7170, Section 5.4: EAP Master Session Key Generation
84*a1157835SDaniel Fojt * MSK = TLS-PRF(S-IMCK[j], "Session Key Generating Function", 64)
85*a1157835SDaniel Fojt */
86*a1157835SDaniel Fojt
87*a1157835SDaniel Fojt if (eap_teap_tls_prf(simck, EAP_TEAP_SIMCK_LEN,
88*a1157835SDaniel Fojt "Session Key Generating Function", (u8 *) "", 0,
89*a1157835SDaniel Fojt msk, EAP_TEAP_KEY_LEN) < 0)
90*a1157835SDaniel Fojt return -1;
91*a1157835SDaniel Fojt wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Derived key (MSK)",
92*a1157835SDaniel Fojt msk, EAP_TEAP_KEY_LEN);
93*a1157835SDaniel Fojt return 0;
94*a1157835SDaniel Fojt }
95*a1157835SDaniel Fojt
96*a1157835SDaniel Fojt
eap_teap_derive_eap_emsk(const u8 * simck,u8 * emsk)97*a1157835SDaniel Fojt int eap_teap_derive_eap_emsk(const u8 *simck, u8 *emsk)
98*a1157835SDaniel Fojt {
99*a1157835SDaniel Fojt /*
100*a1157835SDaniel Fojt * RFC 7170, Section 5.4: EAP Master Session Key Generation
101*a1157835SDaniel Fojt * EMSK = TLS-PRF(S-IMCK[j],
102*a1157835SDaniel Fojt * "Extended Session Key Generating Function", 64)
103*a1157835SDaniel Fojt */
104*a1157835SDaniel Fojt
105*a1157835SDaniel Fojt if (eap_teap_tls_prf(simck, EAP_TEAP_SIMCK_LEN,
106*a1157835SDaniel Fojt "Extended Session Key Generating Function",
107*a1157835SDaniel Fojt (u8 *) "", 0, emsk, EAP_EMSK_LEN) < 0)
108*a1157835SDaniel Fojt return -1;
109*a1157835SDaniel Fojt wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Derived key (EMSK)",
110*a1157835SDaniel Fojt emsk, EAP_EMSK_LEN);
111*a1157835SDaniel Fojt return 0;
112*a1157835SDaniel Fojt }
113*a1157835SDaniel Fojt
114*a1157835SDaniel Fojt
eap_teap_derive_cmk_basic_pw_auth(const u8 * s_imck_msk,u8 * cmk)115*a1157835SDaniel Fojt int eap_teap_derive_cmk_basic_pw_auth(const u8 *s_imck_msk, u8 *cmk)
116*a1157835SDaniel Fojt {
117*a1157835SDaniel Fojt u8 imsk[32], imck[EAP_TEAP_IMCK_LEN];
118*a1157835SDaniel Fojt int res;
119*a1157835SDaniel Fojt
120*a1157835SDaniel Fojt /* FIX: The Basic-Password-Auth (i.e., no inner EAP) case is
121*a1157835SDaniel Fojt * not fully defined in RFC 7170, so this CMK derivation may
122*a1157835SDaniel Fojt * need to be changed if a fixed definition is eventually
123*a1157835SDaniel Fojt * published. For now, derive CMK[0] based on S-IMCK[0] and
124*a1157835SDaniel Fojt * IMSK of 32 octets of zeros. */
125*a1157835SDaniel Fojt os_memset(imsk, 0, 32);
126*a1157835SDaniel Fojt res = eap_teap_tls_prf(s_imck_msk, EAP_TEAP_SIMCK_LEN,
127*a1157835SDaniel Fojt "Inner Methods Compound Keys",
128*a1157835SDaniel Fojt imsk, 32, imck, sizeof(imck));
129*a1157835SDaniel Fojt if (res < 0)
130*a1157835SDaniel Fojt return -1;
131*a1157835SDaniel Fojt os_memcpy(cmk, &imck[EAP_TEAP_SIMCK_LEN], EAP_TEAP_CMK_LEN);
132*a1157835SDaniel Fojt wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: CMK[no-inner-EAP]",
133*a1157835SDaniel Fojt cmk, EAP_TEAP_CMK_LEN);
134*a1157835SDaniel Fojt forced_memzero(imck, sizeof(imck));
135*a1157835SDaniel Fojt return 0;
136*a1157835SDaniel Fojt }
137*a1157835SDaniel Fojt
138*a1157835SDaniel Fojt
eap_teap_derive_imck(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)139*a1157835SDaniel Fojt int eap_teap_derive_imck(const u8 *prev_s_imck_msk, const u8 *prev_s_imck_emsk,
140*a1157835SDaniel Fojt const u8 *msk, size_t msk_len,
141*a1157835SDaniel Fojt const u8 *emsk, size_t emsk_len,
142*a1157835SDaniel Fojt u8 *s_imck_msk, u8 *cmk_msk,
143*a1157835SDaniel Fojt u8 *s_imck_emsk, u8 *cmk_emsk)
144*a1157835SDaniel Fojt {
145*a1157835SDaniel Fojt u8 imsk[64], imck[EAP_TEAP_IMCK_LEN];
146*a1157835SDaniel Fojt int res;
147*a1157835SDaniel Fojt
148*a1157835SDaniel Fojt /*
149*a1157835SDaniel Fojt * RFC 7170, Section 5.2:
150*a1157835SDaniel Fojt * IMSK = First 32 octets of TLS-PRF(EMSK, "TEAPbindkey@ietf.org" |
151*a1157835SDaniel Fojt * "\0" | 64)
152*a1157835SDaniel Fojt * (if EMSK is not available, MSK is used instead; if neither is
153*a1157835SDaniel Fojt * available, IMSK is 32 octets of zeros; MSK is truncated to 32 octets
154*a1157835SDaniel Fojt * or padded to 32 octets, if needed)
155*a1157835SDaniel Fojt * (64 is encoded as a 2-octet field in network byte order)
156*a1157835SDaniel Fojt *
157*a1157835SDaniel Fojt * S-IMCK[0] = session_key_seed
158*a1157835SDaniel Fojt * IMCK[j] = TLS-PRF(S-IMCK[j-1], "Inner Methods Compound Keys",
159*a1157835SDaniel Fojt * IMSK[j], 60)
160*a1157835SDaniel Fojt * S-IMCK[j] = first 40 octets of IMCK[j]
161*a1157835SDaniel Fojt * CMK[j] = last 20 octets of IMCK[j]
162*a1157835SDaniel Fojt */
163*a1157835SDaniel Fojt
164*a1157835SDaniel Fojt wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK[j]", msk, msk_len);
165*a1157835SDaniel Fojt wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK[j]", emsk, emsk_len);
166*a1157835SDaniel Fojt
167*a1157835SDaniel Fojt if (emsk && emsk_len > 0) {
168*a1157835SDaniel Fojt u8 context[3];
169*a1157835SDaniel Fojt
170*a1157835SDaniel Fojt context[0] = 0;
171*a1157835SDaniel Fojt context[1] = 0;
172*a1157835SDaniel Fojt context[2] = 64;
173*a1157835SDaniel Fojt if (eap_teap_tls_prf(emsk, emsk_len, "TEAPbindkey@ietf.org",
174*a1157835SDaniel Fojt context, sizeof(context), imsk, 64) < 0)
175*a1157835SDaniel Fojt return -1;
176*a1157835SDaniel Fojt
177*a1157835SDaniel Fojt wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: IMSK from EMSK",
178*a1157835SDaniel Fojt imsk, 32);
179*a1157835SDaniel Fojt
180*a1157835SDaniel Fojt res = eap_teap_tls_prf(prev_s_imck_emsk, EAP_TEAP_SIMCK_LEN,
181*a1157835SDaniel Fojt "Inner Methods Compound Keys",
182*a1157835SDaniel Fojt imsk, 32, imck, EAP_TEAP_IMCK_LEN);
183*a1157835SDaniel Fojt forced_memzero(imsk, sizeof(imsk));
184*a1157835SDaniel Fojt if (res < 0)
185*a1157835SDaniel Fojt return -1;
186*a1157835SDaniel Fojt
187*a1157835SDaniel Fojt os_memcpy(s_imck_emsk, imck, EAP_TEAP_SIMCK_LEN);
188*a1157835SDaniel Fojt wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK S-IMCK[j]",
189*a1157835SDaniel Fojt s_imck_emsk, EAP_TEAP_SIMCK_LEN);
190*a1157835SDaniel Fojt os_memcpy(cmk_emsk, &imck[EAP_TEAP_SIMCK_LEN],
191*a1157835SDaniel Fojt EAP_TEAP_CMK_LEN);
192*a1157835SDaniel Fojt wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK CMK[j]",
193*a1157835SDaniel Fojt cmk_emsk, EAP_TEAP_CMK_LEN);
194*a1157835SDaniel Fojt forced_memzero(imck, EAP_TEAP_IMCK_LEN);
195*a1157835SDaniel Fojt }
196*a1157835SDaniel Fojt
197*a1157835SDaniel Fojt if (msk && msk_len > 0) {
198*a1157835SDaniel Fojt size_t copy_len = msk_len;
199*a1157835SDaniel Fojt
200*a1157835SDaniel Fojt os_memset(imsk, 0, 32); /* zero pad, if needed */
201*a1157835SDaniel Fojt if (copy_len > 32)
202*a1157835SDaniel Fojt copy_len = 32;
203*a1157835SDaniel Fojt os_memcpy(imsk, msk, copy_len);
204*a1157835SDaniel Fojt wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: IMSK from MSK", imsk, 32);
205*a1157835SDaniel Fojt } else {
206*a1157835SDaniel Fojt os_memset(imsk, 0, 32);
207*a1157835SDaniel Fojt wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Zero IMSK", imsk, 32);
208*a1157835SDaniel Fojt }
209*a1157835SDaniel Fojt
210*a1157835SDaniel Fojt res = eap_teap_tls_prf(prev_s_imck_msk, EAP_TEAP_SIMCK_LEN,
211*a1157835SDaniel Fojt "Inner Methods Compound Keys",
212*a1157835SDaniel Fojt imsk, 32, imck, EAP_TEAP_IMCK_LEN);
213*a1157835SDaniel Fojt forced_memzero(imsk, sizeof(imsk));
214*a1157835SDaniel Fojt if (res < 0)
215*a1157835SDaniel Fojt return -1;
216*a1157835SDaniel Fojt
217*a1157835SDaniel Fojt os_memcpy(s_imck_msk, imck, EAP_TEAP_SIMCK_LEN);
218*a1157835SDaniel Fojt wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK S-IMCK[j]",
219*a1157835SDaniel Fojt s_imck_msk, EAP_TEAP_SIMCK_LEN);
220*a1157835SDaniel Fojt os_memcpy(cmk_msk, &imck[EAP_TEAP_SIMCK_LEN], EAP_TEAP_CMK_LEN);
221*a1157835SDaniel Fojt wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK CMK[j]",
222*a1157835SDaniel Fojt cmk_msk, EAP_TEAP_CMK_LEN);
223*a1157835SDaniel Fojt forced_memzero(imck, EAP_TEAP_IMCK_LEN);
224*a1157835SDaniel Fojt
225*a1157835SDaniel Fojt return 0;
226*a1157835SDaniel Fojt }
227*a1157835SDaniel Fojt
228*a1157835SDaniel Fojt
tls_cipher_suite_match(const u16 * list,size_t count,u16 cs)229*a1157835SDaniel Fojt static int tls_cipher_suite_match(const u16 *list, size_t count, u16 cs)
230*a1157835SDaniel Fojt {
231*a1157835SDaniel Fojt size_t i;
232*a1157835SDaniel Fojt
233*a1157835SDaniel Fojt for (i = 0; i < count; i++) {
234*a1157835SDaniel Fojt if (list[i] == cs)
235*a1157835SDaniel Fojt return 1;
236*a1157835SDaniel Fojt }
237*a1157835SDaniel Fojt
238*a1157835SDaniel Fojt return 0;
239*a1157835SDaniel Fojt }
240*a1157835SDaniel Fojt
241*a1157835SDaniel Fojt
tls_cipher_suite_mac_sha1(u16 cs)242*a1157835SDaniel Fojt static int tls_cipher_suite_mac_sha1(u16 cs)
243*a1157835SDaniel Fojt {
244*a1157835SDaniel Fojt static const u16 sha1_cs[] = {
245*a1157835SDaniel Fojt 0x0005, 0x0007, 0x000a, 0x000d, 0x0010, 0x0013, 0x0016, 0x001b,
246*a1157835SDaniel Fojt 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036,
247*a1157835SDaniel Fojt 0x0037, 0x0038, 0x0039, 0x003a, 0x0041, 0x0042, 0x0043, 0x0044,
248*a1157835SDaniel Fojt 0x0045, 0x0046, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089,
249*a1157835SDaniel Fojt 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091,
250*a1157835SDaniel Fojt 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099,
251*a1157835SDaniel Fojt 0x009a, 0x009b,
252*a1157835SDaniel Fojt 0xc002, 0xc003, 0xc004, 0xc005, 0xc007, 0xc008, 0xc009, 0xc009,
253*a1157835SDaniel Fojt 0xc00a, 0xc00c, 0xc00d, 0xc00e, 0xc00f, 0xc011, 0xc012, 0xc013,
254*a1157835SDaniel Fojt 0xc014, 0xc016, 0xc017, 0xc018, 0xc019, 0xc01a, 0xc01b, 0xc01c,
255*a1157835SDaniel Fojt 0xc014, 0xc01e, 0xc01f, 0xc020, 0xc021, 0xc022, 0xc033, 0xc034,
256*a1157835SDaniel Fojt 0xc035, 0xc036
257*a1157835SDaniel Fojt };
258*a1157835SDaniel Fojt
259*a1157835SDaniel Fojt return tls_cipher_suite_match(sha1_cs, ARRAY_SIZE(sha1_cs), cs);
260*a1157835SDaniel Fojt }
261*a1157835SDaniel Fojt
262*a1157835SDaniel Fojt
tls_cipher_suite_mac_sha256(u16 cs)263*a1157835SDaniel Fojt static int tls_cipher_suite_mac_sha256(u16 cs)
264*a1157835SDaniel Fojt {
265*a1157835SDaniel Fojt static const u16 sha256_cs[] = {
266*a1157835SDaniel Fojt 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0067, 0x0068, 0x0069,
267*a1157835SDaniel Fojt 0x006a, 0x006b, 0x006c, 0x006d, 0x009c, 0x009e, 0x00a0, 0x00a2,
268*a1157835SDaniel Fojt 0x00a4, 0x00a6, 0x00a8, 0x00aa, 0x00ac, 0x00ae, 0x00b2, 0x00b6,
269*a1157835SDaniel Fojt 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bd, 0x00be, 0x00be,
270*a1157835SDaniel Fojt 0x00bf, 0x00bf, 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5,
271*a1157835SDaniel Fojt 0x1301, 0x1303, 0x1304, 0x1305,
272*a1157835SDaniel Fojt 0xc023, 0xc025, 0xc027, 0xc029, 0xc02b, 0xc02d, 0xc02f, 0xc031,
273*a1157835SDaniel Fojt 0xc037, 0xc03c, 0xc03e, 0xc040, 0xc040, 0xc042, 0xc044, 0xc046,
274*a1157835SDaniel Fojt 0xc048, 0xc04a, 0xc04c, 0xc04e, 0xc050, 0xc052, 0xc054, 0xc056,
275*a1157835SDaniel Fojt 0xc058, 0xc05a, 0xc05c, 0xc05e, 0xc060, 0xc062, 0xc064, 0xc066,
276*a1157835SDaniel Fojt 0xc068, 0xc06a, 0xc06c, 0xc06e, 0xc070, 0xc072, 0xc074, 0xc076,
277*a1157835SDaniel Fojt 0xc078, 0xc07a, 0xc07c, 0xc07e, 0xc080, 0xc082, 0xc084, 0xc086,
278*a1157835SDaniel Fojt 0xc088, 0xc08a, 0xc08c, 0xc08e, 0xc090, 0xc092, 0xc094, 0xc096,
279*a1157835SDaniel Fojt 0xc098, 0xc09a, 0xc0b0, 0xc0b2, 0xc0b4,
280*a1157835SDaniel Fojt 0xcca8, 0xcca9, 0xccaa, 0xccab, 0xccac, 0xccad, 0xccae,
281*a1157835SDaniel Fojt 0xd001, 0xd003, 0xd005
282*a1157835SDaniel Fojt };
283*a1157835SDaniel Fojt
284*a1157835SDaniel Fojt return tls_cipher_suite_match(sha256_cs, ARRAY_SIZE(sha256_cs), cs);
285*a1157835SDaniel Fojt }
286*a1157835SDaniel Fojt
287*a1157835SDaniel Fojt
tls_cipher_suite_mac_sha384(u16 cs)288*a1157835SDaniel Fojt static int tls_cipher_suite_mac_sha384(u16 cs)
289*a1157835SDaniel Fojt {
290*a1157835SDaniel Fojt static const u16 sha384_cs[] = {
291*a1157835SDaniel Fojt 0x009d, 0x009f, 0x00a1, 0x00a3, 0x00a5, 0x00a7, 0x00a9, 0x00ab,
292*a1157835SDaniel Fojt 0x00ad, 0x00af, 0x00b3, 0x00b7, 0x1302,
293*a1157835SDaniel Fojt 0xc024, 0xc026, 0xc028, 0xc02a, 0xc02c, 0xc02e, 0xc030, 0xc032,
294*a1157835SDaniel Fojt 0xc038, 0xc03d, 0xc03f, 0xc041, 0xc043, 0xc045, 0xc047, 0xc049,
295*a1157835SDaniel Fojt 0xc04b, 0xc04d, 0xc04f, 0xc051, 0xc053, 0xc055, 0xc057, 0xc059,
296*a1157835SDaniel Fojt 0xc05b, 0xc05d, 0xc05f, 0xc061, 0xc063, 0xc065, 0xc067, 0xc069,
297*a1157835SDaniel Fojt 0xc06b, 0xc06d, 0xc06f, 0xc071, 0xc073, 0xc075, 0xc077, 0xc079,
298*a1157835SDaniel Fojt 0xc07b, 0xc07d, 0xc07f, 0xc081, 0xc083, 0xc085, 0xc087, 0xc089,
299*a1157835SDaniel Fojt 0xc08b, 0xc08d, 0xc08f, 0xc091, 0xc093, 0xc095, 0xc097, 0xc099,
300*a1157835SDaniel Fojt 0xc09b, 0xc0b1, 0xc0b3, 0xc0b5,
301*a1157835SDaniel Fojt 0xd002
302*a1157835SDaniel Fojt };
303*a1157835SDaniel Fojt
304*a1157835SDaniel Fojt return tls_cipher_suite_match(sha384_cs, ARRAY_SIZE(sha384_cs), cs);
305*a1157835SDaniel Fojt }
306*a1157835SDaniel Fojt
307*a1157835SDaniel Fojt
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)308*a1157835SDaniel Fojt static int eap_teap_tls_mac(u16 tls_cs, const u8 *cmk, size_t cmk_len,
309*a1157835SDaniel Fojt const u8 *buffer, size_t buffer_len,
310*a1157835SDaniel Fojt u8 *mac, size_t mac_len)
311*a1157835SDaniel Fojt {
312*a1157835SDaniel Fojt int res;
313*a1157835SDaniel Fojt u8 tmp[48];
314*a1157835SDaniel Fojt
315*a1157835SDaniel Fojt os_memset(tmp, 0, sizeof(tmp));
316*a1157835SDaniel Fojt os_memset(mac, 0, mac_len);
317*a1157835SDaniel Fojt
318*a1157835SDaniel Fojt if (tls_cipher_suite_mac_sha1(tls_cs)) {
319*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA1");
320*a1157835SDaniel Fojt res = hmac_sha1(cmk, cmk_len, buffer, buffer_len, tmp);
321*a1157835SDaniel Fojt } else if (tls_cipher_suite_mac_sha256(tls_cs)) {
322*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA256");
323*a1157835SDaniel Fojt res = hmac_sha256(cmk, cmk_len, buffer, buffer_len, tmp);
324*a1157835SDaniel Fojt } else if (tls_cipher_suite_mac_sha384(tls_cs)) {
325*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA384");
326*a1157835SDaniel Fojt res = hmac_sha384(cmk, cmk_len, buffer, buffer_len, tmp);
327*a1157835SDaniel Fojt } else {
328*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
329*a1157835SDaniel Fojt "EAP-TEAP: Unsupported TLS cipher suite 0x%04x",
330*a1157835SDaniel Fojt tls_cs);
331*a1157835SDaniel Fojt res = -1;
332*a1157835SDaniel Fojt }
333*a1157835SDaniel Fojt if (res < 0)
334*a1157835SDaniel Fojt return res;
335*a1157835SDaniel Fojt
336*a1157835SDaniel Fojt /* FIX: RFC 7170 does not describe how to handle truncation of the
337*a1157835SDaniel Fojt * Compound MAC or if the fields are supposed to be of variable length
338*a1157835SDaniel Fojt * based on the negotiated TLS cipher suite (they are defined as having
339*a1157835SDaniel Fojt * fixed size of 20 octets in the TLV description) */
340*a1157835SDaniel Fojt if (mac_len > sizeof(tmp))
341*a1157835SDaniel Fojt mac_len = sizeof(tmp);
342*a1157835SDaniel Fojt os_memcpy(mac, tmp, mac_len);
343*a1157835SDaniel Fojt return 0;
344*a1157835SDaniel Fojt }
345*a1157835SDaniel Fojt
346*a1157835SDaniel Fojt
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)347*a1157835SDaniel Fojt int eap_teap_compound_mac(u16 tls_cs, const struct teap_tlv_crypto_binding *cb,
348*a1157835SDaniel Fojt const struct wpabuf *server_outer_tlvs,
349*a1157835SDaniel Fojt const struct wpabuf *peer_outer_tlvs,
350*a1157835SDaniel Fojt const u8 *cmk, u8 *compound_mac)
351*a1157835SDaniel Fojt {
352*a1157835SDaniel Fojt u8 *pos, *buffer;
353*a1157835SDaniel Fojt size_t bind_len, buffer_len;
354*a1157835SDaniel Fojt struct teap_tlv_crypto_binding *tmp_cb;
355*a1157835SDaniel Fojt int res;
356*a1157835SDaniel Fojt
357*a1157835SDaniel Fojt /* RFC 7170, Section 5.3 */
358*a1157835SDaniel Fojt bind_len = sizeof(struct teap_tlv_hdr) + be_to_host16(cb->length);
359*a1157835SDaniel Fojt buffer_len = bind_len + 1;
360*a1157835SDaniel Fojt if (server_outer_tlvs)
361*a1157835SDaniel Fojt buffer_len += wpabuf_len(server_outer_tlvs);
362*a1157835SDaniel Fojt if (peer_outer_tlvs)
363*a1157835SDaniel Fojt buffer_len += wpabuf_len(peer_outer_tlvs);
364*a1157835SDaniel Fojt buffer = os_malloc(buffer_len);
365*a1157835SDaniel Fojt if (!buffer)
366*a1157835SDaniel Fojt return -1;
367*a1157835SDaniel Fojt
368*a1157835SDaniel Fojt pos = buffer;
369*a1157835SDaniel Fojt /* 1. The entire Crypto-Binding TLV attribute with both the EMSK and MSK
370*a1157835SDaniel Fojt * Compound MAC fields zeroed out. */
371*a1157835SDaniel Fojt os_memcpy(pos, cb, bind_len);
372*a1157835SDaniel Fojt pos += bind_len;
373*a1157835SDaniel Fojt tmp_cb = (struct teap_tlv_crypto_binding *) buffer;
374*a1157835SDaniel Fojt os_memset(tmp_cb->emsk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN);
375*a1157835SDaniel Fojt os_memset(tmp_cb->msk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN);
376*a1157835SDaniel Fojt
377*a1157835SDaniel Fojt /* 2. The EAP Type sent by the other party in the first TEAP message. */
378*a1157835SDaniel Fojt /* This is supposed to be the EAP Type sent by the other party in the
379*a1157835SDaniel Fojt * first TEAP message, but since we cannot get here without having
380*a1157835SDaniel Fojt * successfully negotiated use of TEAP, this can only be the fixed EAP
381*a1157835SDaniel Fojt * Type of TEAP. */
382*a1157835SDaniel Fojt *pos++ = EAP_TYPE_TEAP;
383*a1157835SDaniel Fojt
384*a1157835SDaniel Fojt /* 3. All the Outer TLVs from the first TEAP message sent by EAP server
385*a1157835SDaniel Fojt * to peer. */
386*a1157835SDaniel Fojt if (server_outer_tlvs) {
387*a1157835SDaniel Fojt os_memcpy(pos, wpabuf_head(server_outer_tlvs),
388*a1157835SDaniel Fojt wpabuf_len(server_outer_tlvs));
389*a1157835SDaniel Fojt pos += wpabuf_len(server_outer_tlvs);
390*a1157835SDaniel Fojt }
391*a1157835SDaniel Fojt
392*a1157835SDaniel Fojt /* 4. All the Outer TLVs from the first TEAP message sent by the peer to
393*a1157835SDaniel Fojt * the EAP server. */
394*a1157835SDaniel Fojt if (peer_outer_tlvs) {
395*a1157835SDaniel Fojt os_memcpy(pos, wpabuf_head(peer_outer_tlvs),
396*a1157835SDaniel Fojt wpabuf_len(peer_outer_tlvs));
397*a1157835SDaniel Fojt pos += wpabuf_len(peer_outer_tlvs);
398*a1157835SDaniel Fojt }
399*a1157835SDaniel Fojt
400*a1157835SDaniel Fojt buffer_len = pos - buffer;
401*a1157835SDaniel Fojt
402*a1157835SDaniel Fojt wpa_hexdump_key(MSG_MSGDUMP,
403*a1157835SDaniel Fojt "EAP-TEAP: CMK for Compound MAC calculation",
404*a1157835SDaniel Fojt cmk, EAP_TEAP_CMK_LEN);
405*a1157835SDaniel Fojt wpa_hexdump(MSG_MSGDUMP,
406*a1157835SDaniel Fojt "EAP-TEAP: BUFFER for Compound MAC calculation",
407*a1157835SDaniel Fojt buffer, buffer_len);
408*a1157835SDaniel Fojt res = eap_teap_tls_mac(tls_cs, cmk, EAP_TEAP_CMK_LEN,
409*a1157835SDaniel Fojt buffer, buffer_len,
410*a1157835SDaniel Fojt compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
411*a1157835SDaniel Fojt os_free(buffer);
412*a1157835SDaniel Fojt
413*a1157835SDaniel Fojt return res;
414*a1157835SDaniel Fojt }
415*a1157835SDaniel Fojt
416*a1157835SDaniel Fojt
eap_teap_parse_tlv(struct eap_teap_tlv_parse * tlv,int tlv_type,u8 * pos,size_t len)417*a1157835SDaniel Fojt int eap_teap_parse_tlv(struct eap_teap_tlv_parse *tlv,
418*a1157835SDaniel Fojt int tlv_type, u8 *pos, size_t len)
419*a1157835SDaniel Fojt {
420*a1157835SDaniel Fojt switch (tlv_type) {
421*a1157835SDaniel Fojt case TEAP_TLV_RESULT:
422*a1157835SDaniel Fojt wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Result TLV", pos, len);
423*a1157835SDaniel Fojt if (tlv->result) {
424*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
425*a1157835SDaniel Fojt "EAP-TEAP: More than one Result TLV in the message");
426*a1157835SDaniel Fojt tlv->result = TEAP_STATUS_FAILURE;
427*a1157835SDaniel Fojt return -2;
428*a1157835SDaniel Fojt }
429*a1157835SDaniel Fojt if (len < 2) {
430*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "EAP-TEAP: Too short Result TLV");
431*a1157835SDaniel Fojt tlv->result = TEAP_STATUS_FAILURE;
432*a1157835SDaniel Fojt break;
433*a1157835SDaniel Fojt }
434*a1157835SDaniel Fojt tlv->result = WPA_GET_BE16(pos);
435*a1157835SDaniel Fojt if (tlv->result != TEAP_STATUS_SUCCESS &&
436*a1157835SDaniel Fojt tlv->result != TEAP_STATUS_FAILURE) {
437*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "EAP-TEAP: Unknown Result %d",
438*a1157835SDaniel Fojt tlv->result);
439*a1157835SDaniel Fojt tlv->result = TEAP_STATUS_FAILURE;
440*a1157835SDaniel Fojt }
441*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "EAP-TEAP: Result: %s",
442*a1157835SDaniel Fojt tlv->result == TEAP_STATUS_SUCCESS ?
443*a1157835SDaniel Fojt "Success" : "Failure");
444*a1157835SDaniel Fojt break;
445*a1157835SDaniel Fojt case TEAP_TLV_NAK:
446*a1157835SDaniel Fojt wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: NAK TLV", pos, len);
447*a1157835SDaniel Fojt if (len < 6) {
448*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "EAP-TEAP: Too short NAK TLV");
449*a1157835SDaniel Fojt tlv->result = TEAP_STATUS_FAILURE;
450*a1157835SDaniel Fojt break;
451*a1157835SDaniel Fojt }
452*a1157835SDaniel Fojt tlv->nak = pos;
453*a1157835SDaniel Fojt tlv->nak_len = len;
454*a1157835SDaniel Fojt break;
455*a1157835SDaniel Fojt case TEAP_TLV_REQUEST_ACTION:
456*a1157835SDaniel Fojt wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Request-Action TLV",
457*a1157835SDaniel Fojt pos, len);
458*a1157835SDaniel Fojt if (tlv->request_action) {
459*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
460*a1157835SDaniel Fojt "EAP-TEAP: More than one Request-Action TLV in the message");
461*a1157835SDaniel Fojt tlv->iresult = TEAP_STATUS_FAILURE;
462*a1157835SDaniel Fojt return -2;
463*a1157835SDaniel Fojt }
464*a1157835SDaniel Fojt if (len < 2) {
465*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
466*a1157835SDaniel Fojt "EAP-TEAP: Too short Request-Action TLV");
467*a1157835SDaniel Fojt tlv->iresult = TEAP_STATUS_FAILURE;
468*a1157835SDaniel Fojt break;
469*a1157835SDaniel Fojt }
470*a1157835SDaniel Fojt tlv->request_action_status = pos[0];
471*a1157835SDaniel Fojt tlv->request_action = pos[1];
472*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
473*a1157835SDaniel Fojt "EAP-TEAP: Request-Action: Status=%u Action=%u",
474*a1157835SDaniel Fojt tlv->request_action_status, tlv->request_action);
475*a1157835SDaniel Fojt break;
476*a1157835SDaniel Fojt case TEAP_TLV_EAP_PAYLOAD:
477*a1157835SDaniel Fojt wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: EAP-Payload TLV",
478*a1157835SDaniel Fojt pos, len);
479*a1157835SDaniel Fojt if (tlv->eap_payload_tlv) {
480*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
481*a1157835SDaniel Fojt "EAP-TEAP: More than one EAP-Payload TLV in the message");
482*a1157835SDaniel Fojt tlv->iresult = TEAP_STATUS_FAILURE;
483*a1157835SDaniel Fojt return -2;
484*a1157835SDaniel Fojt }
485*a1157835SDaniel Fojt tlv->eap_payload_tlv = pos;
486*a1157835SDaniel Fojt tlv->eap_payload_tlv_len = len;
487*a1157835SDaniel Fojt break;
488*a1157835SDaniel Fojt case TEAP_TLV_INTERMEDIATE_RESULT:
489*a1157835SDaniel Fojt wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Intermediate-Result TLV",
490*a1157835SDaniel Fojt pos, len);
491*a1157835SDaniel Fojt if (len < 2) {
492*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
493*a1157835SDaniel Fojt "EAP-TEAP: Too short Intermediate-Result TLV");
494*a1157835SDaniel Fojt tlv->iresult = TEAP_STATUS_FAILURE;
495*a1157835SDaniel Fojt break;
496*a1157835SDaniel Fojt }
497*a1157835SDaniel Fojt if (tlv->iresult) {
498*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
499*a1157835SDaniel Fojt "EAP-TEAP: More than one Intermediate-Result TLV in the message");
500*a1157835SDaniel Fojt tlv->iresult = TEAP_STATUS_FAILURE;
501*a1157835SDaniel Fojt return -2;
502*a1157835SDaniel Fojt }
503*a1157835SDaniel Fojt tlv->iresult = WPA_GET_BE16(pos);
504*a1157835SDaniel Fojt if (tlv->iresult != TEAP_STATUS_SUCCESS &&
505*a1157835SDaniel Fojt tlv->iresult != TEAP_STATUS_FAILURE) {
506*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
507*a1157835SDaniel Fojt "EAP-TEAP: Unknown Intermediate Result %d",
508*a1157835SDaniel Fojt tlv->iresult);
509*a1157835SDaniel Fojt tlv->iresult = TEAP_STATUS_FAILURE;
510*a1157835SDaniel Fojt }
511*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "EAP-TEAP: Intermediate Result: %s",
512*a1157835SDaniel Fojt tlv->iresult == TEAP_STATUS_SUCCESS ?
513*a1157835SDaniel Fojt "Success" : "Failure");
514*a1157835SDaniel Fojt break;
515*a1157835SDaniel Fojt case TEAP_TLV_PAC:
516*a1157835SDaniel Fojt wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: PAC TLV", pos, len);
517*a1157835SDaniel Fojt if (tlv->pac) {
518*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
519*a1157835SDaniel Fojt "EAP-TEAP: More than one PAC TLV in the message");
520*a1157835SDaniel Fojt tlv->iresult = TEAP_STATUS_FAILURE;
521*a1157835SDaniel Fojt return -2;
522*a1157835SDaniel Fojt }
523*a1157835SDaniel Fojt tlv->pac = pos;
524*a1157835SDaniel Fojt tlv->pac_len = len;
525*a1157835SDaniel Fojt break;
526*a1157835SDaniel Fojt case TEAP_TLV_CRYPTO_BINDING:
527*a1157835SDaniel Fojt wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Crypto-Binding TLV",
528*a1157835SDaniel Fojt pos, len);
529*a1157835SDaniel Fojt if (tlv->crypto_binding) {
530*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
531*a1157835SDaniel Fojt "EAP-TEAP: More than one Crypto-Binding TLV in the message");
532*a1157835SDaniel Fojt tlv->iresult = TEAP_STATUS_FAILURE;
533*a1157835SDaniel Fojt return -2;
534*a1157835SDaniel Fojt }
535*a1157835SDaniel Fojt tlv->crypto_binding_len = sizeof(struct teap_tlv_hdr) + len;
536*a1157835SDaniel Fojt if (tlv->crypto_binding_len < sizeof(*tlv->crypto_binding)) {
537*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
538*a1157835SDaniel Fojt "EAP-TEAP: Too short Crypto-Binding TLV");
539*a1157835SDaniel Fojt tlv->iresult = TEAP_STATUS_FAILURE;
540*a1157835SDaniel Fojt return -2;
541*a1157835SDaniel Fojt }
542*a1157835SDaniel Fojt tlv->crypto_binding = (struct teap_tlv_crypto_binding *)
543*a1157835SDaniel Fojt (pos - sizeof(struct teap_tlv_hdr));
544*a1157835SDaniel Fojt break;
545*a1157835SDaniel Fojt case TEAP_TLV_BASIC_PASSWORD_AUTH_REQ:
546*a1157835SDaniel Fojt wpa_hexdump_ascii(MSG_MSGDUMP,
547*a1157835SDaniel Fojt "EAP-TEAP: Basic-Password-Auth-Req TLV",
548*a1157835SDaniel Fojt pos, len);
549*a1157835SDaniel Fojt if (tlv->basic_auth_req) {
550*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
551*a1157835SDaniel Fojt "EAP-TEAP: More than one Basic-Password-Auth-Req TLV in the message");
552*a1157835SDaniel Fojt tlv->iresult = TEAP_STATUS_FAILURE;
553*a1157835SDaniel Fojt return -2;
554*a1157835SDaniel Fojt }
555*a1157835SDaniel Fojt tlv->basic_auth_req = pos;
556*a1157835SDaniel Fojt tlv->basic_auth_req_len = len;
557*a1157835SDaniel Fojt break;
558*a1157835SDaniel Fojt case TEAP_TLV_BASIC_PASSWORD_AUTH_RESP:
559*a1157835SDaniel Fojt wpa_hexdump_ascii(MSG_MSGDUMP,
560*a1157835SDaniel Fojt "EAP-TEAP: Basic-Password-Auth-Resp TLV",
561*a1157835SDaniel Fojt pos, len);
562*a1157835SDaniel Fojt if (tlv->basic_auth_resp) {
563*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
564*a1157835SDaniel Fojt "EAP-TEAP: More than one Basic-Password-Auth-Resp TLV in the message");
565*a1157835SDaniel Fojt tlv->iresult = TEAP_STATUS_FAILURE;
566*a1157835SDaniel Fojt return -2;
567*a1157835SDaniel Fojt }
568*a1157835SDaniel Fojt tlv->basic_auth_resp = pos;
569*a1157835SDaniel Fojt tlv->basic_auth_resp_len = len;
570*a1157835SDaniel Fojt break;
571*a1157835SDaniel Fojt default:
572*a1157835SDaniel Fojt /* Unknown TLV */
573*a1157835SDaniel Fojt return -1;
574*a1157835SDaniel Fojt }
575*a1157835SDaniel Fojt
576*a1157835SDaniel Fojt return 0;
577*a1157835SDaniel Fojt }
578*a1157835SDaniel Fojt
579*a1157835SDaniel Fojt
eap_teap_tlv_type_str(enum teap_tlv_types type)580*a1157835SDaniel Fojt const char * eap_teap_tlv_type_str(enum teap_tlv_types type)
581*a1157835SDaniel Fojt {
582*a1157835SDaniel Fojt switch (type) {
583*a1157835SDaniel Fojt case TEAP_TLV_AUTHORITY_ID:
584*a1157835SDaniel Fojt return "Authority-ID";
585*a1157835SDaniel Fojt case TEAP_TLV_IDENTITY_TYPE:
586*a1157835SDaniel Fojt return "Identity-Type";
587*a1157835SDaniel Fojt case TEAP_TLV_RESULT:
588*a1157835SDaniel Fojt return "Result";
589*a1157835SDaniel Fojt case TEAP_TLV_NAK:
590*a1157835SDaniel Fojt return "NAK";
591*a1157835SDaniel Fojt case TEAP_TLV_ERROR:
592*a1157835SDaniel Fojt return "Error";
593*a1157835SDaniel Fojt case TEAP_TLV_CHANNEL_BINDING:
594*a1157835SDaniel Fojt return "Channel-Binding";
595*a1157835SDaniel Fojt case TEAP_TLV_VENDOR_SPECIFIC:
596*a1157835SDaniel Fojt return "Vendor-Specific";
597*a1157835SDaniel Fojt case TEAP_TLV_REQUEST_ACTION:
598*a1157835SDaniel Fojt return "Request-Action";
599*a1157835SDaniel Fojt case TEAP_TLV_EAP_PAYLOAD:
600*a1157835SDaniel Fojt return "EAP-Payload";
601*a1157835SDaniel Fojt case TEAP_TLV_INTERMEDIATE_RESULT:
602*a1157835SDaniel Fojt return "Intermediate-Result";
603*a1157835SDaniel Fojt case TEAP_TLV_PAC:
604*a1157835SDaniel Fojt return "PAC";
605*a1157835SDaniel Fojt case TEAP_TLV_CRYPTO_BINDING:
606*a1157835SDaniel Fojt return "Crypto-Binding";
607*a1157835SDaniel Fojt case TEAP_TLV_BASIC_PASSWORD_AUTH_REQ:
608*a1157835SDaniel Fojt return "Basic-Password-Auth-Req";
609*a1157835SDaniel Fojt case TEAP_TLV_BASIC_PASSWORD_AUTH_RESP:
610*a1157835SDaniel Fojt return "Basic-Password-Auth-Resp";
611*a1157835SDaniel Fojt case TEAP_TLV_PKCS7:
612*a1157835SDaniel Fojt return "PKCS#7";
613*a1157835SDaniel Fojt case TEAP_TLV_PKCS10:
614*a1157835SDaniel Fojt return "PKCS#10";
615*a1157835SDaniel Fojt case TEAP_TLV_TRUSTED_SERVER_ROOT:
616*a1157835SDaniel Fojt return "Trusted-Server-Root";
617*a1157835SDaniel Fojt }
618*a1157835SDaniel Fojt
619*a1157835SDaniel Fojt return "?";
620*a1157835SDaniel Fojt }
621*a1157835SDaniel Fojt
622*a1157835SDaniel Fojt
eap_teap_tlv_result(int status,int intermediate)623*a1157835SDaniel Fojt struct wpabuf * eap_teap_tlv_result(int status, int intermediate)
624*a1157835SDaniel Fojt {
625*a1157835SDaniel Fojt struct wpabuf *buf;
626*a1157835SDaniel Fojt struct teap_tlv_result *result;
627*a1157835SDaniel Fojt
628*a1157835SDaniel Fojt if (status != TEAP_STATUS_FAILURE && status != TEAP_STATUS_SUCCESS)
629*a1157835SDaniel Fojt return NULL;
630*a1157835SDaniel Fojt
631*a1157835SDaniel Fojt buf = wpabuf_alloc(sizeof(*result));
632*a1157835SDaniel Fojt if (!buf)
633*a1157835SDaniel Fojt return NULL;
634*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "EAP-TEAP: Add %sResult TLV(status=%s)",
635*a1157835SDaniel Fojt intermediate ? "Intermediate-" : "",
636*a1157835SDaniel Fojt status == TEAP_STATUS_SUCCESS ? "Success" : "Failure");
637*a1157835SDaniel Fojt result = wpabuf_put(buf, sizeof(*result));
638*a1157835SDaniel Fojt result->tlv_type = host_to_be16(TEAP_TLV_MANDATORY |
639*a1157835SDaniel Fojt (intermediate ?
640*a1157835SDaniel Fojt TEAP_TLV_INTERMEDIATE_RESULT :
641*a1157835SDaniel Fojt TEAP_TLV_RESULT));
642*a1157835SDaniel Fojt result->length = host_to_be16(2);
643*a1157835SDaniel Fojt result->status = host_to_be16(status);
644*a1157835SDaniel Fojt return buf;
645*a1157835SDaniel Fojt }
646*a1157835SDaniel Fojt
647*a1157835SDaniel Fojt
eap_teap_tlv_error(enum teap_error_codes error)648*a1157835SDaniel Fojt struct wpabuf * eap_teap_tlv_error(enum teap_error_codes error)
649*a1157835SDaniel Fojt {
650*a1157835SDaniel Fojt struct wpabuf *buf;
651*a1157835SDaniel Fojt
652*a1157835SDaniel Fojt buf = wpabuf_alloc(4 + 4);
653*a1157835SDaniel Fojt if (!buf)
654*a1157835SDaniel Fojt return NULL;
655*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "EAP-TEAP: Add Error TLV(Error Code=%d)",
656*a1157835SDaniel Fojt error);
657*a1157835SDaniel Fojt wpabuf_put_be16(buf, TEAP_TLV_MANDATORY | TEAP_TLV_ERROR);
658*a1157835SDaniel Fojt wpabuf_put_be16(buf, 4);
659*a1157835SDaniel Fojt wpabuf_put_be32(buf, error);
660*a1157835SDaniel Fojt return buf;
661*a1157835SDaniel Fojt }
662*a1157835SDaniel Fojt
663*a1157835SDaniel Fojt
eap_teap_allowed_anon_prov_phase2_method(u8 type)664*a1157835SDaniel Fojt int eap_teap_allowed_anon_prov_phase2_method(u8 type)
665*a1157835SDaniel Fojt {
666*a1157835SDaniel Fojt /* RFC 7170, Section 3.8.3: MUST provide mutual authentication,
667*a1157835SDaniel Fojt * provide key generation, and be resistant to dictionary attack.
668*a1157835SDaniel Fojt * Section 3.8 also mentions requirement for using EMSK Compound MAC. */
669*a1157835SDaniel Fojt return type == EAP_TYPE_PWD || type == EAP_TYPE_EKE;
670*a1157835SDaniel Fojt }
671*a1157835SDaniel Fojt
672*a1157835SDaniel Fojt
eap_teap_allowed_anon_prov_cipher_suite(u16 cs)673*a1157835SDaniel Fojt int eap_teap_allowed_anon_prov_cipher_suite(u16 cs)
674*a1157835SDaniel Fojt {
675*a1157835SDaniel Fojt /* RFC 7170, Section 3.8.3: anonymous ciphersuites MAY be supported as
676*a1157835SDaniel Fojt * long as the TLS pre-master secret is generated form contribution from
677*a1157835SDaniel Fojt * both peers. Accept the recommended TLS_DH_anon_WITH_AES_128_CBC_SHA
678*a1157835SDaniel Fojt * cipher suite and other ciphersuites that use DH in some form, have
679*a1157835SDaniel Fojt * SHA-1 or stronger MAC function, and use reasonable strong cipher. */
680*a1157835SDaniel Fojt static const u16 ok_cs[] = {
681*a1157835SDaniel Fojt /* DH-anon */
682*a1157835SDaniel Fojt 0x0034, 0x003a, 0x006c, 0x006d, 0x00a6, 0x00a7,
683*a1157835SDaniel Fojt /* DHE-RSA */
684*a1157835SDaniel Fojt 0x0033, 0x0039, 0x0067, 0x006b, 0x009e, 0x009f,
685*a1157835SDaniel Fojt /* ECDH-anon */
686*a1157835SDaniel Fojt 0xc018, 0xc019,
687*a1157835SDaniel Fojt /* ECDH-RSA */
688*a1157835SDaniel Fojt 0xc003, 0xc00f, 0xc029, 0xc02a, 0xc031, 0xc032,
689*a1157835SDaniel Fojt /* ECDH-ECDSA */
690*a1157835SDaniel Fojt 0xc004, 0xc005, 0xc025, 0xc026, 0xc02d, 0xc02e,
691*a1157835SDaniel Fojt /* ECDHE-RSA */
692*a1157835SDaniel Fojt 0xc013, 0xc014, 0xc027, 0xc028, 0xc02f, 0xc030,
693*a1157835SDaniel Fojt /* ECDHE-ECDSA */
694*a1157835SDaniel Fojt 0xc009, 0xc00a, 0xc023, 0xc024, 0xc02b, 0xc02c,
695*a1157835SDaniel Fojt };
696*a1157835SDaniel Fojt
697*a1157835SDaniel Fojt return tls_cipher_suite_match(ok_cs, ARRAY_SIZE(ok_cs), cs);
698*a1157835SDaniel Fojt }
699