1 /*
2 * EAP-TLS/PEAP/TTLS/FAST server common functions
3 * Copyright (c) 2004-2009, 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/tls.h"
14 #include "eap_i.h"
15 #include "eap_tls_common.h"
16
17
18 static void eap_server_tls_free_in_buf(struct eap_ssl_data *data);
19
20
eap_tls_msg_alloc(enum eap_type type,size_t payload_len,u8 code,u8 identifier)21 struct wpabuf * eap_tls_msg_alloc(enum eap_type type, size_t payload_len,
22 u8 code, u8 identifier)
23 {
24 if (type == EAP_UNAUTH_TLS_TYPE)
25 return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS,
26 EAP_VENDOR_TYPE_UNAUTH_TLS, payload_len,
27 code, identifier);
28 else if (type == EAP_WFA_UNAUTH_TLS_TYPE)
29 return eap_msg_alloc(EAP_VENDOR_WFA_NEW,
30 EAP_VENDOR_WFA_UNAUTH_TLS, payload_len,
31 code, identifier);
32 return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code,
33 identifier);
34 }
35
36
37 #ifdef CONFIG_TLS_INTERNAL
eap_server_tls_log_cb(void * ctx,const char * msg)38 static void eap_server_tls_log_cb(void *ctx, const char *msg)
39 {
40 struct eap_sm *sm = ctx;
41 eap_log_msg(sm, "TLS: %s", msg);
42 }
43 #endif /* CONFIG_TLS_INTERNAL */
44
45
eap_server_tls_ssl_init(struct eap_sm * sm,struct eap_ssl_data * data,int verify_peer,int eap_type)46 int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
47 int verify_peer, int eap_type)
48 {
49 u8 session_ctx[8];
50 unsigned int flags = sm->cfg->tls_flags;
51
52 if (!sm->cfg->ssl_ctx) {
53 wpa_printf(MSG_ERROR, "TLS context not initialized - cannot use TLS-based EAP method");
54 return -1;
55 }
56
57 data->eap = sm;
58 data->phase2 = sm->init_phase2;
59
60 data->conn = tls_connection_init(sm->cfg->ssl_ctx);
61 if (data->conn == NULL) {
62 wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
63 "connection");
64 return -1;
65 }
66
67 #ifdef CONFIG_TLS_INTERNAL
68 tls_connection_set_log_cb(data->conn, eap_server_tls_log_cb, sm);
69 #ifdef CONFIG_TESTING_OPTIONS
70 tls_connection_set_test_flags(data->conn, sm->tls_test_flags);
71 #endif /* CONFIG_TESTING_OPTIONS */
72 #endif /* CONFIG_TLS_INTERNAL */
73
74 if (eap_type != EAP_TYPE_FAST)
75 flags |= TLS_CONN_DISABLE_SESSION_TICKET;
76 os_memcpy(session_ctx, "hostapd", 7);
77 session_ctx[7] = (u8) eap_type;
78 if (tls_connection_set_verify(sm->cfg->ssl_ctx, data->conn, verify_peer,
79 flags, session_ctx,
80 sizeof(session_ctx))) {
81 wpa_printf(MSG_INFO, "SSL: Failed to configure verification "
82 "of TLS peer certificate");
83 tls_connection_deinit(sm->cfg->ssl_ctx, data->conn);
84 data->conn = NULL;
85 return -1;
86 }
87
88 data->tls_out_limit = sm->cfg->fragment_size > 0 ?
89 sm->cfg->fragment_size : 1398;
90 if (data->phase2) {
91 /* Limit the fragment size in the inner TLS authentication
92 * since the outer authentication with EAP-PEAP does not yet
93 * support fragmentation */
94 if (data->tls_out_limit > 100)
95 data->tls_out_limit -= 100;
96 }
97
98 #ifdef CONFIG_TESTING_OPTIONS
99 data->skip_prot_success = sm->cfg->skip_prot_success;
100 #endif /* CONFIG_TESTING_OPTIONS */
101
102 return 0;
103 }
104
105
eap_server_tls_ssl_deinit(struct eap_sm * sm,struct eap_ssl_data * data)106 void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
107 {
108 tls_connection_deinit(sm->cfg->ssl_ctx, data->conn);
109 eap_server_tls_free_in_buf(data);
110 wpabuf_free(data->tls_out);
111 data->tls_out = NULL;
112 }
113
114
eap_server_tls_derive_key(struct eap_sm * sm,struct eap_ssl_data * data,const char * label,const u8 * context,size_t context_len,size_t len)115 u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
116 const char *label, const u8 *context,
117 size_t context_len, size_t len)
118 {
119 u8 *out;
120
121 out = os_malloc(len);
122 if (out == NULL)
123 return NULL;
124
125 if (tls_connection_export_key(sm->cfg->ssl_ctx, data->conn, label,
126 context, context_len, out, len)) {
127 os_free(out);
128 return NULL;
129 }
130
131 return out;
132 }
133
134
135 /**
136 * eap_server_tls_derive_session_id - Derive a Session-Id based on TLS data
137 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
138 * @data: Data for TLS processing
139 * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
140 * @len: Pointer to length of the session ID generated
141 * Returns: Pointer to allocated Session-Id on success or %NULL on failure
142 *
143 * This function derive the Session-Id based on the TLS session data
144 * (client/server random and method type).
145 *
146 * The caller is responsible for freeing the returned buffer.
147 */
eap_server_tls_derive_session_id(struct eap_sm * sm,struct eap_ssl_data * data,u8 eap_type,size_t * len)148 u8 * eap_server_tls_derive_session_id(struct eap_sm *sm,
149 struct eap_ssl_data *data, u8 eap_type,
150 size_t *len)
151 {
152 struct tls_random keys;
153 u8 *out;
154
155 if (data->tls_v13) {
156 u8 *id, *method_id;
157 const u8 context[] = { eap_type };
158
159 /* Session-Id = <EAP-Type> || Method-Id
160 * Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id",
161 * Type-Code, 64)
162 */
163 *len = 1 + 64;
164 id = os_malloc(*len);
165 if (!id)
166 return NULL;
167 method_id = eap_server_tls_derive_key(
168 sm, data, "EXPORTER_EAP_TLS_Method-Id", context, 1, 64);
169 if (!method_id) {
170 os_free(id);
171 return NULL;
172 }
173 id[0] = eap_type;
174 os_memcpy(id + 1, method_id, 64);
175 os_free(method_id);
176 return id;
177 }
178
179 if (tls_connection_get_random(sm->cfg->ssl_ctx, data->conn, &keys))
180 return NULL;
181
182 if (keys.client_random == NULL || keys.server_random == NULL)
183 return NULL;
184
185 *len = 1 + keys.client_random_len + keys.server_random_len;
186 out = os_malloc(*len);
187 if (out == NULL)
188 return NULL;
189
190 /* Session-Id = EAP type || client.random || server.random */
191 out[0] = eap_type;
192 os_memcpy(out + 1, keys.client_random, keys.client_random_len);
193 os_memcpy(out + 1 + keys.client_random_len, keys.server_random,
194 keys.server_random_len);
195
196 return out;
197 }
198
199
eap_server_tls_build_msg(struct eap_ssl_data * data,int eap_type,int version,u8 id)200 struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data,
201 int eap_type, int version, u8 id)
202 {
203 struct wpabuf *req;
204 u8 flags;
205 size_t send_len, plen;
206
207 wpa_printf(MSG_DEBUG, "SSL: Generating Request");
208 if (data->tls_out == NULL) {
209 wpa_printf(MSG_ERROR, "SSL: tls_out NULL in %s", __func__);
210 return NULL;
211 }
212
213 flags = version;
214 send_len = wpabuf_len(data->tls_out) - data->tls_out_pos;
215 if (1 + send_len > data->tls_out_limit) {
216 send_len = data->tls_out_limit - 1;
217 flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
218 if (data->tls_out_pos == 0) {
219 flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
220 send_len -= 4;
221 }
222 }
223
224 plen = 1 + send_len;
225 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
226 plen += 4;
227
228 req = eap_tls_msg_alloc(eap_type, plen, EAP_CODE_REQUEST, id);
229 if (req == NULL)
230 return NULL;
231
232 wpabuf_put_u8(req, flags); /* Flags */
233 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
234 wpabuf_put_be32(req, wpabuf_len(data->tls_out));
235
236 wpabuf_put_data(req, wpabuf_head_u8(data->tls_out) + data->tls_out_pos,
237 send_len);
238 data->tls_out_pos += send_len;
239
240 if (data->tls_out_pos == wpabuf_len(data->tls_out)) {
241 wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
242 "(message sent completely)",
243 (unsigned long) send_len);
244 wpabuf_free(data->tls_out);
245 data->tls_out = NULL;
246 data->tls_out_pos = 0;
247 data->state = MSG;
248 } else {
249 wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
250 "(%lu more to send)", (unsigned long) send_len,
251 (unsigned long) wpabuf_len(data->tls_out) -
252 data->tls_out_pos);
253 data->state = WAIT_FRAG_ACK;
254 }
255
256 return req;
257 }
258
259
eap_server_tls_build_ack(u8 id,int eap_type,int version)260 struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version)
261 {
262 struct wpabuf *req;
263
264 req = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_REQUEST, id);
265 if (req == NULL)
266 return NULL;
267 wpa_printf(MSG_DEBUG, "SSL: Building ACK");
268 wpabuf_put_u8(req, version); /* Flags */
269 return req;
270 }
271
272
eap_server_tls_process_cont(struct eap_ssl_data * data,const u8 * buf,size_t len)273 static int eap_server_tls_process_cont(struct eap_ssl_data *data,
274 const u8 *buf, size_t len)
275 {
276 /* Process continuation of a pending message */
277 if (len > wpabuf_tailroom(data->tls_in)) {
278 wpa_printf(MSG_DEBUG, "SSL: Fragment overflow");
279 return -1;
280 }
281
282 wpabuf_put_data(data->tls_in, buf, len);
283 wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu "
284 "bytes more", (unsigned long) len,
285 (unsigned long) wpabuf_tailroom(data->tls_in));
286
287 return 0;
288 }
289
290
eap_server_tls_process_fragment(struct eap_ssl_data * data,u8 flags,u32 message_length,const u8 * buf,size_t len)291 static int eap_server_tls_process_fragment(struct eap_ssl_data *data,
292 u8 flags, u32 message_length,
293 const u8 *buf, size_t len)
294 {
295 /* Process a fragment that is not the last one of the message */
296 if (data->tls_in == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) {
297 wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a "
298 "fragmented packet");
299 return -1;
300 }
301
302 if (data->tls_in == NULL) {
303 /* First fragment of the message */
304
305 /* Limit length to avoid rogue peers from causing large
306 * memory allocations. */
307 if (message_length > 65536) {
308 wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size"
309 " over 64 kB)");
310 return -1;
311 }
312
313 if (len > message_length) {
314 wpa_printf(MSG_INFO, "SSL: Too much data (%d bytes) in "
315 "first fragment of frame (TLS Message "
316 "Length %d bytes)",
317 (int) len, (int) message_length);
318 return -1;
319 }
320
321 data->tls_in = wpabuf_alloc(message_length);
322 if (data->tls_in == NULL) {
323 wpa_printf(MSG_DEBUG, "SSL: No memory for message");
324 return -1;
325 }
326 wpabuf_put_data(data->tls_in, buf, len);
327 wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first "
328 "fragment, waiting for %lu bytes more",
329 (unsigned long) len,
330 (unsigned long) wpabuf_tailroom(data->tls_in));
331 }
332
333 return 0;
334 }
335
336
eap_server_tls_phase1(struct eap_sm * sm,struct eap_ssl_data * data)337 int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
338 {
339 char buf[20];
340
341 if (data->tls_out) {
342 /* This should not happen.. */
343 wpa_printf(MSG_INFO, "SSL: pending tls_out data when "
344 "processing new message");
345 wpabuf_free(data->tls_out);
346 WPA_ASSERT(data->tls_out == NULL);
347 }
348
349 data->tls_out = tls_connection_server_handshake(sm->cfg->ssl_ctx,
350 data->conn,
351 data->tls_in, NULL);
352 if (data->tls_out == NULL) {
353 wpa_printf(MSG_INFO, "SSL: TLS processing failed");
354 return -1;
355 }
356 if (tls_connection_get_failed(sm->cfg->ssl_ctx, data->conn)) {
357 /* TLS processing has failed - return error */
358 wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
359 "report error");
360 return -1;
361 }
362
363 if (tls_get_version(sm->cfg->ssl_ctx, data->conn,
364 buf, sizeof(buf)) == 0) {
365 wpa_printf(MSG_DEBUG, "SSL: Using TLS version %s", buf);
366 data->tls_v13 = os_strcmp(buf, "TLSv1.3") == 0;
367 }
368
369 if (!sm->serial_num &&
370 tls_connection_established(sm->cfg->ssl_ctx, data->conn))
371 sm->serial_num = tls_connection_peer_serial_num(
372 sm->cfg->ssl_ctx, data->conn);
373
374 /*
375 * RFC 9190 Section 2.5
376 *
377 * We need to signal the other end that TLS negotiation is done. We
378 * can't send a zero-length application data message, so we send
379 * application data which is one byte of zero.
380 *
381 * Note this is only done for when there is no application data to be
382 * sent. So this is done always for EAP-TLS but notably not for PEAP
383 * even on resumption.
384 */
385 if (data->tls_v13 &&
386 tls_connection_established(sm->cfg->ssl_ctx, data->conn)) {
387 struct wpabuf *plain, *encr;
388
389 switch (sm->currentMethod) {
390 case EAP_TYPE_PEAP:
391 break;
392 default:
393 if (!tls_connection_resumed(sm->cfg->ssl_ctx,
394 data->conn))
395 break;
396 /* fallthrough */
397 case EAP_TYPE_TLS:
398 #ifdef CONFIG_TESTING_OPTIONS
399 if (data->skip_prot_success) {
400 wpa_printf(MSG_INFO,
401 "TESTING: Do not send protected success indication");
402 break;
403 }
404 #endif /* CONFIG_TESTING_OPTIONS */
405 wpa_printf(MSG_DEBUG,
406 "EAP-TLS: Send protected success indication (appl data 0x00)");
407
408 plain = wpabuf_alloc(1);
409 if (!plain)
410 return -1;
411 wpabuf_put_u8(plain, 0);
412 encr = eap_server_tls_encrypt(sm, data, plain);
413 wpabuf_free(plain);
414 if (!encr)
415 return -1;
416 if (wpabuf_resize(&data->tls_out, wpabuf_len(encr)) < 0)
417 {
418 wpa_printf(MSG_INFO,
419 "EAP-TLS: Failed to resize output buffer");
420 wpabuf_free(encr);
421 return -1;
422 }
423 wpabuf_put_buf(data->tls_out, encr);
424 wpa_hexdump_buf(MSG_DEBUG,
425 "EAP-TLS: Data appended to the message",
426 encr);
427 wpabuf_free(encr);
428 }
429 }
430
431 return 0;
432 }
433
434
eap_server_tls_reassemble(struct eap_ssl_data * data,u8 flags,const u8 ** pos,size_t * left)435 static int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
436 const u8 **pos, size_t *left)
437 {
438 unsigned int tls_msg_len = 0;
439 const u8 *end = *pos + *left;
440
441 wpa_hexdump(MSG_MSGDUMP, "SSL: Received data", *pos, *left);
442
443 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
444 if (*left < 4) {
445 wpa_printf(MSG_INFO, "SSL: Short frame with TLS "
446 "length");
447 return -1;
448 }
449 tls_msg_len = WPA_GET_BE32(*pos);
450 wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d",
451 tls_msg_len);
452 *pos += 4;
453 *left -= 4;
454
455 if (*left > tls_msg_len) {
456 wpa_printf(MSG_INFO, "SSL: TLS Message Length (%d "
457 "bytes) smaller than this fragment (%d "
458 "bytes)", (int) tls_msg_len, (int) *left);
459 return -1;
460 }
461 }
462
463 wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x "
464 "Message Length %u", flags, tls_msg_len);
465
466 if (data->state == WAIT_FRAG_ACK) {
467 if (*left != 0) {
468 wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in "
469 "WAIT_FRAG_ACK state");
470 return -1;
471 }
472 wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged");
473 return 1;
474 }
475
476 if (data->tls_in &&
477 eap_server_tls_process_cont(data, *pos, end - *pos) < 0)
478 return -1;
479
480 if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) {
481 if (eap_server_tls_process_fragment(data, flags, tls_msg_len,
482 *pos, end - *pos) < 0)
483 return -1;
484
485 data->state = FRAG_ACK;
486 return 1;
487 }
488
489 if (data->state == FRAG_ACK) {
490 wpa_printf(MSG_DEBUG, "SSL: All fragments received");
491 data->state = MSG;
492 }
493
494 if (data->tls_in == NULL) {
495 /* Wrap unfragmented messages as wpabuf without extra copy */
496 wpabuf_set(&data->tmpbuf, *pos, end - *pos);
497 data->tls_in = &data->tmpbuf;
498 }
499
500 return 0;
501 }
502
503
eap_server_tls_free_in_buf(struct eap_ssl_data * data)504 static void eap_server_tls_free_in_buf(struct eap_ssl_data *data)
505 {
506 if (data->tls_in != &data->tmpbuf)
507 wpabuf_free(data->tls_in);
508 data->tls_in = NULL;
509 }
510
511
eap_server_tls_encrypt(struct eap_sm * sm,struct eap_ssl_data * data,const struct wpabuf * plain)512 struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
513 struct eap_ssl_data *data,
514 const struct wpabuf *plain)
515 {
516 struct wpabuf *buf;
517
518 buf = tls_connection_encrypt(sm->cfg->ssl_ctx, data->conn, plain);
519 if (buf == NULL) {
520 wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data");
521 return NULL;
522 }
523
524 return buf;
525 }
526
527
eap_server_tls_process(struct eap_sm * sm,struct eap_ssl_data * data,struct wpabuf * respData,void * priv,int eap_type,int (* proc_version)(struct eap_sm * sm,void * priv,int peer_version),void (* proc_msg)(struct eap_sm * sm,void * priv,const struct wpabuf * respData))528 int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
529 struct wpabuf *respData, void *priv, int eap_type,
530 int (*proc_version)(struct eap_sm *sm, void *priv,
531 int peer_version),
532 void (*proc_msg)(struct eap_sm *sm, void *priv,
533 const struct wpabuf *respData))
534 {
535 const u8 *pos;
536 u8 flags;
537 size_t left;
538 int ret, res = 0;
539
540 if (eap_type == EAP_UNAUTH_TLS_TYPE)
541 pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
542 EAP_VENDOR_TYPE_UNAUTH_TLS, respData,
543 &left);
544 else if (eap_type == EAP_WFA_UNAUTH_TLS_TYPE)
545 pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW,
546 EAP_VENDOR_WFA_UNAUTH_TLS, respData,
547 &left);
548 else
549 pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData,
550 &left);
551 if (pos == NULL || left < 1)
552 return 0; /* Should not happen - frame already validated */
553 flags = *pos++;
554 left--;
555 wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x",
556 (unsigned long) wpabuf_len(respData), flags);
557
558 if (proc_version &&
559 proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0)
560 return -1;
561
562 ret = eap_server_tls_reassemble(data, flags, &pos, &left);
563 if (ret < 0) {
564 res = -1;
565 goto done;
566 } else if (ret == 1)
567 return 0;
568
569 if (proc_msg)
570 proc_msg(sm, priv, respData);
571
572 if (tls_connection_get_write_alerts(sm->cfg->ssl_ctx, data->conn) > 1) {
573 wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in "
574 "TLS processing");
575 res = -1;
576 }
577
578 done:
579 eap_server_tls_free_in_buf(data);
580
581 return res;
582 }
583