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