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