]> git.ipfire.org Git - thirdparty/hostap.git/blame - src/eap_server/eap_server_teap.c
EAP-TEAP server: Require Intermediate-Result TLV even with Result TLV
[thirdparty/hostap.git] / src / eap_server / eap_server_teap.c
CommitLineData
0ed57c5e
JM
1/*
2 * EAP-TEAP server (RFC 7170)
3 * Copyright (c) 2004-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/aes_wrap.h"
13#include "crypto/tls.h"
14#include "crypto/random.h"
15#include "eap_common/eap_teap_common.h"
16#include "eap_i.h"
17#include "eap_tls_common.h"
18
19
20static void eap_teap_reset(struct eap_sm *sm, void *priv);
21
22
23/* Private PAC-Opaque TLV types */
24#define PAC_OPAQUE_TYPE_PAD 0
25#define PAC_OPAQUE_TYPE_KEY 1
26#define PAC_OPAQUE_TYPE_LIFETIME 2
27#define PAC_OPAQUE_TYPE_IDENTITY 3
28
29struct eap_teap_data {
30 struct eap_ssl_data ssl;
31 enum {
32 START, PHASE1, PHASE1B, PHASE2_START, PHASE2_ID,
33 PHASE2_BASIC_AUTH, PHASE2_METHOD, CRYPTO_BINDING, REQUEST_PAC,
34 FAILURE_SEND_RESULT, SUCCESS, FAILURE
35 } state;
36
37 u8 teap_version;
38 u8 peer_version;
39 u16 tls_cs;
40
41 const struct eap_method *phase2_method;
42 void *phase2_priv;
43
44 u8 crypto_binding_nonce[32];
45 int final_result;
46
47 u8 simck_msk[EAP_TEAP_SIMCK_LEN];
48 u8 cmk_msk[EAP_TEAP_CMK_LEN];
49 u8 simck_emsk[EAP_TEAP_SIMCK_LEN];
50 u8 cmk_emsk[EAP_TEAP_CMK_LEN];
51 int simck_idx;
52 int cmk_emsk_available;
53
54 u8 pac_opaque_encr[16];
55 u8 *srv_id;
56 size_t srv_id_len;
57 char *srv_id_info;
58
59 int anon_provisioning;
60 int send_new_pac; /* server triggered re-keying of Tunnel PAC */
61 struct wpabuf *pending_phase2_resp;
62 struct wpabuf *server_outer_tlvs;
63 struct wpabuf *peer_outer_tlvs;
64 u8 *identity; /* from PAC-Opaque */
65 size_t identity_len;
66 int eap_seq;
67 int tnc_started;
68
69 int pac_key_lifetime;
70 int pac_key_refresh_time;
71
72 enum teap_error_codes error_code;
73};
74
75
76static int eap_teap_process_phase2_start(struct eap_sm *sm,
77 struct eap_teap_data *data);
78
79
80static const char * eap_teap_state_txt(int state)
81{
82 switch (state) {
83 case START:
84 return "START";
85 case PHASE1:
86 return "PHASE1";
87 case PHASE1B:
88 return "PHASE1B";
89 case PHASE2_START:
90 return "PHASE2_START";
91 case PHASE2_ID:
92 return "PHASE2_ID";
93 case PHASE2_BASIC_AUTH:
94 return "PHASE2_BASIC_AUTH";
95 case PHASE2_METHOD:
96 return "PHASE2_METHOD";
97 case CRYPTO_BINDING:
98 return "CRYPTO_BINDING";
99 case REQUEST_PAC:
100 return "REQUEST_PAC";
101 case FAILURE_SEND_RESULT:
102 return "FAILURE_SEND_RESULT";
103 case SUCCESS:
104 return "SUCCESS";
105 case FAILURE:
106 return "FAILURE";
107 default:
108 return "Unknown?!";
109 }
110}
111
112
113static void eap_teap_state(struct eap_teap_data *data, int state)
114{
115 wpa_printf(MSG_DEBUG, "EAP-TEAP: %s -> %s",
116 eap_teap_state_txt(data->state),
117 eap_teap_state_txt(state));
118 data->state = state;
119}
120
121
122static EapType eap_teap_req_failure(struct eap_teap_data *data,
123 enum teap_error_codes error)
124{
125 eap_teap_state(data, FAILURE_SEND_RESULT);
126 return EAP_TYPE_NONE;
127}
128
129
130static int eap_teap_session_ticket_cb(void *ctx, const u8 *ticket, size_t len,
131 const u8 *client_random,
132 const u8 *server_random,
133 u8 *master_secret)
134{
135 struct eap_teap_data *data = ctx;
136 const u8 *pac_opaque;
137 size_t pac_opaque_len;
138 u8 *buf, *pos, *end, *pac_key = NULL;
139 os_time_t lifetime = 0;
140 struct os_time now;
141 u8 *identity = NULL;
142 size_t identity_len = 0;
143
144 wpa_printf(MSG_DEBUG, "EAP-TEAP: SessionTicket callback");
145 wpa_hexdump(MSG_DEBUG, "EAP-TEAP: SessionTicket (PAC-Opaque)",
146 ticket, len);
147
148 if (len < 4 || WPA_GET_BE16(ticket) != PAC_TYPE_PAC_OPAQUE) {
149 wpa_printf(MSG_DEBUG, "EAP-TEAP: Ignore invalid SessionTicket");
150 return 0;
151 }
152
153 pac_opaque_len = WPA_GET_BE16(ticket + 2);
154 pac_opaque = ticket + 4;
155 if (pac_opaque_len < 8 || pac_opaque_len % 8 ||
156 pac_opaque_len > len - 4) {
157 wpa_printf(MSG_DEBUG,
158 "EAP-TEAP: Ignore invalid PAC-Opaque (len=%lu left=%lu)",
159 (unsigned long) pac_opaque_len,
160 (unsigned long) len);
161 return 0;
162 }
163 wpa_hexdump(MSG_DEBUG, "EAP-TEAP: Received PAC-Opaque",
164 pac_opaque, pac_opaque_len);
165
166 buf = os_malloc(pac_opaque_len - 8);
167 if (!buf) {
168 wpa_printf(MSG_DEBUG,
169 "EAP-TEAP: Failed to allocate memory for decrypting PAC-Opaque");
170 return 0;
171 }
172
173 if (aes_unwrap(data->pac_opaque_encr, sizeof(data->pac_opaque_encr),
174 (pac_opaque_len - 8) / 8, pac_opaque, buf) < 0) {
175 wpa_printf(MSG_DEBUG, "EAP-TEAP: Failed to decrypt PAC-Opaque");
176 os_free(buf);
177 /*
178 * This may have been caused by server changing the PAC-Opaque
179 * encryption key, so just ignore this PAC-Opaque instead of
180 * failing the authentication completely. Provisioning can now
181 * be used to provision a new PAC.
182 */
183 return 0;
184 }
185
186 end = buf + pac_opaque_len - 8;
187 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Decrypted PAC-Opaque",
188 buf, end - buf);
189
190 pos = buf;
191 while (end - pos > 1) {
192 u8 id, elen;
193
194 id = *pos++;
195 elen = *pos++;
196 if (elen > end - pos)
197 break;
198
199 switch (id) {
200 case PAC_OPAQUE_TYPE_PAD:
201 goto done;
202 case PAC_OPAQUE_TYPE_KEY:
203 if (elen != EAP_TEAP_PAC_KEY_LEN) {
204 wpa_printf(MSG_DEBUG,
205 "EAP-TEAP: Invalid PAC-Key length %d",
206 elen);
207 os_free(buf);
208 return -1;
209 }
210 pac_key = pos;
211 wpa_hexdump_key(MSG_DEBUG,
212 "EAP-TEAP: PAC-Key from decrypted PAC-Opaque",
213 pac_key, EAP_TEAP_PAC_KEY_LEN);
214 break;
215 case PAC_OPAQUE_TYPE_LIFETIME:
216 if (elen != 4) {
217 wpa_printf(MSG_DEBUG,
218 "EAP-TEAP: Invalid PAC-Key lifetime length %d",
219 elen);
220 os_free(buf);
221 return -1;
222 }
223 lifetime = WPA_GET_BE32(pos);
224 break;
225 case PAC_OPAQUE_TYPE_IDENTITY:
226 identity = pos;
227 identity_len = elen;
228 break;
229 }
230
231 pos += elen;
232 }
233done:
234
235 if (!pac_key) {
236 wpa_printf(MSG_DEBUG,
237 "EAP-TEAP: No PAC-Key included in PAC-Opaque");
238 os_free(buf);
239 return -1;
240 }
241
242 if (identity) {
243 wpa_hexdump_ascii(MSG_DEBUG,
244 "EAP-TEAP: Identity from PAC-Opaque",
245 identity, identity_len);
246 os_free(data->identity);
247 data->identity = os_malloc(identity_len);
248 if (data->identity) {
249 os_memcpy(data->identity, identity, identity_len);
250 data->identity_len = identity_len;
251 }
252 }
253
254 if (os_get_time(&now) < 0 || lifetime <= 0 || now.sec > lifetime) {
255 wpa_printf(MSG_DEBUG,
256 "EAP-TEAP: PAC-Key not valid anymore (lifetime=%ld now=%ld)",
257 lifetime, now.sec);
258 data->send_new_pac = 2;
259 /*
260 * Allow PAC to be used to allow a PAC update with some level
261 * of server authentication (i.e., do not fall back to full TLS
262 * handshake since we cannot be sure that the peer would be
263 * able to validate server certificate now). However, reject
264 * the authentication since the PAC was not valid anymore. Peer
265 * can connect again with the newly provisioned PAC after this.
266 */
267 } else if (lifetime - now.sec < data->pac_key_refresh_time) {
268 wpa_printf(MSG_DEBUG,
269 "EAP-TEAP: PAC-Key soft timeout; send an update if authentication succeeds");
270 data->send_new_pac = 1;
271 }
272
273 /* EAP-TEAP uses PAC-Key as the TLS master_secret */
274 os_memcpy(master_secret, pac_key, EAP_TEAP_PAC_KEY_LEN);
275
276 os_free(buf);
277
278 return 1;
279}
280
281
282static int eap_teap_derive_key_auth(struct eap_sm *sm,
283 struct eap_teap_data *data)
284{
285 int res;
286
287 /* RFC 7170, Section 5.1 */
288 res = tls_connection_export_key(sm->ssl_ctx, data->ssl.conn,
289 TEAP_TLS_EXPORTER_LABEL_SKS, NULL, 0,
290 data->simck_msk, EAP_TEAP_SIMCK_LEN);
291 if (res)
292 return res;
293 wpa_hexdump_key(MSG_DEBUG,
294 "EAP-TEAP: session_key_seed (S-IMCK[0])",
295 data->simck_msk, EAP_TEAP_SIMCK_LEN);
296 os_memcpy(data->simck_emsk, data->simck_msk, EAP_TEAP_SIMCK_LEN);
297 data->simck_idx = 0;
298 return 0;
299}
300
301
302static int eap_teap_update_icmk(struct eap_sm *sm, struct eap_teap_data *data)
303{
304 u8 *msk = NULL, *emsk = NULL;
305 size_t msk_len = 0, emsk_len = 0;
306 int res;
307
308 wpa_printf(MSG_DEBUG, "EAP-TEAP: Deriving ICMK[%d] (S-IMCK and CMK)",
309 data->simck_idx + 1);
310
311 if (sm->eap_teap_auth == 1)
a66e53c4
JM
312 return eap_teap_derive_cmk_basic_pw_auth(data->tls_cs,
313 data->simck_msk,
0ed57c5e
JM
314 data->cmk_msk);
315
316 if (!data->phase2_method || !data->phase2_priv) {
317 wpa_printf(MSG_INFO, "EAP-TEAP: Phase 2 method not available");
318 return -1;
319 }
320
321 if (data->phase2_method->getKey) {
322 msk = data->phase2_method->getKey(sm, data->phase2_priv,
323 &msk_len);
324 if (!msk) {
325 wpa_printf(MSG_INFO,
326 "EAP-TEAP: Could not fetch Phase 2 MSK");
327 return -1;
328 }
329 }
330
331 if (data->phase2_method->get_emsk) {
332 emsk = data->phase2_method->get_emsk(sm, data->phase2_priv,
333 &emsk_len);
334 }
335
a66e53c4
JM
336 res = eap_teap_derive_imck(data->tls_cs,
337 data->simck_msk, data->simck_emsk,
0ed57c5e
JM
338 msk, msk_len, emsk, emsk_len,
339 data->simck_msk, data->cmk_msk,
340 data->simck_emsk, data->cmk_emsk);
341 bin_clear_free(msk, msk_len);
342 bin_clear_free(emsk, emsk_len);
343 if (res == 0) {
344 data->simck_idx++;
345 if (emsk)
346 data->cmk_emsk_available = 1;
347 }
348 return 0;
349}
350
351
352static void * eap_teap_init(struct eap_sm *sm)
353{
354 struct eap_teap_data *data;
355
356 data = os_zalloc(sizeof(*data));
357 if (!data)
358 return NULL;
359 data->teap_version = EAP_TEAP_VERSION;
360 data->state = START;
361
362 if (eap_server_tls_ssl_init(sm, &data->ssl, 0, EAP_TYPE_TEAP)) {
363 wpa_printf(MSG_INFO, "EAP-TEAP: Failed to initialize SSL.");
364 eap_teap_reset(sm, data);
365 return NULL;
366 }
367
368 /* TODO: Add anon-DH TLS cipher suites (and if one is negotiated,
369 * enforce inner EAP with mutual authentication to be used) */
370
371 if (tls_connection_set_session_ticket_cb(sm->ssl_ctx, data->ssl.conn,
372 eap_teap_session_ticket_cb,
373 data) < 0) {
374 wpa_printf(MSG_INFO,
375 "EAP-TEAP: Failed to set SessionTicket callback");
376 eap_teap_reset(sm, data);
377 return NULL;
378 }
379
380 if (!sm->pac_opaque_encr_key) {
381 wpa_printf(MSG_INFO,
382 "EAP-TEAP: No PAC-Opaque encryption key configured");
383 eap_teap_reset(sm, data);
384 return NULL;
385 }
386 os_memcpy(data->pac_opaque_encr, sm->pac_opaque_encr_key,
387 sizeof(data->pac_opaque_encr));
388
389 if (!sm->eap_fast_a_id) {
390 wpa_printf(MSG_INFO, "EAP-TEAP: No A-ID configured");
391 eap_teap_reset(sm, data);
392 return NULL;
393 }
394 data->srv_id = os_malloc(sm->eap_fast_a_id_len);
395 if (!data->srv_id) {
396 eap_teap_reset(sm, data);
397 return NULL;
398 }
399 os_memcpy(data->srv_id, sm->eap_fast_a_id, sm->eap_fast_a_id_len);
400 data->srv_id_len = sm->eap_fast_a_id_len;
401
402 if (!sm->eap_fast_a_id_info) {
403 wpa_printf(MSG_INFO, "EAP-TEAP: No A-ID-Info configured");
404 eap_teap_reset(sm, data);
405 return NULL;
406 }
407 data->srv_id_info = os_strdup(sm->eap_fast_a_id_info);
408 if (!data->srv_id_info) {
409 eap_teap_reset(sm, data);
410 return NULL;
411 }
412
413 /* PAC-Key lifetime in seconds (hard limit) */
414 data->pac_key_lifetime = sm->pac_key_lifetime;
415
416 /*
417 * PAC-Key refresh time in seconds (soft limit on remaining hard
418 * limit). The server will generate a new PAC-Key when this number of
419 * seconds (or fewer) of the lifetime remains.
420 */
421 data->pac_key_refresh_time = sm->pac_key_refresh_time;
422
423 return data;
424}
425
426
427static void eap_teap_reset(struct eap_sm *sm, void *priv)
428{
429 struct eap_teap_data *data = priv;
430
431 if (!data)
432 return;
433 if (data->phase2_priv && data->phase2_method)
434 data->phase2_method->reset(sm, data->phase2_priv);
435 eap_server_tls_ssl_deinit(sm, &data->ssl);
436 os_free(data->srv_id);
437 os_free(data->srv_id_info);
438 wpabuf_free(data->pending_phase2_resp);
439 wpabuf_free(data->server_outer_tlvs);
440 wpabuf_free(data->peer_outer_tlvs);
441 os_free(data->identity);
442 forced_memzero(data->simck_msk, EAP_TEAP_SIMCK_LEN);
443 forced_memzero(data->simck_emsk, EAP_TEAP_SIMCK_LEN);
444 forced_memzero(data->cmk_msk, EAP_TEAP_CMK_LEN);
445 forced_memzero(data->cmk_emsk, EAP_TEAP_CMK_LEN);
446 forced_memzero(data->pac_opaque_encr, sizeof(data->pac_opaque_encr));
447 bin_clear_free(data, sizeof(*data));
448}
449
450
451static struct wpabuf * eap_teap_build_start(struct eap_sm *sm,
452 struct eap_teap_data *data, u8 id)
453{
454 struct wpabuf *req;
455 size_t outer_tlv_len = sizeof(struct teap_tlv_hdr) + data->srv_id_len;
456 const u8 *start, *end;
457
458 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TEAP,
459 1 + 4 + outer_tlv_len, EAP_CODE_REQUEST, id);
460 if (!req) {
461 wpa_printf(MSG_ERROR,
462 "EAP-TEAP: Failed to allocate memory for request");
463 eap_teap_state(data, FAILURE);
464 return NULL;
465 }
466
467 wpabuf_put_u8(req, EAP_TLS_FLAGS_START | EAP_TEAP_FLAGS_OUTER_TLV_LEN |
468 data->teap_version);
469 wpabuf_put_be32(req, outer_tlv_len);
470
471 start = wpabuf_put(req, 0);
472
473 /* RFC 7170, Section 4.2.2: Authority-ID TLV */
474 eap_teap_put_tlv(req, TEAP_TLV_AUTHORITY_ID,
475 data->srv_id, data->srv_id_len);
476
477 end = wpabuf_put(req, 0);
478 wpabuf_free(data->server_outer_tlvs);
479 data->server_outer_tlvs = wpabuf_alloc_copy(start, end - start);
480 if (!data->server_outer_tlvs) {
481 eap_teap_state(data, FAILURE);
482 return NULL;
483 }
484
485 eap_teap_state(data, PHASE1);
486
487 return req;
488}
489
490
491static int eap_teap_phase1_done(struct eap_sm *sm, struct eap_teap_data *data)
492{
493 char cipher[64];
494
495 wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 1 done, starting Phase 2");
496
497 data->tls_cs = tls_connection_get_cipher_suite(data->ssl.conn);
498 wpa_printf(MSG_DEBUG, "EAP-TEAP: TLS cipher suite 0x%04x",
499 data->tls_cs);
500
501 if (tls_get_cipher(sm->ssl_ctx, data->ssl.conn, cipher, sizeof(cipher))
502 < 0) {
503 wpa_printf(MSG_DEBUG,
504 "EAP-TEAP: Failed to get cipher information");
505 eap_teap_state(data, FAILURE);
506 return -1;
507 }
508 data->anon_provisioning = os_strstr(cipher, "ADH") != NULL;
509
510 if (data->anon_provisioning)
511 wpa_printf(MSG_DEBUG, "EAP-TEAP: Anonymous provisioning");
512
513 if (eap_teap_derive_key_auth(sm, data) < 0) {
514 eap_teap_state(data, FAILURE);
515 return -1;
516 }
517
518 eap_teap_state(data, PHASE2_START);
519
520 return 0;
521}
522
523
524static struct wpabuf * eap_teap_build_phase2_req(struct eap_sm *sm,
525 struct eap_teap_data *data,
526 u8 id)
527{
528 struct wpabuf *req;
529
530 if (sm->eap_teap_auth == 1) {
531 wpa_printf(MSG_DEBUG, "EAP-TEAP: Initiate Basic-Password-Auth");
532 req = wpabuf_alloc(sizeof(struct teap_tlv_hdr));
533 if (!req)
534 return NULL;
535 eap_teap_put_tlv_hdr(req, TEAP_TLV_BASIC_PASSWORD_AUTH_REQ, 0);
536 return req;
537 }
538
539 wpa_printf(MSG_DEBUG, "EAP-TEAP: Initiate inner EAP method");
540 if (!data->phase2_priv) {
541 wpa_printf(MSG_DEBUG,
542 "EAP-TEAP: Phase 2 method not initialized");
543 return NULL;
544 }
545
546 req = data->phase2_method->buildReq(sm, data->phase2_priv, id);
547 if (!req)
548 return NULL;
549
550 wpa_hexdump_buf_key(MSG_MSGDUMP, "EAP-TEAP: Phase 2 EAP-Request", req);
551 return eap_teap_tlv_eap_payload(req);
552}
553
554
555static struct wpabuf * eap_teap_build_crypto_binding(
556 struct eap_sm *sm, struct eap_teap_data *data)
557{
558 struct wpabuf *buf;
559 struct teap_tlv_result *result;
560 struct teap_tlv_crypto_binding *cb;
561 u8 subtype, flags;
562
563 buf = wpabuf_alloc(2 * sizeof(*result) + sizeof(*cb));
564 if (!buf)
565 return NULL;
566
567 if (data->send_new_pac || data->anon_provisioning ||
568 data->phase2_method)
569 data->final_result = 0;
570 else
571 data->final_result = 1;
572
573 if (!data->final_result || data->eap_seq > 0) {
574 /* Intermediate-Result */
575 wpa_printf(MSG_DEBUG,
576 "EAP-TEAP: Add Intermediate-Result TLV (status=SUCCESS)");
577 result = wpabuf_put(buf, sizeof(*result));
578 result->tlv_type = host_to_be16(TEAP_TLV_MANDATORY |
579 TEAP_TLV_INTERMEDIATE_RESULT);
580 result->length = host_to_be16(2);
581 result->status = host_to_be16(TEAP_STATUS_SUCCESS);
582 }
583
584 if (data->final_result) {
585 /* Result TLV */
586 wpa_printf(MSG_DEBUG,
587 "EAP-TEAP: Add Result TLV (status=SUCCESS)");
588 result = wpabuf_put(buf, sizeof(*result));
589 result->tlv_type = host_to_be16(TEAP_TLV_MANDATORY |
590 TEAP_TLV_RESULT);
591 result->length = host_to_be16(2);
592 result->status = host_to_be16(TEAP_STATUS_SUCCESS);
593 }
594
595 /* Crypto-Binding TLV */
596 cb = wpabuf_put(buf, sizeof(*cb));
597 cb->tlv_type = host_to_be16(TEAP_TLV_MANDATORY |
598 TEAP_TLV_CRYPTO_BINDING);
599 cb->length = host_to_be16(sizeof(*cb) - sizeof(struct teap_tlv_hdr));
600 cb->version = EAP_TEAP_VERSION;
601 cb->received_version = data->peer_version;
602 /* FIX: RFC 7170 is not clear on which Flags value to use when
603 * Crypto-Binding TLV is used with Basic-Password-Auth */
604 flags = data->cmk_emsk_available ?
605 TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC :
606 TEAP_CRYPTO_BINDING_MSK_CMAC;
607 subtype = TEAP_CRYPTO_BINDING_SUBTYPE_REQUEST;
608 cb->subtype = (flags << 4) | subtype;
609 if (random_get_bytes(cb->nonce, sizeof(cb->nonce)) < 0) {
610 wpabuf_free(buf);
611 return NULL;
612 }
613
614 /*
615 * RFC 7170, Section 4.2.13:
616 * The nonce in a request MUST have its least significant bit set to 0.
617 */
618 cb->nonce[sizeof(cb->nonce) - 1] &= ~0x01;
619
620 os_memcpy(data->crypto_binding_nonce, cb->nonce, sizeof(cb->nonce));
621
622 if (eap_teap_compound_mac(data->tls_cs, cb, data->server_outer_tlvs,
623 data->peer_outer_tlvs, data->cmk_msk,
624 cb->msk_compound_mac) < 0) {
625 wpabuf_free(buf);
626 return NULL;
627 }
628
629 if (data->cmk_emsk_available &&
630 eap_teap_compound_mac(data->tls_cs, cb, data->server_outer_tlvs,
631 data->peer_outer_tlvs, data->cmk_emsk,
632 cb->emsk_compound_mac) < 0) {
633 wpabuf_free(buf);
634 return NULL;
635 }
636
637 wpa_printf(MSG_DEBUG,
638 "EAP-TEAP: Add Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
639 cb->version, cb->received_version, flags, subtype);
640 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Nonce",
641 cb->nonce, sizeof(cb->nonce));
642 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: EMSK Compound MAC",
643 cb->emsk_compound_mac, sizeof(cb->emsk_compound_mac));
644 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: MSK Compound MAC",
645 cb->msk_compound_mac, sizeof(cb->msk_compound_mac));
646
647 return buf;
648}
649
650
651static struct wpabuf * eap_teap_build_pac(struct eap_sm *sm,
652 struct eap_teap_data *data)
653{
654 u8 pac_key[EAP_TEAP_PAC_KEY_LEN];
655 u8 *pac_buf, *pac_opaque;
656 struct wpabuf *buf;
657 u8 *pos;
658 size_t buf_len, srv_id_info_len, pac_len;
659 struct teap_tlv_hdr *pac_tlv;
660 struct pac_attr_hdr *pac_info;
661 struct teap_tlv_result *result;
662 struct os_time now;
663
664 wpa_printf(MSG_DEBUG, "EAP-TEAP: Build a new PAC");
665
666 if (random_get_bytes(pac_key, EAP_TEAP_PAC_KEY_LEN) < 0 ||
667 os_get_time(&now) < 0)
668 return NULL;
669 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Generated PAC-Key",
670 pac_key, EAP_TEAP_PAC_KEY_LEN);
671
672 pac_len = (2 + EAP_TEAP_PAC_KEY_LEN) + (2 + 4) +
673 (2 + sm->identity_len) + 8;
674 pac_buf = os_malloc(pac_len);
675 if (!pac_buf)
676 return NULL;
677
678 srv_id_info_len = os_strlen(data->srv_id_info);
679
680 pos = pac_buf;
681 *pos++ = PAC_OPAQUE_TYPE_KEY;
682 *pos++ = EAP_TEAP_PAC_KEY_LEN;
683 os_memcpy(pos, pac_key, EAP_TEAP_PAC_KEY_LEN);
684 pos += EAP_TEAP_PAC_KEY_LEN;
685
686 wpa_printf(MSG_DEBUG, "EAP-TEAP: PAC-Key lifetime: %u seconds",
687 data->pac_key_lifetime);
688 *pos++ = PAC_OPAQUE_TYPE_LIFETIME;
689 *pos++ = 4;
690 WPA_PUT_BE32(pos, now.sec + data->pac_key_lifetime);
691 pos += 4;
692
693 if (sm->identity) {
694 wpa_hexdump_ascii(MSG_DEBUG, "EAP-TEAP: PAC-Opaque Identity",
695 sm->identity, sm->identity_len);
696 *pos++ = PAC_OPAQUE_TYPE_IDENTITY;
697 *pos++ = sm->identity_len;
698 os_memcpy(pos, sm->identity, sm->identity_len);
699 pos += sm->identity_len;
700 }
701
702 pac_len = pos - pac_buf;
703 while (pac_len % 8) {
704 *pos++ = PAC_OPAQUE_TYPE_PAD;
705 pac_len++;
706 }
707
708 pac_opaque = os_malloc(pac_len + 8);
709 if (!pac_opaque) {
710 os_free(pac_buf);
711 return NULL;
712 }
713 if (aes_wrap(data->pac_opaque_encr, sizeof(data->pac_opaque_encr),
714 pac_len / 8, pac_buf, pac_opaque) < 0) {
715 os_free(pac_buf);
716 os_free(pac_opaque);
717 return NULL;
718 }
719 os_free(pac_buf);
720
721 pac_len += 8;
722 wpa_hexdump(MSG_DEBUG, "EAP-TEAP: PAC-Opaque", pac_opaque, pac_len);
723
724 buf_len = sizeof(*pac_tlv) +
725 sizeof(struct pac_attr_hdr) + EAP_TEAP_PAC_KEY_LEN +
726 sizeof(struct pac_attr_hdr) + pac_len +
727 data->srv_id_len + srv_id_info_len + 100 + sizeof(*result);
728 buf = wpabuf_alloc(buf_len);
729 if (!buf) {
730 os_free(pac_opaque);
731 return NULL;
732 }
733
734 /* Result TLV */
735 wpa_printf(MSG_DEBUG, "EAP-TEAP: Add Result TLV (status=SUCCESS)");
736 result = wpabuf_put(buf, sizeof(*result));
737 WPA_PUT_BE16((u8 *) &result->tlv_type,
738 TEAP_TLV_MANDATORY | TEAP_TLV_RESULT);
739 WPA_PUT_BE16((u8 *) &result->length, 2);
740 WPA_PUT_BE16((u8 *) &result->status, TEAP_STATUS_SUCCESS);
741
742 /* PAC TLV */
743 wpa_printf(MSG_DEBUG, "EAP-TEAP: Add PAC TLV");
744 pac_tlv = wpabuf_put(buf, sizeof(*pac_tlv));
745 pac_tlv->tlv_type = host_to_be16(TEAP_TLV_MANDATORY | TEAP_TLV_PAC);
746
747 /* PAC-Key */
748 eap_teap_put_tlv(buf, PAC_TYPE_PAC_KEY, pac_key, EAP_TEAP_PAC_KEY_LEN);
749
750 /* PAC-Opaque */
751 eap_teap_put_tlv(buf, PAC_TYPE_PAC_OPAQUE, pac_opaque, pac_len);
752 os_free(pac_opaque);
753
754 /* PAC-Info */
755 pac_info = wpabuf_put(buf, sizeof(*pac_info));
756 pac_info->type = host_to_be16(PAC_TYPE_PAC_INFO);
757
758 /* PAC-Lifetime (inside PAC-Info) */
759 eap_teap_put_tlv_hdr(buf, PAC_TYPE_CRED_LIFETIME, 4);
760 wpabuf_put_be32(buf, now.sec + data->pac_key_lifetime);
761
762 /* A-ID (inside PAC-Info) */
763 eap_teap_put_tlv(buf, PAC_TYPE_A_ID, data->srv_id, data->srv_id_len);
764
765 /* Note: headers may be misaligned after A-ID */
766
767 if (sm->identity) {
768 eap_teap_put_tlv(buf, PAC_TYPE_I_ID, sm->identity,
769 sm->identity_len);
770 }
771
772 /* A-ID-Info (inside PAC-Info) */
773 eap_teap_put_tlv(buf, PAC_TYPE_A_ID_INFO, data->srv_id_info,
774 srv_id_info_len);
775
776 /* PAC-Type (inside PAC-Info) */
777 eap_teap_put_tlv_hdr(buf, PAC_TYPE_PAC_TYPE, 2);
778 wpabuf_put_be16(buf, PAC_TYPE_TUNNEL_PAC);
779
780 /* Update PAC-Info and PAC TLV Length fields */
781 pos = wpabuf_put(buf, 0);
782 pac_info->len = host_to_be16(pos - (u8 *) (pac_info + 1));
783 pac_tlv->length = host_to_be16(pos - (u8 *) (pac_tlv + 1));
784
785 return buf;
786}
787
788
789static int eap_teap_encrypt_phase2(struct eap_sm *sm,
790 struct eap_teap_data *data,
791 struct wpabuf *plain, int piggyback)
792{
793 struct wpabuf *encr;
794
795 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TEAP: Encrypting Phase 2 TLVs",
796 plain);
797 encr = eap_server_tls_encrypt(sm, &data->ssl, plain);
798 wpabuf_free(plain);
799
800 if (!encr)
801 return -1;
802
803 if (data->ssl.tls_out && piggyback) {
804 wpa_printf(MSG_DEBUG,
805 "EAP-TEAP: Piggyback Phase 2 data (len=%d) with last Phase 1 Message (len=%d used=%d)",
806 (int) wpabuf_len(encr),
807 (int) wpabuf_len(data->ssl.tls_out),
808 (int) data->ssl.tls_out_pos);
809 if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(encr)) < 0) {
810 wpa_printf(MSG_WARNING,
811 "EAP-TEAP: Failed to resize output buffer");
812 wpabuf_free(encr);
813 return -1;
814 }
815 wpabuf_put_buf(data->ssl.tls_out, encr);
816 wpabuf_free(encr);
817 } else {
818 wpabuf_free(data->ssl.tls_out);
819 data->ssl.tls_out_pos = 0;
820 data->ssl.tls_out = encr;
821 }
822
823 return 0;
824}
825
826
827static struct wpabuf * eap_teap_buildReq(struct eap_sm *sm, void *priv, u8 id)
828{
829 struct eap_teap_data *data = priv;
830 struct wpabuf *req = NULL;
831 int piggyback = 0;
832
833 if (data->ssl.state == FRAG_ACK) {
834 return eap_server_tls_build_ack(id, EAP_TYPE_TEAP,
835 data->teap_version);
836 }
837
838 if (data->ssl.state == WAIT_FRAG_ACK) {
839 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TEAP,
840 data->teap_version, id);
841 }
842
843 switch (data->state) {
844 case START:
845 return eap_teap_build_start(sm, data, id);
846 case PHASE1B:
847 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
848 if (eap_teap_phase1_done(sm, data) < 0)
849 return NULL;
850 if (data->state == PHASE2_START) {
851 int res;
852
853 /*
854 * Try to generate Phase 2 data to piggyback
855 * with the end of Phase 1 to avoid extra
856 * roundtrip.
857 */
858 wpa_printf(MSG_DEBUG,
859 "EAP-TEAP: Try to start Phase 2");
860 res = eap_teap_process_phase2_start(sm, data);
861 if (res == 1) {
862 req = eap_teap_build_crypto_binding(
863 sm, data);
864 piggyback = 1;
865 break;
866 }
867
868 if (res)
869 break;
870 req = eap_teap_build_phase2_req(sm, data, id);
871 piggyback = 1;
872 }
873 }
874 break;
875 case PHASE2_ID:
876 case PHASE2_BASIC_AUTH:
877 case PHASE2_METHOD:
878 req = eap_teap_build_phase2_req(sm, data, id);
879 break;
880 case CRYPTO_BINDING:
881 req = eap_teap_build_crypto_binding(sm, data);
882 if (data->phase2_method) {
883 /*
884 * Include the start of the next EAP method in the
885 * sequence in the same message with Crypto-Binding to
886 * save a round-trip.
887 */
888 struct wpabuf *eap;
889
890 eap = eap_teap_build_phase2_req(sm, data, id);
891 req = wpabuf_concat(req, eap);
892 eap_teap_state(data, PHASE2_METHOD);
893 }
894 break;
895 case REQUEST_PAC:
896 req = eap_teap_build_pac(sm, data);
897 break;
898 case FAILURE_SEND_RESULT:
899 req = eap_teap_tlv_result(TEAP_STATUS_FAILURE, 0);
900 if (data->error_code)
901 req = wpabuf_concat(
902 req, eap_teap_tlv_error(data->error_code));
903 break;
904 default:
905 wpa_printf(MSG_DEBUG, "EAP-TEAP: %s - unexpected state %d",
906 __func__, data->state);
907 return NULL;
908 }
909
910 if (req && eap_teap_encrypt_phase2(sm, data, req, piggyback) < 0)
911 return NULL;
912
913 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TEAP,
914 data->teap_version, id);
915}
916
917
918static Boolean eap_teap_check(struct eap_sm *sm, void *priv,
919 struct wpabuf *respData)
920{
921 const u8 *pos;
922 size_t len;
923
924 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TEAP, respData, &len);
925 if (!pos || len < 1) {
926 wpa_printf(MSG_INFO, "EAP-TEAP: Invalid frame");
927 return TRUE;
928 }
929
930 return FALSE;
931}
932
933
934static int eap_teap_phase2_init(struct eap_sm *sm, struct eap_teap_data *data,
935 EapType eap_type)
936{
937 if (data->phase2_priv && data->phase2_method) {
938 data->phase2_method->reset(sm, data->phase2_priv);
939 data->phase2_method = NULL;
940 data->phase2_priv = NULL;
941 }
942 data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF,
943 eap_type);
944 if (!data->phase2_method)
945 return -1;
946
947 sm->init_phase2 = 1;
948 data->phase2_priv = data->phase2_method->init(sm);
949 sm->init_phase2 = 0;
950
951 return data->phase2_priv ? 0 : -1;
952}
953
954
955static void eap_teap_process_phase2_response(struct eap_sm *sm,
956 struct eap_teap_data *data,
957 u8 *in_data, size_t in_len)
958{
959 u8 next_type = EAP_TYPE_NONE;
960 struct eap_hdr *hdr;
961 u8 *pos;
962 size_t left;
963 struct wpabuf buf;
964 const struct eap_method *m = data->phase2_method;
965 void *priv = data->phase2_priv;
966
967 if (!priv) {
968 wpa_printf(MSG_DEBUG,
969 "EAP-TEAP: %s - Phase 2 not initialized?!",
970 __func__);
971 return;
972 }
973
974 hdr = (struct eap_hdr *) in_data;
975 pos = (u8 *) (hdr + 1);
976
977 if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {
978 left = in_len - sizeof(*hdr);
979 wpa_hexdump(MSG_DEBUG,
980 "EAP-TEAP: Phase 2 type Nak'ed; allowed types",
981 pos + 1, left - 1);
982#ifdef EAP_SERVER_TNC
983 if (m && m->vendor == EAP_VENDOR_IETF &&
984 m->method == EAP_TYPE_TNC) {
985 wpa_printf(MSG_DEBUG,
986 "EAP-TEAP: Peer Nak'ed required TNC negotiation");
987 next_type = eap_teap_req_failure(data, 0);
988 eap_teap_phase2_init(sm, data, next_type);
989 return;
990 }
991#endif /* EAP_SERVER_TNC */
992 eap_sm_process_nak(sm, pos + 1, left - 1);
993 if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
994 sm->user->methods[sm->user_eap_method_index].method !=
995 EAP_TYPE_NONE) {
996 next_type = sm->user->methods[
997 sm->user_eap_method_index++].method;
998 wpa_printf(MSG_DEBUG, "EAP-TEAP: try EAP type %d",
999 next_type);
1000 } else {
1001 next_type = eap_teap_req_failure(data, 0);
1002 }
1003 eap_teap_phase2_init(sm, data, next_type);
1004 return;
1005 }
1006
1007 wpabuf_set(&buf, in_data, in_len);
1008
1009 if (m->check(sm, priv, &buf)) {
1010 wpa_printf(MSG_DEBUG,
1011 "EAP-TEAP: Phase 2 check() asked to ignore the packet");
1012 eap_teap_req_failure(data, TEAP_ERROR_INNER_METHOD);
1013 return;
1014 }
1015
1016 m->process(sm, priv, &buf);
1017
1018 if (!m->isDone(sm, priv))
1019 return;
1020
1021 if (!m->isSuccess(sm, priv)) {
1022 wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 2 method failed");
1023 next_type = eap_teap_req_failure(data, TEAP_ERROR_INNER_METHOD);
1024 eap_teap_phase2_init(sm, data, next_type);
1025 return;
1026 }
1027
1028 switch (data->state) {
1029 case PHASE2_ID:
1030 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
1031 wpa_hexdump_ascii(MSG_DEBUG,
1032 "EAP-TEAP: Phase 2 Identity not found in the user database",
1033 sm->identity, sm->identity_len);
1034 next_type = eap_teap_req_failure(
1035 data, TEAP_ERROR_INNER_METHOD);
1036 break;
1037 }
1038
1039 eap_teap_state(data, PHASE2_METHOD);
1040 if (data->anon_provisioning) {
1041 /* TODO: Allow any inner EAP method that provides
1042 * mutual authentication and EMSK derivation (i.e.,
1043 * EAP-pwd or EAP-EKE). */
1044 next_type = EAP_TYPE_PWD;
1045 sm->user_eap_method_index = 0;
1046 } else {
1047 next_type = sm->user->methods[0].method;
1048 sm->user_eap_method_index = 1;
1049 }
1050 wpa_printf(MSG_DEBUG, "EAP-TEAP: Try EAP type %d", next_type);
1051 break;
1052 case PHASE2_METHOD:
1053 case CRYPTO_BINDING:
1054 eap_teap_update_icmk(sm, data);
1055 eap_teap_state(data, CRYPTO_BINDING);
1056 data->eap_seq++;
1057 next_type = EAP_TYPE_NONE;
1058#ifdef EAP_SERVER_TNC
1059 if (sm->tnc && !data->tnc_started) {
1060 wpa_printf(MSG_DEBUG, "EAP-TEAP: Initialize TNC");
1061 next_type = EAP_TYPE_TNC;
1062 data->tnc_started = 1;
1063 }
1064#endif /* EAP_SERVER_TNC */
1065 break;
1066 case FAILURE:
1067 break;
1068 default:
1069 wpa_printf(MSG_DEBUG, "EAP-TEAP: %s - unexpected state %d",
1070 __func__, data->state);
1071 break;
1072 }
1073
1074 eap_teap_phase2_init(sm, data, next_type);
1075}
1076
1077
1078static void eap_teap_process_phase2_eap(struct eap_sm *sm,
1079 struct eap_teap_data *data,
1080 u8 *in_data, size_t in_len)
1081{
1082 struct eap_hdr *hdr;
1083 size_t len;
1084
1085 hdr = (struct eap_hdr *) in_data;
1086 if (in_len < (int) sizeof(*hdr)) {
1087 wpa_printf(MSG_INFO,
1088 "EAP-TEAP: Too short Phase 2 EAP frame (len=%lu)",
1089 (unsigned long) in_len);
1090 eap_teap_req_failure(data, TEAP_ERROR_INNER_METHOD);
1091 return;
1092 }
1093 len = be_to_host16(hdr->length);
1094 if (len > in_len) {
1095 wpa_printf(MSG_INFO,
1096 "EAP-TEAP: Length mismatch in Phase 2 EAP frame (len=%lu hdr->length=%lu)",
1097 (unsigned long) in_len, (unsigned long) len);
1098 eap_teap_req_failure(data, TEAP_ERROR_INNER_METHOD);
1099 return;
1100 }
1101 wpa_printf(MSG_DEBUG,
1102 "EAP-TEAP: Received Phase 2: code=%d identifier=%d length=%lu",
1103 hdr->code, hdr->identifier,
1104 (unsigned long) len);
1105 switch (hdr->code) {
1106 case EAP_CODE_RESPONSE:
1107 eap_teap_process_phase2_response(sm, data, (u8 *) hdr, len);
1108 break;
1109 default:
1110 wpa_printf(MSG_INFO,
1111 "EAP-TEAP: Unexpected code=%d in Phase 2 EAP header",
1112 hdr->code);
1113 break;
1114 }
1115}
1116
1117
1118static void eap_teap_process_basic_auth_resp(struct eap_sm *sm,
1119 struct eap_teap_data *data,
1120 u8 *in_data, size_t in_len)
1121{
1122 u8 *pos, *end, *username, *password, *new_id;
1123 u8 userlen, passlen;
1124
1125 pos = in_data;
1126 end = pos + in_len;
1127
1128 if (end - pos < 1) {
1129 wpa_printf(MSG_DEBUG,
1130 "EAP-TEAP: No room for Basic-Password-Auth-Resp Userlen field");
1131 eap_teap_req_failure(data, 0);
1132 return;
1133 }
1134 userlen = *pos++;
1135 if (end - pos < userlen) {
1136 wpa_printf(MSG_DEBUG,
1137 "EAP-TEAP: Truncated Basic-Password-Auth-Resp Username field");
1138 eap_teap_req_failure(data, 0);
1139 return;
1140 }
1141 username = pos;
1142 pos += userlen;
1143 wpa_hexdump_ascii(MSG_DEBUG,
1144 "EAP-TEAP: Basic-Password-Auth-Resp Username",
1145 username, userlen);
1146
1147 if (end - pos < 1) {
1148 wpa_printf(MSG_DEBUG,
1149 "EAP-TEAP: No room for Basic-Password-Auth-Resp Passlen field");
1150 eap_teap_req_failure(data, 0);
1151 return;
1152 }
1153 passlen = *pos++;
1154 if (end - pos < passlen) {
1155 wpa_printf(MSG_DEBUG,
1156 "EAP-TEAP: Truncated Basic-Password-Auth-Resp Password field");
1157 eap_teap_req_failure(data, 0);
1158 return;
1159 }
1160 password = pos;
1161 pos += passlen;
1162 wpa_hexdump_ascii_key(MSG_DEBUG,
1163 "EAP-TEAP: Basic-Password-Auth-Resp Password",
1164 password, passlen);
1165
1166 if (end > pos) {
1167 wpa_printf(MSG_DEBUG,
1168 "EAP-TEAP: Unexpected %d extra octet(s) at the end of Basic-Password-Auth-Resp TLV",
1169 (int) (end - pos));
1170 eap_teap_req_failure(data, 0);
1171 return;
1172 }
1173
1174 if (eap_user_get(sm, username, userlen, 1) != 0) {
1175 wpa_printf(MSG_DEBUG,
1176 "EAP-TEAP: Username not found in the user database");
1177 eap_teap_req_failure(data, 0);
1178 return;
1179 }
1180
1181 if (!sm->user || !sm->user->password || sm->user->password_hash) {
1182 wpa_printf(MSG_DEBUG,
1183 "EAP-TEAP: No plaintext user password configured");
1184 eap_teap_req_failure(data, 0);
1185 return;
1186 }
1187
1188 if (sm->user->password_len != passlen ||
1189 os_memcmp_const(sm->user->password, password, passlen) != 0) {
1190 wpa_printf(MSG_DEBUG, "EAP-TEAP: Invalid password");
1191 eap_teap_req_failure(data, 0);
1192 return;
1193 }
1194
1195 wpa_printf(MSG_DEBUG, "EAP-TEAP: Correct password");
1196 new_id = os_memdup(username, userlen);
1197 if (new_id) {
1198 os_free(sm->identity);
1199 sm->identity = new_id;
1200 sm->identity_len = userlen;
1201 }
1202 eap_teap_state(data, CRYPTO_BINDING);
1203 eap_teap_update_icmk(sm, data);
1204}
1205
1206
1207static int eap_teap_parse_tlvs(struct wpabuf *data,
1208 struct eap_teap_tlv_parse *tlv)
1209{
1210 u16 tlv_type;
1211 int mandatory, res;
1212 size_t len;
1213 u8 *pos, *end;
1214
1215 os_memset(tlv, 0, sizeof(*tlv));
1216
1217 pos = wpabuf_mhead(data);
1218 end = pos + wpabuf_len(data);
1219 while (end - pos > 4) {
1220 mandatory = pos[0] & 0x80;
1221 tlv_type = WPA_GET_BE16(pos) & 0x3fff;
1222 pos += 2;
1223 len = WPA_GET_BE16(pos);
1224 pos += 2;
1225 if (len > (size_t) (end - pos)) {
1226 wpa_printf(MSG_INFO, "EAP-TEAP: TLV overflow");
1227 return -1;
1228 }
1229 wpa_printf(MSG_DEBUG,
1230 "EAP-TEAP: Received Phase 2: TLV type %u (%s) length %u%s",
1231 tlv_type, eap_teap_tlv_type_str(tlv_type),
1232 (unsigned int) len,
1233 mandatory ? " (mandatory)" : "");
1234
1235 res = eap_teap_parse_tlv(tlv, tlv_type, pos, len);
1236 if (res == -2)
1237 break;
1238 if (res < 0) {
1239 if (mandatory) {
1240 wpa_printf(MSG_DEBUG,
1241 "EAP-TEAP: NAK unknown mandatory TLV type %u",
1242 tlv_type);
1243 /* TODO: generate NAK TLV */
1244 break;
1245 }
1246
1247 wpa_printf(MSG_DEBUG,
1248 "EAP-TEAP: Ignore unknown optional TLV type %u",
1249 tlv_type);
1250 }
1251
1252 pos += len;
1253 }
1254
1255 return 0;
1256}
1257
1258
1259static int eap_teap_validate_crypto_binding(
1260 struct eap_teap_data *data, const struct teap_tlv_crypto_binding *cb,
1261 size_t bind_len)
1262{
1263 u8 flags, subtype;
1264
1265 subtype = cb->subtype & 0x0f;
1266 flags = cb->subtype >> 4;
1267
1268 wpa_printf(MSG_DEBUG,
1269 "EAP-TEAP: Reply Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
1270 cb->version, cb->received_version, flags, subtype);
1271 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Nonce",
1272 cb->nonce, sizeof(cb->nonce));
1273 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: EMSK Compound MAC",
1274 cb->emsk_compound_mac, sizeof(cb->emsk_compound_mac));
1275 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: MSK Compound MAC",
1276 cb->msk_compound_mac, sizeof(cb->msk_compound_mac));
1277
1278 if (cb->version != EAP_TEAP_VERSION ||
1279 cb->received_version != data->peer_version) {
1280 wpa_printf(MSG_DEBUG,
1281 "EAP-TEAP: Unexpected version in Crypto-Binding: Version %u Received Version %u",
1282 cb->version, cb->received_version);
1283 return -1;
1284 }
1285
1286 if (flags < 1 || flags > 3) {
1287 wpa_printf(MSG_DEBUG,
1288 "EAP-TEAP: Unexpected Flags in Crypto-Binding: %u",
1289 flags);
1290 return -1;
1291 }
1292
1293 if (subtype != TEAP_CRYPTO_BINDING_SUBTYPE_RESPONSE) {
1294 wpa_printf(MSG_DEBUG,
1295 "EAP-TEAP: Unexpected Sub-Type in Crypto-Binding: %u",
1296 subtype);
1297 return -1;
1298 }
1299
1300 if (os_memcmp_const(data->crypto_binding_nonce, cb->nonce,
1301 EAP_TEAP_NONCE_LEN - 1) != 0 ||
1302 (data->crypto_binding_nonce[EAP_TEAP_NONCE_LEN - 1] | 1) !=
1303 cb->nonce[EAP_TEAP_NONCE_LEN - 1]) {
1304 wpa_printf(MSG_DEBUG,
1305 "EAP-TEAP: Invalid Nonce in Crypto-Binding");
1306 return -1;
1307 }
1308
1309 if (flags == TEAP_CRYPTO_BINDING_MSK_CMAC ||
1310 flags == TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC) {
1311 u8 msk_compound_mac[EAP_TEAP_COMPOUND_MAC_LEN];
1312
1313 if (eap_teap_compound_mac(data->tls_cs, cb,
1314 data->server_outer_tlvs,
1315 data->peer_outer_tlvs, data->cmk_msk,
1316 msk_compound_mac) < 0)
1317 return -1;
1318 if (os_memcmp_const(msk_compound_mac, cb->msk_compound_mac,
1319 EAP_TEAP_COMPOUND_MAC_LEN) != 0) {
1320 wpa_hexdump(MSG_DEBUG,
1321 "EAP-TEAP: Calculated MSK Compound MAC",
1322 msk_compound_mac,
1323 EAP_TEAP_COMPOUND_MAC_LEN);
1324 wpa_printf(MSG_INFO,
1325 "EAP-TEAP: MSK Compound MAC did not match");
1326 return -1;
1327 }
1328 }
1329
1330 if ((flags == TEAP_CRYPTO_BINDING_EMSK_CMAC ||
1331 flags == TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC) &&
1332 data->cmk_emsk_available) {
1333 u8 emsk_compound_mac[EAP_TEAP_COMPOUND_MAC_LEN];
1334
1335 if (eap_teap_compound_mac(data->tls_cs, cb,
1336 data->server_outer_tlvs,
1337 data->peer_outer_tlvs, data->cmk_emsk,
1338 emsk_compound_mac) < 0)
1339 return -1;
1340 if (os_memcmp_const(emsk_compound_mac, cb->emsk_compound_mac,
1341 EAP_TEAP_COMPOUND_MAC_LEN) != 0) {
1342 wpa_hexdump(MSG_DEBUG,
1343 "EAP-TEAP: Calculated EMSK Compound MAC",
1344 emsk_compound_mac,
1345 EAP_TEAP_COMPOUND_MAC_LEN);
1346 wpa_printf(MSG_INFO,
1347 "EAP-TEAP: EMSK Compound MAC did not match");
1348 return -1;
1349 }
1350 }
1351
1352 if (flags == TEAP_CRYPTO_BINDING_EMSK_CMAC &&
1353 !data->cmk_emsk_available) {
1354 wpa_printf(MSG_INFO,
1355 "EAP-TEAP: Peer included only EMSK Compound MAC, but no locally generated inner EAP EMSK to validate this");
1356 return -1;
1357 }
1358
1359 return 0;
1360}
1361
1362
1363static int eap_teap_pac_type(u8 *pac, size_t len, u16 type)
1364{
1365 struct teap_attr_pac_type *tlv;
1366
1367 if (!pac || len != sizeof(*tlv))
1368 return 0;
1369
1370 tlv = (struct teap_attr_pac_type *) pac;
1371
1372 return be_to_host16(tlv->type) == PAC_TYPE_PAC_TYPE &&
1373 be_to_host16(tlv->length) == 2 &&
1374 be_to_host16(tlv->pac_type) == type;
1375}
1376
1377
1378static void eap_teap_process_phase2_tlvs(struct eap_sm *sm,
1379 struct eap_teap_data *data,
1380 struct wpabuf *in_data)
1381{
1382 struct eap_teap_tlv_parse tlv;
1383 int check_crypto_binding = data->state == CRYPTO_BINDING;
1384
1385 if (eap_teap_parse_tlvs(in_data, &tlv) < 0) {
1386 wpa_printf(MSG_DEBUG,
1387 "EAP-TEAP: Failed to parse received Phase 2 TLVs");
1388 return;
1389 }
1390
1391 if (tlv.result == TEAP_STATUS_FAILURE) {
1392 wpa_printf(MSG_DEBUG, "EAP-TEAP: Result TLV indicated failure");
1393 eap_teap_state(data, FAILURE);
1394 return;
1395 }
1396
1397 if (tlv.nak) {
1398 wpa_printf(MSG_DEBUG,
1399 "EAP-TEAP: Peer NAK'ed Vendor-Id %u NAK-Type %u",
1400 WPA_GET_BE32(tlv.nak), WPA_GET_BE16(tlv.nak + 4));
1401 eap_teap_state(data, FAILURE_SEND_RESULT);
1402 return;
1403 }
1404
1405 if (data->state == REQUEST_PAC) {
1406 u16 type, len, res;
1407
1408 if (!tlv.pac || tlv.pac_len < 6) {
1409 wpa_printf(MSG_DEBUG,
1410 "EAP-TEAP: No PAC Acknowledgement received");
1411 eap_teap_state(data, FAILURE);
1412 return;
1413 }
1414
1415 type = WPA_GET_BE16(tlv.pac);
1416 len = WPA_GET_BE16(tlv.pac + 2);
1417 res = WPA_GET_BE16(tlv.pac + 4);
1418
1419 if (type != PAC_TYPE_PAC_ACKNOWLEDGEMENT || len != 2 ||
1420 res != TEAP_STATUS_SUCCESS) {
1421 wpa_printf(MSG_DEBUG,
1422 "EAP-TEAP: PAC TLV did not contain acknowledgement");
1423 eap_teap_state(data, FAILURE);
1424 return;
1425 }
1426
1427 wpa_printf(MSG_DEBUG,
1428 "EAP-TEAP: PAC-Acknowledgement received - PAC provisioning succeeded");
1429 eap_teap_state(data, SUCCESS);
1430 return;
1431 }
1432
1433 if (check_crypto_binding) {
1434 if (!tlv.crypto_binding) {
1435 wpa_printf(MSG_DEBUG,
1436 "EAP-TEAP: No Crypto-Binding TLV received");
1437 eap_teap_state(data, FAILURE);
1438 return;
1439 }
1440
1441 if (data->final_result &&
1442 tlv.result != TEAP_STATUS_SUCCESS) {
1443 wpa_printf(MSG_DEBUG,
1444 "EAP-TEAP: Crypto-Binding TLV without Success Result");
1445 eap_teap_state(data, FAILURE);
1446 return;
1447 }
1448
234489ef 1449 if (sm->eap_teap_auth != 1 &&
0ed57c5e
JM
1450 tlv.iresult != TEAP_STATUS_SUCCESS) {
1451 wpa_printf(MSG_DEBUG,
1452 "EAP-TEAP: Crypto-Binding TLV without intermediate Success Result");
1453 eap_teap_state(data, FAILURE);
1454 return;
1455 }
1456
1457 if (eap_teap_validate_crypto_binding(data, tlv.crypto_binding,
1458 tlv.crypto_binding_len)) {
1459 eap_teap_state(data, FAILURE);
1460 return;
1461 }
1462
1463 wpa_printf(MSG_DEBUG,
1464 "EAP-TEAP: Valid Crypto-Binding TLV received");
1465 if (data->final_result) {
1466 wpa_printf(MSG_DEBUG,
1467 "EAP-TEAP: Authentication completed successfully");
1468 }
1469
1470 if (data->anon_provisioning &&
1471 sm->eap_fast_prov != ANON_PROV &&
1472 sm->eap_fast_prov != BOTH_PROV) {
1473 wpa_printf(MSG_DEBUG,
1474 "EAP-TEAP: Client is trying to use unauthenticated provisioning which is disabled");
1475 eap_teap_state(data, FAILURE);
1476 return;
1477 }
1478
1479 if (sm->eap_fast_prov != AUTH_PROV &&
1480 sm->eap_fast_prov != BOTH_PROV &&
1481 tlv.request_action == TEAP_REQUEST_ACTION_PROCESS_TLV &&
1482 eap_teap_pac_type(tlv.pac, tlv.pac_len,
1483 PAC_TYPE_TUNNEL_PAC)) {
1484 wpa_printf(MSG_DEBUG,
1485 "EAP-TEAP: Client is trying to use authenticated provisioning which is disabled");
1486 eap_teap_state(data, FAILURE);
1487 return;
1488 }
1489
1490 if (data->anon_provisioning ||
1491 (tlv.request_action == TEAP_REQUEST_ACTION_PROCESS_TLV &&
1492 eap_teap_pac_type(tlv.pac, tlv.pac_len,
1493 PAC_TYPE_TUNNEL_PAC))) {
1494 wpa_printf(MSG_DEBUG,
1495 "EAP-TEAP: Requested a new Tunnel PAC");
1496 eap_teap_state(data, REQUEST_PAC);
1497 } else if (data->send_new_pac) {
1498 wpa_printf(MSG_DEBUG,
1499 "EAP-TEAP: Server triggered re-keying of Tunnel PAC");
1500 eap_teap_state(data, REQUEST_PAC);
1501 } else if (data->final_result)
1502 eap_teap_state(data, SUCCESS);
1503 }
1504
1505 if (tlv.basic_auth_resp) {
1506 if (sm->eap_teap_auth != 1) {
1507 wpa_printf(MSG_DEBUG,
1508 "EAP-TEAP: Unexpected Basic-Password-Auth-Resp when trying to use inner EAP");
1509 eap_teap_state(data, FAILURE);
1510 return;
1511 }
1512 eap_teap_process_basic_auth_resp(sm, data, tlv.basic_auth_resp,
1513 tlv.basic_auth_resp_len);
1514 }
1515
1516 if (tlv.eap_payload_tlv) {
1517 if (sm->eap_teap_auth == 1) {
1518 wpa_printf(MSG_DEBUG,
1519 "EAP-TEAP: Unexpected EAP Payload TLV when trying to use Basic-Password-Auth");
1520 eap_teap_state(data, FAILURE);
1521 return;
1522 }
1523 eap_teap_process_phase2_eap(sm, data, tlv.eap_payload_tlv,
1524 tlv.eap_payload_tlv_len);
1525 }
1526}
1527
1528
1529static void eap_teap_process_phase2(struct eap_sm *sm,
1530 struct eap_teap_data *data,
1531 struct wpabuf *in_buf)
1532{
1533 struct wpabuf *in_decrypted;
1534
1535 wpa_printf(MSG_DEBUG,
1536 "EAP-TEAP: Received %lu bytes encrypted data for Phase 2",
1537 (unsigned long) wpabuf_len(in_buf));
1538
1539 if (data->pending_phase2_resp) {
1540 wpa_printf(MSG_DEBUG,
1541 "EAP-TEAP: Pending Phase 2 response - skip decryption and use old data");
1542 eap_teap_process_phase2_tlvs(sm, data,
1543 data->pending_phase2_resp);
1544 wpabuf_free(data->pending_phase2_resp);
1545 data->pending_phase2_resp = NULL;
1546 return;
1547 }
1548
1549 in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
1550 in_buf);
1551 if (!in_decrypted) {
1552 wpa_printf(MSG_INFO,
1553 "EAP-TEAP: Failed to decrypt Phase 2 data");
1554 eap_teap_state(data, FAILURE);
1555 return;
1556 }
1557
1558 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TEAP: Decrypted Phase 2 TLVs",
1559 in_decrypted);
1560
1561 eap_teap_process_phase2_tlvs(sm, data, in_decrypted);
1562
1563 if (sm->method_pending == METHOD_PENDING_WAIT) {
1564 wpa_printf(MSG_DEBUG,
1565 "EAP-TEAP: Phase 2 method is in pending wait state - save decrypted response");
1566 wpabuf_free(data->pending_phase2_resp);
1567 data->pending_phase2_resp = in_decrypted;
1568 return;
1569 }
1570
1571 wpabuf_free(in_decrypted);
1572}
1573
1574
1575static int eap_teap_process_version(struct eap_sm *sm, void *priv,
1576 int peer_version)
1577{
1578 struct eap_teap_data *data = priv;
1579
1580 if (peer_version < 1) {
1581 /* Version 1 was the first defined version, so reject 0 */
1582 wpa_printf(MSG_INFO,
1583 "EAP-TEAP: Peer used unknown TEAP version %u",
1584 peer_version);
1585 return -1;
1586 }
1587
1588 if (peer_version < data->teap_version) {
1589 wpa_printf(MSG_DEBUG, "EAP-TEAP: peer ver=%u, own ver=%u; "
1590 "use version %u",
1591 peer_version, data->teap_version, peer_version);
1592 data->teap_version = peer_version;
1593 }
1594
1595 data->peer_version = peer_version;
1596
1597 return 0;
1598}
1599
1600
1601static int eap_teap_process_phase1(struct eap_sm *sm,
1602 struct eap_teap_data *data)
1603{
1604 if (eap_server_tls_phase1(sm, &data->ssl) < 0) {
1605 wpa_printf(MSG_INFO, "EAP-TEAP: TLS processing failed");
1606 eap_teap_state(data, FAILURE);
1607 return -1;
1608 }
1609
1610 if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) ||
1611 wpabuf_len(data->ssl.tls_out) > 0)
1612 return 1;
1613
1614 /*
1615 * Phase 1 was completed with the received message (e.g., when using
1616 * abbreviated handshake), so Phase 2 can be started immediately
1617 * without having to send through an empty message to the peer.
1618 */
1619
1620 return eap_teap_phase1_done(sm, data);
1621}
1622
1623
1624static int eap_teap_process_phase2_start(struct eap_sm *sm,
1625 struct eap_teap_data *data)
1626{
1627 u8 next_type;
1628
1629 if (data->identity) {
1630 /* Used PAC and identity is from PAC-Opaque */
1631 os_free(sm->identity);
1632 sm->identity = data->identity;
1633 data->identity = NULL;
1634 sm->identity_len = data->identity_len;
1635 data->identity_len = 0;
1636 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
1637 wpa_hexdump_ascii(MSG_DEBUG,
1638 "EAP-TEAP: Phase 2 Identity not found in the user database",
1639 sm->identity, sm->identity_len);
1640 next_type = EAP_TYPE_NONE;
1641 eap_teap_state(data, PHASE2_METHOD);
1642 } else if (sm->eap_teap_pac_no_inner) {
1643 wpa_printf(MSG_DEBUG,
1644 "EAP-TEAP: Used PAC and identity already known - skip inner auth");
1645 /* FIX: Need to derive CMK here. However, how is that
1646 * supposed to be done? RFC 7170 does not tell that for
1647 * the no-inner-auth case. */
a66e53c4
JM
1648 eap_teap_derive_cmk_basic_pw_auth(data->tls_cs,
1649 data->simck_msk,
0ed57c5e
JM
1650 data->cmk_msk);
1651 eap_teap_state(data, CRYPTO_BINDING);
1652 return 1;
1653 } else if (sm->eap_teap_auth == 1) {
1654 eap_teap_state(data, PHASE2_BASIC_AUTH);
1655 return 1;
1656 } else {
1657 wpa_printf(MSG_DEBUG,
1658 "EAP-TEAP: Identity already known - skip Phase 2 Identity Request");
1659 next_type = sm->user->methods[0].method;
1660 sm->user_eap_method_index = 1;
1661 eap_teap_state(data, PHASE2_METHOD);
1662 }
1663
1664 } else if (sm->eap_teap_auth == 1) {
1665 eap_teap_state(data, PHASE2_BASIC_AUTH);
1666 return 0;
1667 } else {
1668 eap_teap_state(data, PHASE2_ID);
1669 next_type = EAP_TYPE_IDENTITY;
1670 }
1671
1672 return eap_teap_phase2_init(sm, data, next_type);
1673}
1674
1675
1676static void eap_teap_process_msg(struct eap_sm *sm, void *priv,
1677 const struct wpabuf *respData)
1678{
1679 struct eap_teap_data *data = priv;
1680
1681 switch (data->state) {
1682 case PHASE1:
1683 case PHASE1B:
1684 if (eap_teap_process_phase1(sm, data))
1685 break;
1686
1687 /* fall through */
1688 case PHASE2_START:
1689 eap_teap_process_phase2_start(sm, data);
1690 break;
1691 case PHASE2_ID:
1692 case PHASE2_BASIC_AUTH:
1693 case PHASE2_METHOD:
1694 case CRYPTO_BINDING:
1695 case REQUEST_PAC:
1696 eap_teap_process_phase2(sm, data, data->ssl.tls_in);
1697 break;
1698 case FAILURE_SEND_RESULT:
1699 /* Protected failure result indication completed. Ignore the
1700 * received message (which is supposed to include Result TLV
1701 * indicating failure) and terminate exchange with cleartext
1702 * EAP-Failure. */
1703 eap_teap_state(data, FAILURE);
1704 break;
1705 default:
1706 wpa_printf(MSG_DEBUG, "EAP-TEAP: Unexpected state %d in %s",
1707 data->state, __func__);
1708 break;
1709 }
1710}
1711
1712
1713static void eap_teap_process(struct eap_sm *sm, void *priv,
1714 struct wpabuf *respData)
1715{
1716 struct eap_teap_data *data = priv;
1717 const u8 *pos;
1718 size_t len;
1719 struct wpabuf *resp = respData;
1720 u8 flags;
1721
1722 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TEAP, respData, &len);
1723 if (!pos || len < 1)
1724 return;
1725
1726 flags = *pos++;
1727 len--;
1728
1729 if (flags & EAP_TEAP_FLAGS_OUTER_TLV_LEN) {
1730 /* Extract Outer TLVs from the message before common TLS
1731 * processing */
1732 u32 message_len = 0, outer_tlv_len;
1733 const u8 *hdr;
1734
1735 if (data->state != PHASE1) {
1736 wpa_printf(MSG_INFO,
1737 "EAP-TEAP: Unexpected Outer TLVs in a message that is not the first message from the peer");
1738 return;
1739 }
1740
1741 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
1742 if (len < 4) {
1743 wpa_printf(MSG_INFO,
1744 "EAP-TEAP: Too short message to include Message Length field");
1745 return;
1746 }
1747
1748 message_len = WPA_GET_BE32(pos);
1749 pos += 4;
1750 len -= 4;
1751 if (message_len < 4) {
1752 wpa_printf(MSG_INFO,
1753 "EAP-TEAP: Message Length field has too msall value to include Outer TLV Length field");
1754 return;
1755 }
1756 }
1757
1758 if (len < 4) {
1759 wpa_printf(MSG_INFO,
1760 "EAP-TEAP: Too short message to include Outer TLVs Length field");
1761 return;
1762 }
1763
1764 outer_tlv_len = WPA_GET_BE32(pos);
1765 pos += 4;
1766 len -= 4;
1767
1768 wpa_printf(MSG_DEBUG,
1769 "EAP-TEAP: Message Length %u Outer TLV Length %u",
1770 message_len, outer_tlv_len);
1771 if (len < outer_tlv_len) {
1772 wpa_printf(MSG_INFO,
1773 "EAP-TEAP: Too short message to include Outer TLVs field");
1774 return;
1775 }
1776
1777 if (message_len &&
1778 (message_len < outer_tlv_len ||
1779 message_len < 4 + outer_tlv_len)) {
1780 wpa_printf(MSG_INFO,
1781 "EAP-TEAP: Message Length field has too small value to include Outer TLVs");
1782 return;
1783 }
1784
1785 if (wpabuf_len(respData) < 4 + outer_tlv_len ||
1786 len < outer_tlv_len)
1787 return;
1788 resp = wpabuf_alloc(wpabuf_len(respData) - 4 - outer_tlv_len);
1789 if (!resp)
1790 return;
1791 hdr = wpabuf_head(respData);
1792 wpabuf_put_u8(resp, *hdr++); /* Code */
1793 wpabuf_put_u8(resp, *hdr++); /* Identifier */
1794 wpabuf_put_be16(resp, WPA_GET_BE16(hdr) - 4 - outer_tlv_len);
1795 hdr += 2;
1796 wpabuf_put_u8(resp, *hdr++); /* Type */
1797 /* Flags | Ver */
1798 wpabuf_put_u8(resp, flags & ~EAP_TEAP_FLAGS_OUTER_TLV_LEN);
1799
1800 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
1801 wpabuf_put_be32(resp, message_len - 4 - outer_tlv_len);
1802
1803 wpabuf_put_data(resp, pos, len - outer_tlv_len);
1804 pos += len - outer_tlv_len;
1805 wpabuf_free(data->peer_outer_tlvs);
1806 data->peer_outer_tlvs = wpabuf_alloc_copy(pos, outer_tlv_len);
1807 if (!data->peer_outer_tlvs)
1808 return;
1809 wpa_hexdump_buf(MSG_DEBUG, "EAP-TEAP: Outer TLVs",
1810 data->peer_outer_tlvs);
1811
1812 wpa_hexdump_buf(MSG_DEBUG,
1813 "EAP-TEAP: TLS Data message after Outer TLV removal",
1814 resp);
1815 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TEAP, resp,
1816 &len);
1817 if (!pos || len < 1) {
1818 wpa_printf(MSG_INFO,
1819 "EAP-TEAP: Invalid frame after Outer TLV removal");
1820 return;
1821 }
1822 }
1823
1824 if (data->state == PHASE1)
1825 eap_teap_state(data, PHASE1B);
1826
1827 if (eap_server_tls_process(sm, &data->ssl, resp, data,
1828 EAP_TYPE_TEAP, eap_teap_process_version,
1829 eap_teap_process_msg) < 0)
1830 eap_teap_state(data, FAILURE);
1831
1832 if (resp != respData)
1833 wpabuf_free(resp);
1834}
1835
1836
1837static Boolean eap_teap_isDone(struct eap_sm *sm, void *priv)
1838{
1839 struct eap_teap_data *data = priv;
1840
1841 return data->state == SUCCESS || data->state == FAILURE;
1842}
1843
1844
1845static u8 * eap_teap_getKey(struct eap_sm *sm, void *priv, size_t *len)
1846{
1847 struct eap_teap_data *data = priv;
1848 u8 *eapKeyData;
1849
1850 if (data->state != SUCCESS)
1851 return NULL;
1852
1853 eapKeyData = os_malloc(EAP_TEAP_KEY_LEN);
1854 if (!eapKeyData)
1855 return NULL;
1856
1857 /* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
1858 * is used in this derivation */
a66e53c4
JM
1859 if (eap_teap_derive_eap_msk(data->tls_cs, data->simck_msk,
1860 eapKeyData) < 0) {
0ed57c5e
JM
1861 os_free(eapKeyData);
1862 return NULL;
1863 }
1864 *len = EAP_TEAP_KEY_LEN;
1865
1866 return eapKeyData;
1867}
1868
1869
1870static u8 * eap_teap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1871{
1872 struct eap_teap_data *data = priv;
1873 u8 *eapKeyData;
1874
1875 if (data->state != SUCCESS)
1876 return NULL;
1877
1878 eapKeyData = os_malloc(EAP_EMSK_LEN);
1879 if (!eapKeyData)
1880 return NULL;
1881
1882 /* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
1883 * is used in this derivation */
a66e53c4
JM
1884 if (eap_teap_derive_eap_emsk(data->tls_cs, data->simck_msk,
1885 eapKeyData) < 0) {
0ed57c5e
JM
1886 os_free(eapKeyData);
1887 return NULL;
1888 }
1889 *len = EAP_EMSK_LEN;
1890
1891 return eapKeyData;
1892}
1893
1894
1895static Boolean eap_teap_isSuccess(struct eap_sm *sm, void *priv)
1896{
1897 struct eap_teap_data *data = priv;
1898
1899 return data->state == SUCCESS;
1900}
1901
1902
1903static u8 * eap_teap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
1904{
1905 struct eap_teap_data *data = priv;
1906 const size_t max_id_len = 100;
1907 int res;
1908 u8 *id;
1909
1910 if (data->state != SUCCESS)
1911 return NULL;
1912
1913 id = os_malloc(max_id_len);
1914 if (!id)
1915 return NULL;
1916
1917 id[0] = EAP_TYPE_TEAP;
1918 res = tls_get_tls_unique(data->ssl.conn, id + 1, max_id_len - 1);
1919 if (res < 0) {
1920 os_free(id);
1921 wpa_printf(MSG_ERROR, "EAP-TEAP: Failed to derive Session-Id");
1922 return NULL;
1923 }
1924
1925 *len = 1 + res;
1926 wpa_hexdump(MSG_DEBUG, "EAP-TEAP: Derived Session-Id", id, *len);
1927 return id;
1928}
1929
1930
1931int eap_server_teap_register(void)
1932{
1933 struct eap_method *eap;
1934
1935 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1936 EAP_VENDOR_IETF, EAP_TYPE_TEAP, "TEAP");
1937 if (!eap)
1938 return -1;
1939
1940 eap->init = eap_teap_init;
1941 eap->reset = eap_teap_reset;
1942 eap->buildReq = eap_teap_buildReq;
1943 eap->check = eap_teap_check;
1944 eap->process = eap_teap_process;
1945 eap->isDone = eap_teap_isDone;
1946 eap->getKey = eap_teap_getKey;
1947 eap->get_emsk = eap_teap_get_emsk;
1948 eap->isSuccess = eap_teap_isSuccess;
1949 eap->getSessionId = eap_teap_get_session_id;
1950
1951 return eap_server_method_register(eap);
1952}