2 * EAP-TLS/PEAP/TTLS/FAST server common functions
3 * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
12 #include "crypto/sha1.h"
13 #include "crypto/tls.h"
15 #include "eap_tls_common.h"
18 static void eap_server_tls_free_in_buf(struct eap_ssl_data
*data
);
21 struct wpabuf
* eap_tls_msg_alloc(EapType type
, size_t payload_len
,
22 u8 code
, u8 identifier
)
24 if (type
== EAP_UNAUTH_TLS_TYPE
)
25 return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS
,
26 EAP_VENDOR_TYPE_UNAUTH_TLS
, payload_len
,
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
,
32 return eap_msg_alloc(EAP_VENDOR_IETF
, type
, payload_len
, code
,
37 #ifdef CONFIG_TLS_INTERNAL
38 static void eap_server_tls_log_cb(void *ctx
, const char *msg
)
40 struct eap_sm
*sm
= ctx
;
41 eap_log_msg(sm
, "TLS: %s", msg
);
43 #endif /* CONFIG_TLS_INTERNAL */
46 int eap_server_tls_ssl_init(struct eap_sm
*sm
, struct eap_ssl_data
*data
,
47 int verify_peer
, int eap_type
)
50 unsigned int flags
= sm
->tls_flags
;
52 if (sm
->ssl_ctx
== NULL
) {
53 wpa_printf(MSG_ERROR
, "TLS context not initialized - cannot use TLS-based EAP method");
58 data
->phase2
= sm
->init_phase2
;
60 data
->conn
= tls_connection_init(sm
->ssl_ctx
);
61 if (data
->conn
== NULL
) {
62 wpa_printf(MSG_INFO
, "SSL: Failed to initialize new TLS "
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 */
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
->ssl_ctx
, data
->conn
, verify_peer
,
80 sizeof(session_ctx
))) {
81 wpa_printf(MSG_INFO
, "SSL: Failed to configure verification "
82 "of TLS peer certificate");
83 tls_connection_deinit(sm
->ssl_ctx
, data
->conn
);
88 data
->tls_out_limit
= sm
->fragment_size
> 0 ? sm
->fragment_size
: 1398;
90 /* Limit the fragment size in the inner TLS authentication
91 * since the outer authentication with EAP-PEAP does not yet
92 * support fragmentation */
93 if (data
->tls_out_limit
> 100)
94 data
->tls_out_limit
-= 100;
100 void eap_server_tls_ssl_deinit(struct eap_sm
*sm
, struct eap_ssl_data
*data
)
102 tls_connection_deinit(sm
->ssl_ctx
, data
->conn
);
103 eap_server_tls_free_in_buf(data
);
104 wpabuf_free(data
->tls_out
);
105 data
->tls_out
= NULL
;
109 u8
* eap_server_tls_derive_key(struct eap_sm
*sm
, struct eap_ssl_data
*data
,
110 const char *label
, const u8
*context
,
111 size_t context_len
, size_t len
)
115 out
= os_malloc(len
);
119 if (tls_connection_export_key(sm
->ssl_ctx
, data
->conn
, label
,
120 context
, context_len
, out
, len
)) {
130 * eap_server_tls_derive_session_id - Derive a Session-Id based on TLS data
131 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
132 * @data: Data for TLS processing
133 * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
134 * @len: Pointer to length of the session ID generated
135 * Returns: Pointer to allocated Session-Id on success or %NULL on failure
137 * This function derive the Session-Id based on the TLS session data
138 * (client/server random and method type).
140 * The caller is responsible for freeing the returned buffer.
142 u8
* eap_server_tls_derive_session_id(struct eap_sm
*sm
,
143 struct eap_ssl_data
*data
, u8 eap_type
,
146 struct tls_random keys
;
149 if (eap_type
== EAP_TYPE_TLS
&& data
->tls_v13
) {
152 /* Session-Id = <EAP-Type> || Method-Id
153 * Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id",
157 id
= os_malloc(*len
);
160 method_id
= eap_server_tls_derive_key(
161 sm
, data
, "EXPORTER_EAP_TLS_Method-Id", NULL
, 0, 64);
167 os_memcpy(id
+ 1, method_id
, 64);
172 if (tls_connection_get_random(sm
->ssl_ctx
, data
->conn
, &keys
))
175 if (keys
.client_random
== NULL
|| keys
.server_random
== NULL
)
178 *len
= 1 + keys
.client_random_len
+ keys
.server_random_len
;
179 out
= os_malloc(*len
);
183 /* Session-Id = EAP type || client.random || server.random */
185 os_memcpy(out
+ 1, keys
.client_random
, keys
.client_random_len
);
186 os_memcpy(out
+ 1 + keys
.client_random_len
, keys
.server_random
,
187 keys
.server_random_len
);
193 struct wpabuf
* eap_server_tls_build_msg(struct eap_ssl_data
*data
,
194 int eap_type
, int version
, u8 id
)
198 size_t send_len
, plen
;
200 wpa_printf(MSG_DEBUG
, "SSL: Generating Request");
201 if (data
->tls_out
== NULL
) {
202 wpa_printf(MSG_ERROR
, "SSL: tls_out NULL in %s", __func__
);
207 send_len
= wpabuf_len(data
->tls_out
) - data
->tls_out_pos
;
208 if (1 + send_len
> data
->tls_out_limit
) {
209 send_len
= data
->tls_out_limit
- 1;
210 flags
|= EAP_TLS_FLAGS_MORE_FRAGMENTS
;
211 if (data
->tls_out_pos
== 0) {
212 flags
|= EAP_TLS_FLAGS_LENGTH_INCLUDED
;
218 if (flags
& EAP_TLS_FLAGS_LENGTH_INCLUDED
)
221 req
= eap_tls_msg_alloc(eap_type
, plen
, EAP_CODE_REQUEST
, id
);
225 wpabuf_put_u8(req
, flags
); /* Flags */
226 if (flags
& EAP_TLS_FLAGS_LENGTH_INCLUDED
)
227 wpabuf_put_be32(req
, wpabuf_len(data
->tls_out
));
229 wpabuf_put_data(req
, wpabuf_head_u8(data
->tls_out
) + data
->tls_out_pos
,
231 data
->tls_out_pos
+= send_len
;
233 if (data
->tls_out_pos
== wpabuf_len(data
->tls_out
)) {
234 wpa_printf(MSG_DEBUG
, "SSL: Sending out %lu bytes "
235 "(message sent completely)",
236 (unsigned long) send_len
);
237 wpabuf_free(data
->tls_out
);
238 data
->tls_out
= NULL
;
239 data
->tls_out_pos
= 0;
242 wpa_printf(MSG_DEBUG
, "SSL: Sending out %lu bytes "
243 "(%lu more to send)", (unsigned long) send_len
,
244 (unsigned long) wpabuf_len(data
->tls_out
) -
246 data
->state
= WAIT_FRAG_ACK
;
253 struct wpabuf
* eap_server_tls_build_ack(u8 id
, int eap_type
, int version
)
257 req
= eap_tls_msg_alloc(eap_type
, 1, EAP_CODE_REQUEST
, id
);
260 wpa_printf(MSG_DEBUG
, "SSL: Building ACK");
261 wpabuf_put_u8(req
, version
); /* Flags */
266 static int eap_server_tls_process_cont(struct eap_ssl_data
*data
,
267 const u8
*buf
, size_t len
)
269 /* Process continuation of a pending message */
270 if (len
> wpabuf_tailroom(data
->tls_in
)) {
271 wpa_printf(MSG_DEBUG
, "SSL: Fragment overflow");
275 wpabuf_put_data(data
->tls_in
, buf
, len
);
276 wpa_printf(MSG_DEBUG
, "SSL: Received %lu bytes, waiting for %lu "
277 "bytes more", (unsigned long) len
,
278 (unsigned long) wpabuf_tailroom(data
->tls_in
));
284 static int eap_server_tls_process_fragment(struct eap_ssl_data
*data
,
285 u8 flags
, u32 message_length
,
286 const u8
*buf
, size_t len
)
288 /* Process a fragment that is not the last one of the message */
289 if (data
->tls_in
== NULL
&& !(flags
& EAP_TLS_FLAGS_LENGTH_INCLUDED
)) {
290 wpa_printf(MSG_DEBUG
, "SSL: No Message Length field in a "
291 "fragmented packet");
295 if (data
->tls_in
== NULL
) {
296 /* First fragment of the message */
298 /* Limit length to avoid rogue peers from causing large
299 * memory allocations. */
300 if (message_length
> 65536) {
301 wpa_printf(MSG_INFO
, "SSL: Too long TLS fragment (size"
306 if (len
> message_length
) {
307 wpa_printf(MSG_INFO
, "SSL: Too much data (%d bytes) in "
308 "first fragment of frame (TLS Message "
310 (int) len
, (int) message_length
);
314 data
->tls_in
= wpabuf_alloc(message_length
);
315 if (data
->tls_in
== NULL
) {
316 wpa_printf(MSG_DEBUG
, "SSL: No memory for message");
319 wpabuf_put_data(data
->tls_in
, buf
, len
);
320 wpa_printf(MSG_DEBUG
, "SSL: Received %lu bytes in first "
321 "fragment, waiting for %lu bytes more",
323 (unsigned long) wpabuf_tailroom(data
->tls_in
));
330 int eap_server_tls_phase1(struct eap_sm
*sm
, struct eap_ssl_data
*data
)
335 /* This should not happen.. */
336 wpa_printf(MSG_INFO
, "SSL: pending tls_out data when "
337 "processing new message");
338 wpabuf_free(data
->tls_out
);
339 WPA_ASSERT(data
->tls_out
== NULL
);
342 data
->tls_out
= tls_connection_server_handshake(sm
->ssl_ctx
,
345 if (data
->tls_out
== NULL
) {
346 wpa_printf(MSG_INFO
, "SSL: TLS processing failed");
349 if (tls_connection_get_failed(sm
->ssl_ctx
, data
->conn
)) {
350 /* TLS processing has failed - return error */
351 wpa_printf(MSG_DEBUG
, "SSL: Failed - tls_out available to "
356 if (tls_get_version(sm
->ssl_ctx
, data
->conn
, buf
, sizeof(buf
)) == 0) {
357 wpa_printf(MSG_DEBUG
, "SSL: Using TLS version %s", buf
);
358 data
->tls_v13
= os_strcmp(buf
, "TLSv1.3") == 0;
361 if (!sm
->serial_num
&&
362 tls_connection_established(sm
->ssl_ctx
, data
->conn
))
363 sm
->serial_num
= tls_connection_peer_serial_num(sm
->ssl_ctx
,
370 static int eap_server_tls_reassemble(struct eap_ssl_data
*data
, u8 flags
,
371 const u8
**pos
, size_t *left
)
373 unsigned int tls_msg_len
= 0;
374 const u8
*end
= *pos
+ *left
;
376 wpa_hexdump(MSG_MSGDUMP
, "SSL: Received data", *pos
, *left
);
378 if (flags
& EAP_TLS_FLAGS_LENGTH_INCLUDED
) {
380 wpa_printf(MSG_INFO
, "SSL: Short frame with TLS "
384 tls_msg_len
= WPA_GET_BE32(*pos
);
385 wpa_printf(MSG_DEBUG
, "SSL: TLS Message Length: %d",
390 if (*left
> tls_msg_len
) {
391 wpa_printf(MSG_INFO
, "SSL: TLS Message Length (%d "
392 "bytes) smaller than this fragment (%d "
393 "bytes)", (int) tls_msg_len
, (int) *left
);
398 wpa_printf(MSG_DEBUG
, "SSL: Received packet: Flags 0x%x "
399 "Message Length %u", flags
, tls_msg_len
);
401 if (data
->state
== WAIT_FRAG_ACK
) {
403 wpa_printf(MSG_DEBUG
, "SSL: Unexpected payload in "
404 "WAIT_FRAG_ACK state");
407 wpa_printf(MSG_DEBUG
, "SSL: Fragment acknowledged");
412 eap_server_tls_process_cont(data
, *pos
, end
- *pos
) < 0)
415 if (flags
& EAP_TLS_FLAGS_MORE_FRAGMENTS
) {
416 if (eap_server_tls_process_fragment(data
, flags
, tls_msg_len
,
417 *pos
, end
- *pos
) < 0)
420 data
->state
= FRAG_ACK
;
424 if (data
->state
== FRAG_ACK
) {
425 wpa_printf(MSG_DEBUG
, "SSL: All fragments received");
429 if (data
->tls_in
== NULL
) {
430 /* Wrap unfragmented messages as wpabuf without extra copy */
431 wpabuf_set(&data
->tmpbuf
, *pos
, end
- *pos
);
432 data
->tls_in
= &data
->tmpbuf
;
439 static void eap_server_tls_free_in_buf(struct eap_ssl_data
*data
)
441 if (data
->tls_in
!= &data
->tmpbuf
)
442 wpabuf_free(data
->tls_in
);
447 struct wpabuf
* eap_server_tls_encrypt(struct eap_sm
*sm
,
448 struct eap_ssl_data
*data
,
449 const struct wpabuf
*plain
)
453 buf
= tls_connection_encrypt(sm
->ssl_ctx
, data
->conn
,
456 wpa_printf(MSG_INFO
, "SSL: Failed to encrypt Phase 2 data");
464 int eap_server_tls_process(struct eap_sm
*sm
, struct eap_ssl_data
*data
,
465 struct wpabuf
*respData
, void *priv
, int eap_type
,
466 int (*proc_version
)(struct eap_sm
*sm
, void *priv
,
468 void (*proc_msg
)(struct eap_sm
*sm
, void *priv
,
469 const struct wpabuf
*respData
))
476 if (eap_type
== EAP_UNAUTH_TLS_TYPE
)
477 pos
= eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS
,
478 EAP_VENDOR_TYPE_UNAUTH_TLS
, respData
,
480 else if (eap_type
== EAP_WFA_UNAUTH_TLS_TYPE
)
481 pos
= eap_hdr_validate(EAP_VENDOR_WFA_NEW
,
482 EAP_VENDOR_WFA_UNAUTH_TLS
, respData
,
485 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, eap_type
, respData
,
487 if (pos
== NULL
|| left
< 1)
488 return 0; /* Should not happen - frame already validated */
491 wpa_printf(MSG_DEBUG
, "SSL: Received packet(len=%lu) - Flags 0x%02x",
492 (unsigned long) wpabuf_len(respData
), flags
);
495 proc_version(sm
, priv
, flags
& EAP_TLS_VERSION_MASK
) < 0)
498 ret
= eap_server_tls_reassemble(data
, flags
, &pos
, &left
);
506 proc_msg(sm
, priv
, respData
);
508 if (tls_connection_get_write_alerts(sm
->ssl_ctx
, data
->conn
) > 1) {
509 wpa_printf(MSG_INFO
, "SSL: Locally detected fatal error in "
515 eap_server_tls_free_in_buf(data
);