Line data Source code
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 :
21 1176 : struct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len,
22 : u8 code, u8 identifier)
23 : {
24 1176 : if (type == EAP_UNAUTH_TLS_TYPE)
25 8 : return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS,
26 : EAP_VENDOR_TYPE_UNAUTH_TLS, payload_len,
27 : code, identifier);
28 1168 : else if (type == EAP_WFA_UNAUTH_TLS_TYPE)
29 8 : return eap_msg_alloc(EAP_VENDOR_WFA_NEW,
30 : EAP_VENDOR_WFA_UNAUTH_TLS, payload_len,
31 : code, identifier);
32 1160 : return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code,
33 : identifier);
34 : }
35 :
36 :
37 : #ifdef CONFIG_TLS_INTERNAL
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 :
46 339 : int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
47 : int verify_peer)
48 : {
49 339 : if (sm->ssl_ctx == NULL) {
50 0 : wpa_printf(MSG_ERROR, "TLS context not initialized - cannot use TLS-based EAP method");
51 0 : return -1;
52 : }
53 :
54 339 : data->eap = sm;
55 339 : data->phase2 = sm->init_phase2;
56 :
57 339 : data->conn = tls_connection_init(sm->ssl_ctx);
58 339 : if (data->conn == NULL) {
59 0 : wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
60 : "connection");
61 0 : return -1;
62 : }
63 :
64 : #ifdef CONFIG_TLS_INTERNAL
65 : tls_connection_set_log_cb(data->conn, eap_server_tls_log_cb, sm);
66 : #ifdef CONFIG_TESTING_OPTIONS
67 : tls_connection_set_test_flags(data->conn, sm->tls_test_flags);
68 : #endif /* CONFIG_TESTING_OPTIONS */
69 : #endif /* CONFIG_TLS_INTERNAL */
70 :
71 339 : if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer)) {
72 0 : wpa_printf(MSG_INFO, "SSL: Failed to configure verification "
73 : "of TLS peer certificate");
74 0 : tls_connection_deinit(sm->ssl_ctx, data->conn);
75 0 : data->conn = NULL;
76 0 : return -1;
77 : }
78 :
79 339 : data->tls_out_limit = sm->fragment_size > 0 ? sm->fragment_size : 1398;
80 339 : if (data->phase2) {
81 : /* Limit the fragment size in the inner TLS authentication
82 : * since the outer authentication with EAP-PEAP does not yet
83 : * support fragmentation */
84 2 : if (data->tls_out_limit > 100)
85 2 : data->tls_out_limit -= 100;
86 : }
87 339 : return 0;
88 : }
89 :
90 :
91 339 : void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
92 : {
93 339 : tls_connection_deinit(sm->ssl_ctx, data->conn);
94 339 : eap_server_tls_free_in_buf(data);
95 339 : wpabuf_free(data->tls_out);
96 339 : data->tls_out = NULL;
97 339 : }
98 :
99 :
100 287 : u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
101 : char *label, size_t len)
102 : {
103 : struct tls_keys keys;
104 287 : u8 *rnd = NULL, *out;
105 :
106 287 : out = os_malloc(len);
107 287 : if (out == NULL)
108 0 : return NULL;
109 :
110 287 : if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
111 : 0)
112 287 : return out;
113 :
114 0 : if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
115 0 : goto fail;
116 :
117 0 : if (keys.client_random == NULL || keys.server_random == NULL ||
118 0 : keys.master_key == NULL)
119 : goto fail;
120 :
121 0 : rnd = os_malloc(keys.client_random_len + keys.server_random_len);
122 0 : if (rnd == NULL)
123 0 : goto fail;
124 0 : os_memcpy(rnd, keys.client_random, keys.client_random_len);
125 0 : os_memcpy(rnd + keys.client_random_len, keys.server_random,
126 : keys.server_random_len);
127 :
128 0 : if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
129 0 : label, rnd, keys.client_random_len +
130 0 : keys.server_random_len, out, len))
131 0 : goto fail;
132 :
133 0 : os_free(rnd);
134 0 : return out;
135 :
136 : fail:
137 0 : os_free(out);
138 0 : os_free(rnd);
139 0 : return NULL;
140 : }
141 :
142 :
143 : /**
144 : * eap_server_tls_derive_session_id - Derive a Session-Id based on TLS data
145 : * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
146 : * @data: Data for TLS processing
147 : * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
148 : * @len: Pointer to length of the session ID generated
149 : * Returns: Pointer to allocated Session-Id on success or %NULL on failure
150 : *
151 : * This function derive the Session-Id based on the TLS session data
152 : * (client/server random and method type).
153 : *
154 : * The caller is responsible for freeing the returned buffer.
155 : */
156 191 : u8 * eap_server_tls_derive_session_id(struct eap_sm *sm,
157 : struct eap_ssl_data *data, u8 eap_type,
158 : size_t *len)
159 : {
160 : struct tls_keys keys;
161 : u8 *out;
162 :
163 191 : if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
164 0 : return NULL;
165 :
166 191 : if (keys.client_random == NULL || keys.server_random == NULL)
167 0 : return NULL;
168 :
169 191 : *len = 1 + keys.client_random_len + keys.server_random_len;
170 191 : out = os_malloc(*len);
171 191 : if (out == NULL)
172 0 : return NULL;
173 :
174 : /* Session-Id = EAP type || client.random || server.random */
175 191 : out[0] = eap_type;
176 191 : os_memcpy(out + 1, keys.client_random, keys.client_random_len);
177 191 : os_memcpy(out + 1 + keys.client_random_len, keys.server_random,
178 : keys.server_random_len);
179 :
180 191 : return out;
181 : }
182 :
183 :
184 1083 : struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data,
185 : int eap_type, int version, u8 id)
186 : {
187 : struct wpabuf *req;
188 : u8 flags;
189 : size_t send_len, plen;
190 :
191 1083 : wpa_printf(MSG_DEBUG, "SSL: Generating Request");
192 1083 : if (data->tls_out == NULL) {
193 5 : wpa_printf(MSG_ERROR, "SSL: tls_out NULL in %s", __func__);
194 5 : return NULL;
195 : }
196 :
197 1078 : flags = version;
198 1078 : send_len = wpabuf_len(data->tls_out) - data->tls_out_pos;
199 1078 : if (1 + send_len > data->tls_out_limit) {
200 225 : send_len = data->tls_out_limit - 1;
201 225 : flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
202 225 : if (data->tls_out_pos == 0) {
203 216 : flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
204 216 : send_len -= 4;
205 : }
206 : }
207 :
208 1078 : plen = 1 + send_len;
209 1078 : if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
210 216 : plen += 4;
211 :
212 1078 : req = eap_tls_msg_alloc(eap_type, plen, EAP_CODE_REQUEST, id);
213 1078 : if (req == NULL)
214 0 : return NULL;
215 :
216 1078 : wpabuf_put_u8(req, flags); /* Flags */
217 1078 : if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
218 216 : wpabuf_put_be32(req, wpabuf_len(data->tls_out));
219 :
220 1078 : wpabuf_put_data(req, wpabuf_head_u8(data->tls_out) + data->tls_out_pos,
221 : send_len);
222 1078 : data->tls_out_pos += send_len;
223 :
224 1078 : if (data->tls_out_pos == wpabuf_len(data->tls_out)) {
225 853 : wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
226 : "(message sent completely)",
227 : (unsigned long) send_len);
228 853 : wpabuf_free(data->tls_out);
229 853 : data->tls_out = NULL;
230 853 : data->tls_out_pos = 0;
231 853 : data->state = MSG;
232 : } else {
233 225 : wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
234 : "(%lu more to send)", (unsigned long) send_len,
235 225 : (unsigned long) wpabuf_len(data->tls_out) -
236 225 : data->tls_out_pos);
237 225 : data->state = WAIT_FRAG_ACK;
238 : }
239 :
240 1078 : return req;
241 : }
242 :
243 :
244 73 : struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version)
245 : {
246 : struct wpabuf *req;
247 :
248 73 : req = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_REQUEST, id);
249 73 : if (req == NULL)
250 0 : return NULL;
251 73 : wpa_printf(MSG_DEBUG, "SSL: Building ACK");
252 73 : wpabuf_put_u8(req, version); /* Flags */
253 73 : return req;
254 : }
255 :
256 :
257 72 : static int eap_server_tls_process_cont(struct eap_ssl_data *data,
258 : const u8 *buf, size_t len)
259 : {
260 : /* Process continuation of a pending message */
261 72 : if (len > wpabuf_tailroom(data->tls_in)) {
262 0 : wpa_printf(MSG_DEBUG, "SSL: Fragment overflow");
263 0 : return -1;
264 : }
265 :
266 72 : wpabuf_put_data(data->tls_in, buf, len);
267 72 : wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu "
268 : "bytes more", (unsigned long) len,
269 72 : (unsigned long) wpabuf_tailroom(data->tls_in));
270 :
271 72 : return 0;
272 : }
273 :
274 :
275 73 : static int eap_server_tls_process_fragment(struct eap_ssl_data *data,
276 : u8 flags, u32 message_length,
277 : const u8 *buf, size_t len)
278 : {
279 : /* Process a fragment that is not the last one of the message */
280 73 : if (data->tls_in == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) {
281 0 : wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a "
282 : "fragmented packet");
283 0 : return -1;
284 : }
285 :
286 73 : if (data->tls_in == NULL) {
287 : /* First fragment of the message */
288 :
289 : /* Limit length to avoid rogue peers from causing large
290 : * memory allocations. */
291 23 : if (message_length > 65536) {
292 0 : wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size"
293 : " over 64 kB)");
294 0 : return -1;
295 : }
296 :
297 23 : if (len > message_length) {
298 0 : wpa_printf(MSG_INFO, "SSL: Too much data (%d bytes) in "
299 : "first fragment of frame (TLS Message "
300 : "Length %d bytes)",
301 : (int) len, (int) message_length);
302 0 : return -1;
303 : }
304 :
305 23 : data->tls_in = wpabuf_alloc(message_length);
306 23 : if (data->tls_in == NULL) {
307 0 : wpa_printf(MSG_DEBUG, "SSL: No memory for message");
308 0 : return -1;
309 : }
310 23 : wpabuf_put_data(data->tls_in, buf, len);
311 23 : wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first "
312 : "fragment, waiting for %lu bytes more",
313 : (unsigned long) len,
314 23 : (unsigned long) wpabuf_tailroom(data->tls_in));
315 : }
316 :
317 73 : return 0;
318 : }
319 :
320 :
321 519 : int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
322 : {
323 519 : if (data->tls_out) {
324 : /* This should not happen.. */
325 0 : wpa_printf(MSG_INFO, "SSL: pending tls_out data when "
326 : "processing new message");
327 0 : wpabuf_free(data->tls_out);
328 : WPA_ASSERT(data->tls_out == NULL);
329 : }
330 :
331 519 : data->tls_out = tls_connection_server_handshake(sm->ssl_ctx,
332 : data->conn,
333 519 : data->tls_in, NULL);
334 519 : if (data->tls_out == NULL) {
335 0 : wpa_printf(MSG_INFO, "SSL: TLS processing failed");
336 0 : return -1;
337 : }
338 519 : if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
339 : /* TLS processing has failed - return error */
340 27 : wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
341 : "report error");
342 27 : return -1;
343 : }
344 :
345 492 : return 0;
346 : }
347 :
348 :
349 1413 : static int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
350 : const u8 **pos, size_t *left)
351 : {
352 1413 : unsigned int tls_msg_len = 0;
353 1413 : const u8 *end = *pos + *left;
354 :
355 1413 : if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
356 41 : if (*left < 4) {
357 0 : wpa_printf(MSG_INFO, "SSL: Short frame with TLS "
358 : "length");
359 0 : return -1;
360 : }
361 41 : tls_msg_len = WPA_GET_BE32(*pos);
362 41 : wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d",
363 : tls_msg_len);
364 41 : *pos += 4;
365 41 : *left -= 4;
366 :
367 41 : if (*left > tls_msg_len) {
368 0 : wpa_printf(MSG_INFO, "SSL: TLS Message Length (%d "
369 : "bytes) smaller than this fragment (%d "
370 0 : "bytes)", (int) tls_msg_len, (int) *left);
371 0 : return -1;
372 : }
373 : }
374 :
375 1413 : wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x "
376 : "Message Length %u", flags, tls_msg_len);
377 :
378 1413 : if (data->state == WAIT_FRAG_ACK) {
379 225 : if (*left != 0) {
380 0 : wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in "
381 : "WAIT_FRAG_ACK state");
382 0 : return -1;
383 : }
384 225 : wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged");
385 225 : return 1;
386 : }
387 :
388 1260 : if (data->tls_in &&
389 72 : eap_server_tls_process_cont(data, *pos, end - *pos) < 0)
390 0 : return -1;
391 :
392 1188 : if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) {
393 73 : if (eap_server_tls_process_fragment(data, flags, tls_msg_len,
394 73 : *pos, end - *pos) < 0)
395 0 : return -1;
396 :
397 73 : data->state = FRAG_ACK;
398 73 : return 1;
399 : }
400 :
401 1115 : if (data->state == FRAG_ACK) {
402 22 : wpa_printf(MSG_DEBUG, "SSL: All fragments received");
403 22 : data->state = MSG;
404 : }
405 :
406 1115 : if (data->tls_in == NULL) {
407 : /* Wrap unfragmented messages as wpabuf without extra copy */
408 1093 : wpabuf_set(&data->tmpbuf, *pos, end - *pos);
409 1093 : data->tls_in = &data->tmpbuf;
410 : }
411 :
412 1115 : return 0;
413 : }
414 :
415 :
416 1454 : static void eap_server_tls_free_in_buf(struct eap_ssl_data *data)
417 : {
418 1454 : if (data->tls_in != &data->tmpbuf)
419 361 : wpabuf_free(data->tls_in);
420 1454 : data->tls_in = NULL;
421 1454 : }
422 :
423 :
424 382 : struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
425 : struct eap_ssl_data *data,
426 : const struct wpabuf *plain)
427 : {
428 : struct wpabuf *buf;
429 :
430 382 : buf = tls_connection_encrypt(sm->ssl_ctx, data->conn,
431 : plain);
432 382 : if (buf == NULL) {
433 0 : wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data");
434 0 : return NULL;
435 : }
436 :
437 382 : return buf;
438 : }
439 :
440 :
441 1413 : int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
442 : struct wpabuf *respData, void *priv, int eap_type,
443 : int (*proc_version)(struct eap_sm *sm, void *priv,
444 : int peer_version),
445 : void (*proc_msg)(struct eap_sm *sm, void *priv,
446 : const struct wpabuf *respData))
447 : {
448 : const u8 *pos;
449 : u8 flags;
450 : size_t left;
451 1413 : int ret, res = 0;
452 :
453 1413 : if (eap_type == EAP_UNAUTH_TLS_TYPE)
454 8 : pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
455 : EAP_VENDOR_TYPE_UNAUTH_TLS, respData,
456 : &left);
457 1405 : else if (eap_type == EAP_WFA_UNAUTH_TLS_TYPE)
458 8 : pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW,
459 : EAP_VENDOR_WFA_UNAUTH_TLS, respData,
460 : &left);
461 : else
462 1397 : pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData,
463 : &left);
464 1413 : if (pos == NULL || left < 1)
465 0 : return 0; /* Should not happen - frame already validated */
466 1413 : flags = *pos++;
467 1413 : left--;
468 1413 : wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x",
469 : (unsigned long) wpabuf_len(respData), flags);
470 :
471 2715 : if (proc_version &&
472 1302 : proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0)
473 0 : return -1;
474 :
475 1413 : ret = eap_server_tls_reassemble(data, flags, &pos, &left);
476 1413 : if (ret < 0) {
477 0 : res = -1;
478 0 : goto done;
479 1413 : } else if (ret == 1)
480 298 : return 0;
481 :
482 1115 : if (proc_msg)
483 1115 : proc_msg(sm, priv, respData);
484 :
485 1115 : if (tls_connection_get_write_alerts(sm->ssl_ctx, data->conn) > 1) {
486 0 : wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in "
487 : "TLS processing");
488 0 : res = -1;
489 : }
490 :
491 : done:
492 1115 : eap_server_tls_free_in_buf(data);
493 :
494 1115 : return res;
495 : }
|