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