1 /*
2 * TLS interface functions and an internal TLS implementation
3 * Copyright (c) 2004-2011, 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 * This file interface functions for hostapd/wpa_supplicant to use the
9 * integrated TLSv1 implementation.
10 */
11
12 #include "includes.h"
13
14 #include "common.h"
15 #include "tls.h"
16 #include "tls/tlsv1_client.h"
17 #include "tls/tlsv1_server.h"
18
19
20 static int tls_ref_count = 0;
21
22 struct tls_global {
23 int server;
24 struct tlsv1_credentials *server_cred;
25 int check_crl;
26 };
27
28 struct tls_connection {
29 struct tlsv1_client *client;
30 struct tlsv1_server *server;
31 };
32
33
tls_init(const struct tls_config * conf)34 void * tls_init(const struct tls_config *conf)
35 {
36 struct tls_global *global;
37
38 if (tls_ref_count == 0) {
39 #ifdef CONFIG_TLS_INTERNAL_CLIENT
40 if (tlsv1_client_global_init())
41 return NULL;
42 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
43 #ifdef CONFIG_TLS_INTERNAL_SERVER
44 if (tlsv1_server_global_init())
45 return NULL;
46 #endif /* CONFIG_TLS_INTERNAL_SERVER */
47 }
48 tls_ref_count++;
49
50 global = os_zalloc(sizeof(*global));
51 if (global == NULL)
52 return NULL;
53
54 return global;
55 }
56
tls_deinit(void * ssl_ctx)57 void tls_deinit(void *ssl_ctx)
58 {
59 struct tls_global *global = ssl_ctx;
60 tls_ref_count--;
61 if (tls_ref_count == 0) {
62 #ifdef CONFIG_TLS_INTERNAL_CLIENT
63 tlsv1_client_global_deinit();
64 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
65 #ifdef CONFIG_TLS_INTERNAL_SERVER
66 tlsv1_cred_free(global->server_cred);
67 tlsv1_server_global_deinit();
68 #endif /* CONFIG_TLS_INTERNAL_SERVER */
69 }
70 os_free(global);
71 }
72
73
tls_get_errors(void * tls_ctx)74 int tls_get_errors(void *tls_ctx)
75 {
76 return 0;
77 }
78
79
tls_connection_init(void * tls_ctx)80 struct tls_connection * tls_connection_init(void *tls_ctx)
81 {
82 struct tls_connection *conn;
83 struct tls_global *global = tls_ctx;
84
85 conn = os_zalloc(sizeof(*conn));
86 if (conn == NULL)
87 return NULL;
88
89 #ifdef CONFIG_TLS_INTERNAL_CLIENT
90 if (!global->server) {
91 conn->client = tlsv1_client_init();
92 if (conn->client == NULL) {
93 os_free(conn);
94 return NULL;
95 }
96 }
97 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
98 #ifdef CONFIG_TLS_INTERNAL_SERVER
99 if (global->server) {
100 conn->server = tlsv1_server_init(global->server_cred);
101 if (conn->server == NULL) {
102 os_free(conn);
103 return NULL;
104 }
105 }
106 #endif /* CONFIG_TLS_INTERNAL_SERVER */
107
108 return conn;
109 }
110
111
tls_connection_deinit(void * tls_ctx,struct tls_connection * conn)112 void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
113 {
114 if (conn == NULL)
115 return;
116 #ifdef CONFIG_TLS_INTERNAL_CLIENT
117 if (conn->client)
118 tlsv1_client_deinit(conn->client);
119 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
120 #ifdef CONFIG_TLS_INTERNAL_SERVER
121 if (conn->server)
122 tlsv1_server_deinit(conn->server);
123 #endif /* CONFIG_TLS_INTERNAL_SERVER */
124 os_free(conn);
125 }
126
127
tls_connection_established(void * tls_ctx,struct tls_connection * conn)128 int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
129 {
130 #ifdef CONFIG_TLS_INTERNAL_CLIENT
131 if (conn->client)
132 return tlsv1_client_established(conn->client);
133 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
134 #ifdef CONFIG_TLS_INTERNAL_SERVER
135 if (conn->server)
136 return tlsv1_server_established(conn->server);
137 #endif /* CONFIG_TLS_INTERNAL_SERVER */
138 return 0;
139 }
140
141
tls_connection_shutdown(void * tls_ctx,struct tls_connection * conn)142 int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
143 {
144 #ifdef CONFIG_TLS_INTERNAL_CLIENT
145 if (conn->client)
146 return tlsv1_client_shutdown(conn->client);
147 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
148 #ifdef CONFIG_TLS_INTERNAL_SERVER
149 if (conn->server)
150 return tlsv1_server_shutdown(conn->server);
151 #endif /* CONFIG_TLS_INTERNAL_SERVER */
152 return -1;
153 }
154
155
tls_connection_set_params(void * tls_ctx,struct tls_connection * conn,const struct tls_connection_params * params)156 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
157 const struct tls_connection_params *params)
158 {
159 #ifdef CONFIG_TLS_INTERNAL_CLIENT
160 struct tlsv1_credentials *cred;
161
162 if (conn->client == NULL)
163 return -1;
164
165 cred = tlsv1_cred_alloc();
166 if (cred == NULL)
167 return -1;
168
169 if (tlsv1_set_ca_cert(cred, params->ca_cert,
170 params->ca_cert_blob, params->ca_cert_blob_len,
171 params->ca_path)) {
172 wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA "
173 "certificates");
174 tlsv1_cred_free(cred);
175 return -1;
176 }
177
178 if (tlsv1_set_cert(cred, params->client_cert,
179 params->client_cert_blob,
180 params->client_cert_blob_len)) {
181 wpa_printf(MSG_INFO, "TLS: Failed to configure client "
182 "certificate");
183 tlsv1_cred_free(cred);
184 return -1;
185 }
186
187 if (tlsv1_set_private_key(cred, params->private_key,
188 params->private_key_passwd,
189 params->private_key_blob,
190 params->private_key_blob_len)) {
191 wpa_printf(MSG_INFO, "TLS: Failed to load private key");
192 tlsv1_cred_free(cred);
193 return -1;
194 }
195
196 if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
197 params->dh_blob_len)) {
198 wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
199 tlsv1_cred_free(cred);
200 return -1;
201 }
202
203 if (tlsv1_client_set_cred(conn->client, cred) < 0) {
204 tlsv1_cred_free(cred);
205 return -1;
206 }
207
208 tlsv1_client_set_time_checks(
209 conn->client, !(params->flags & TLS_CONN_DISABLE_TIME_CHECKS));
210
211 return 0;
212 #else /* CONFIG_TLS_INTERNAL_CLIENT */
213 return -1;
214 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
215 }
216
217
tls_global_set_params(void * tls_ctx,const struct tls_connection_params * params)218 int tls_global_set_params(void *tls_ctx,
219 const struct tls_connection_params *params)
220 {
221 #ifdef CONFIG_TLS_INTERNAL_SERVER
222 struct tls_global *global = tls_ctx;
223 struct tlsv1_credentials *cred;
224
225 /* Currently, global parameters are only set when running in server
226 * mode. */
227 global->server = 1;
228 tlsv1_cred_free(global->server_cred);
229 global->server_cred = cred = tlsv1_cred_alloc();
230 if (cred == NULL)
231 return -1;
232
233 if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob,
234 params->ca_cert_blob_len, params->ca_path)) {
235 wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA "
236 "certificates");
237 return -1;
238 }
239
240 if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob,
241 params->client_cert_blob_len)) {
242 wpa_printf(MSG_INFO, "TLS: Failed to configure server "
243 "certificate");
244 return -1;
245 }
246
247 if (tlsv1_set_private_key(cred, params->private_key,
248 params->private_key_passwd,
249 params->private_key_blob,
250 params->private_key_blob_len)) {
251 wpa_printf(MSG_INFO, "TLS: Failed to load private key");
252 return -1;
253 }
254
255 if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
256 params->dh_blob_len)) {
257 wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
258 return -1;
259 }
260
261 return 0;
262 #else /* CONFIG_TLS_INTERNAL_SERVER */
263 return -1;
264 #endif /* CONFIG_TLS_INTERNAL_SERVER */
265 }
266
267
tls_global_set_verify(void * tls_ctx,int check_crl)268 int tls_global_set_verify(void *tls_ctx, int check_crl)
269 {
270 struct tls_global *global = tls_ctx;
271 global->check_crl = check_crl;
272 return 0;
273 }
274
275
tls_connection_set_verify(void * tls_ctx,struct tls_connection * conn,int verify_peer)276 int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
277 int verify_peer)
278 {
279 #ifdef CONFIG_TLS_INTERNAL_SERVER
280 if (conn->server)
281 return tlsv1_server_set_verify(conn->server, verify_peer);
282 #endif /* CONFIG_TLS_INTERNAL_SERVER */
283 return -1;
284 }
285
286
tls_connection_get_keys(void * tls_ctx,struct tls_connection * conn,struct tls_keys * keys)287 int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
288 struct tls_keys *keys)
289 {
290 #ifdef CONFIG_TLS_INTERNAL_CLIENT
291 if (conn->client)
292 return tlsv1_client_get_keys(conn->client, keys);
293 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
294 #ifdef CONFIG_TLS_INTERNAL_SERVER
295 if (conn->server)
296 return tlsv1_server_get_keys(conn->server, keys);
297 #endif /* CONFIG_TLS_INTERNAL_SERVER */
298 return -1;
299 }
300
301
tls_connection_prf(void * tls_ctx,struct tls_connection * conn,const char * label,int server_random_first,u8 * out,size_t out_len)302 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
303 const char *label, int server_random_first,
304 u8 *out, size_t out_len)
305 {
306 #ifdef CONFIG_TLS_INTERNAL_CLIENT
307 if (conn->client) {
308 return tlsv1_client_prf(conn->client, label,
309 server_random_first,
310 out, out_len);
311 }
312 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
313 #ifdef CONFIG_TLS_INTERNAL_SERVER
314 if (conn->server) {
315 return tlsv1_server_prf(conn->server, label,
316 server_random_first,
317 out, out_len);
318 }
319 #endif /* CONFIG_TLS_INTERNAL_SERVER */
320 return -1;
321 }
322
323
tls_connection_handshake(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)324 struct wpabuf * tls_connection_handshake(void *tls_ctx,
325 struct tls_connection *conn,
326 const struct wpabuf *in_data,
327 struct wpabuf **appl_data)
328 {
329 return tls_connection_handshake2(tls_ctx, conn, in_data, appl_data,
330 NULL);
331 }
332
333
tls_connection_handshake2(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data,int * need_more_data)334 struct wpabuf * tls_connection_handshake2(void *tls_ctx,
335 struct tls_connection *conn,
336 const struct wpabuf *in_data,
337 struct wpabuf **appl_data,
338 int *need_more_data)
339 {
340 #ifdef CONFIG_TLS_INTERNAL_CLIENT
341 u8 *res, *ad;
342 size_t res_len, ad_len;
343 struct wpabuf *out;
344
345 if (conn->client == NULL)
346 return NULL;
347
348 ad = NULL;
349 res = tlsv1_client_handshake(conn->client,
350 in_data ? wpabuf_head(in_data) : NULL,
351 in_data ? wpabuf_len(in_data) : 0,
352 &res_len, &ad, &ad_len, need_more_data);
353 if (res == NULL)
354 return NULL;
355 out = wpabuf_alloc_ext_data(res, res_len);
356 if (out == NULL) {
357 os_free(res);
358 os_free(ad);
359 return NULL;
360 }
361 if (appl_data) {
362 if (ad) {
363 *appl_data = wpabuf_alloc_ext_data(ad, ad_len);
364 if (*appl_data == NULL)
365 os_free(ad);
366 } else
367 *appl_data = NULL;
368 } else
369 os_free(ad);
370
371 return out;
372 #else /* CONFIG_TLS_INTERNAL_CLIENT */
373 return NULL;
374 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
375 }
376
377
tls_connection_server_handshake(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)378 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
379 struct tls_connection *conn,
380 const struct wpabuf *in_data,
381 struct wpabuf **appl_data)
382 {
383 #ifdef CONFIG_TLS_INTERNAL_SERVER
384 u8 *res;
385 size_t res_len;
386 struct wpabuf *out;
387
388 if (conn->server == NULL)
389 return NULL;
390
391 if (appl_data)
392 *appl_data = NULL;
393
394 res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data),
395 wpabuf_len(in_data), &res_len);
396 if (res == NULL && tlsv1_server_established(conn->server))
397 return wpabuf_alloc(0);
398 if (res == NULL)
399 return NULL;
400 out = wpabuf_alloc_ext_data(res, res_len);
401 if (out == NULL) {
402 os_free(res);
403 return NULL;
404 }
405
406 return out;
407 #else /* CONFIG_TLS_INTERNAL_SERVER */
408 return NULL;
409 #endif /* CONFIG_TLS_INTERNAL_SERVER */
410 }
411
412
tls_connection_encrypt(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data)413 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
414 struct tls_connection *conn,
415 const struct wpabuf *in_data)
416 {
417 #ifdef CONFIG_TLS_INTERNAL_CLIENT
418 if (conn->client) {
419 struct wpabuf *buf;
420 int res;
421 buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
422 if (buf == NULL)
423 return NULL;
424 res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data),
425 wpabuf_len(in_data),
426 wpabuf_mhead(buf),
427 wpabuf_size(buf));
428 if (res < 0) {
429 wpabuf_free(buf);
430 return NULL;
431 }
432 wpabuf_put(buf, res);
433 return buf;
434 }
435 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
436 #ifdef CONFIG_TLS_INTERNAL_SERVER
437 if (conn->server) {
438 struct wpabuf *buf;
439 int res;
440 buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
441 if (buf == NULL)
442 return NULL;
443 res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data),
444 wpabuf_len(in_data),
445 wpabuf_mhead(buf),
446 wpabuf_size(buf));
447 if (res < 0) {
448 wpabuf_free(buf);
449 return NULL;
450 }
451 wpabuf_put(buf, res);
452 return buf;
453 }
454 #endif /* CONFIG_TLS_INTERNAL_SERVER */
455 return NULL;
456 }
457
458
tls_connection_decrypt(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data)459 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
460 struct tls_connection *conn,
461 const struct wpabuf *in_data)
462 {
463 return tls_connection_decrypt2(tls_ctx, conn, in_data, NULL);
464 }
465
466
tls_connection_decrypt2(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,int * need_more_data)467 struct wpabuf * tls_connection_decrypt2(void *tls_ctx,
468 struct tls_connection *conn,
469 const struct wpabuf *in_data,
470 int *need_more_data)
471 {
472 if (need_more_data)
473 *need_more_data = 0;
474
475 #ifdef CONFIG_TLS_INTERNAL_CLIENT
476 if (conn->client) {
477 return tlsv1_client_decrypt(conn->client, wpabuf_head(in_data),
478 wpabuf_len(in_data),
479 need_more_data);
480 }
481 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
482 #ifdef CONFIG_TLS_INTERNAL_SERVER
483 if (conn->server) {
484 struct wpabuf *buf;
485 int res;
486 buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
487 if (buf == NULL)
488 return NULL;
489 res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data),
490 wpabuf_len(in_data),
491 wpabuf_mhead(buf),
492 wpabuf_size(buf));
493 if (res < 0) {
494 wpabuf_free(buf);
495 return NULL;
496 }
497 wpabuf_put(buf, res);
498 return buf;
499 }
500 #endif /* CONFIG_TLS_INTERNAL_SERVER */
501 return NULL;
502 }
503
504
tls_connection_resumed(void * tls_ctx,struct tls_connection * conn)505 int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
506 {
507 #ifdef CONFIG_TLS_INTERNAL_CLIENT
508 if (conn->client)
509 return tlsv1_client_resumed(conn->client);
510 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
511 #ifdef CONFIG_TLS_INTERNAL_SERVER
512 if (conn->server)
513 return tlsv1_server_resumed(conn->server);
514 #endif /* CONFIG_TLS_INTERNAL_SERVER */
515 return -1;
516 }
517
518
tls_connection_set_cipher_list(void * tls_ctx,struct tls_connection * conn,u8 * ciphers)519 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
520 u8 *ciphers)
521 {
522 #ifdef CONFIG_TLS_INTERNAL_CLIENT
523 if (conn->client)
524 return tlsv1_client_set_cipher_list(conn->client, ciphers);
525 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
526 #ifdef CONFIG_TLS_INTERNAL_SERVER
527 if (conn->server)
528 return tlsv1_server_set_cipher_list(conn->server, ciphers);
529 #endif /* CONFIG_TLS_INTERNAL_SERVER */
530 return -1;
531 }
532
533
tls_get_cipher(void * tls_ctx,struct tls_connection * conn,char * buf,size_t buflen)534 int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
535 char *buf, size_t buflen)
536 {
537 if (conn == NULL)
538 return -1;
539 #ifdef CONFIG_TLS_INTERNAL_CLIENT
540 if (conn->client)
541 return tlsv1_client_get_cipher(conn->client, buf, buflen);
542 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
543 #ifdef CONFIG_TLS_INTERNAL_SERVER
544 if (conn->server)
545 return tlsv1_server_get_cipher(conn->server, buf, buflen);
546 #endif /* CONFIG_TLS_INTERNAL_SERVER */
547 return -1;
548 }
549
550
tls_connection_enable_workaround(void * tls_ctx,struct tls_connection * conn)551 int tls_connection_enable_workaround(void *tls_ctx,
552 struct tls_connection *conn)
553 {
554 return -1;
555 }
556
557
tls_connection_client_hello_ext(void * tls_ctx,struct tls_connection * conn,int ext_type,const u8 * data,size_t data_len)558 int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
559 int ext_type, const u8 *data,
560 size_t data_len)
561 {
562 #ifdef CONFIG_TLS_INTERNAL_CLIENT
563 if (conn->client) {
564 return tlsv1_client_hello_ext(conn->client, ext_type,
565 data, data_len);
566 }
567 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
568 return -1;
569 }
570
571
tls_connection_get_failed(void * tls_ctx,struct tls_connection * conn)572 int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
573 {
574 return 0;
575 }
576
577
tls_connection_get_read_alerts(void * tls_ctx,struct tls_connection * conn)578 int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
579 {
580 return 0;
581 }
582
583
tls_connection_get_write_alerts(void * tls_ctx,struct tls_connection * conn)584 int tls_connection_get_write_alerts(void *tls_ctx,
585 struct tls_connection *conn)
586 {
587 return 0;
588 }
589
590
tls_connection_get_keyblock_size(void * tls_ctx,struct tls_connection * conn)591 int tls_connection_get_keyblock_size(void *tls_ctx,
592 struct tls_connection *conn)
593 {
594 #ifdef CONFIG_TLS_INTERNAL_CLIENT
595 if (conn->client)
596 return tlsv1_client_get_keyblock_size(conn->client);
597 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
598 #ifdef CONFIG_TLS_INTERNAL_SERVER
599 if (conn->server)
600 return tlsv1_server_get_keyblock_size(conn->server);
601 #endif /* CONFIG_TLS_INTERNAL_SERVER */
602 return -1;
603 }
604
605
tls_capabilities(void * tls_ctx)606 unsigned int tls_capabilities(void *tls_ctx)
607 {
608 return 0;
609 }
610
611
tls_connection_set_session_ticket_cb(void * tls_ctx,struct tls_connection * conn,tls_session_ticket_cb cb,void * ctx)612 int tls_connection_set_session_ticket_cb(void *tls_ctx,
613 struct tls_connection *conn,
614 tls_session_ticket_cb cb,
615 void *ctx)
616 {
617 #ifdef CONFIG_TLS_INTERNAL_CLIENT
618 if (conn->client) {
619 tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx);
620 return 0;
621 }
622 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
623 #ifdef CONFIG_TLS_INTERNAL_SERVER
624 if (conn->server) {
625 tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx);
626 return 0;
627 }
628 #endif /* CONFIG_TLS_INTERNAL_SERVER */
629 return -1;
630 }
631