]> git.ipfire.org Git - thirdparty/hostap.git/blame - src/crypto/tls_internal.c
Remove the GPL notification from files contributed by Jouni Malinen
[thirdparty/hostap.git] / src / crypto / tls_internal.c
CommitLineData
6fc6879b 1/*
81c85c06 2 * TLS interface functions and an internal TLS implementation
235279e7 3 * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
6fc6879b 4 *
0f3d578e
JM
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
6fc6879b
JM
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
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;
31};
32
33
34void * 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
57void 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
74int tls_get_errors(void *tls_ctx)
75{
76 return 0;
77}
78
79
80struct 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
112void 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
128int 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
142int 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
156int 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
235279e7
JM
208 tlsv1_client_set_time_checks(
209 conn->client, !(params->flags & TLS_CONN_DISABLE_TIME_CHECKS));
210
6fc6879b
JM
211 return 0;
212#else /* CONFIG_TLS_INTERNAL_CLIENT */
213 return -1;
214#endif /* CONFIG_TLS_INTERNAL_CLIENT */
215}
216
217
218int 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
268int 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
276int 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
6fc6879b
JM
287int 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
302int 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
81c85c06
JM
324struct wpabuf * tls_connection_handshake(void *tls_ctx,
325 struct tls_connection *conn,
326 const struct wpabuf *in_data,
327 struct wpabuf **appl_data)
dbdcfa39
JM
328{
329 return tls_connection_handshake2(tls_ctx, conn, in_data, appl_data,
330 NULL);
331}
332
333
334struct 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)
6fc6879b
JM
339{
340#ifdef CONFIG_TLS_INTERNAL_CLIENT
81c85c06
JM
341 u8 *res, *ad;
342 size_t res_len, ad_len;
343 struct wpabuf *out;
344
6fc6879b
JM
345 if (conn->client == NULL)
346 return NULL;
347
81c85c06
JM
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,
dbdcfa39 352 &res_len, &ad, &ad_len, need_more_data);
81c85c06
JM
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);
6fc6879b 370
81c85c06 371 return out;
6fc6879b
JM
372#else /* CONFIG_TLS_INTERNAL_CLIENT */
373 return NULL;
374#endif /* CONFIG_TLS_INTERNAL_CLIENT */
375}
376
377
81c85c06
JM
378struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
379 struct tls_connection *conn,
380 const struct wpabuf *in_data,
381 struct wpabuf **appl_data)
6fc6879b
JM
382{
383#ifdef CONFIG_TLS_INTERNAL_SERVER
81c85c06
JM
384 u8 *res;
385 size_t res_len;
386 struct wpabuf *out;
387
6fc6879b
JM
388 if (conn->server == NULL)
389 return NULL;
390
81c85c06
JM
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;
4d4233ea 404 }
81c85c06 405
6fc6879b
JM
406 return out;
407#else /* CONFIG_TLS_INTERNAL_SERVER */
408 return NULL;
409#endif /* CONFIG_TLS_INTERNAL_SERVER */
410}
411
412
81c85c06
JM
413struct wpabuf * tls_connection_encrypt(void *tls_ctx,
414 struct tls_connection *conn,
415 const struct wpabuf *in_data)
6fc6879b
JM
416{
417#ifdef CONFIG_TLS_INTERNAL_CLIENT
418 if (conn->client) {
81c85c06
JM
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;
6fc6879b
JM
434 }
435#endif /* CONFIG_TLS_INTERNAL_CLIENT */
436#ifdef CONFIG_TLS_INTERNAL_SERVER
437 if (conn->server) {
81c85c06
JM
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;
6fc6879b
JM
453 }
454#endif /* CONFIG_TLS_INTERNAL_SERVER */
81c85c06 455 return NULL;
6fc6879b
JM
456}
457
458
81c85c06
JM
459struct wpabuf * tls_connection_decrypt(void *tls_ctx,
460 struct tls_connection *conn,
461 const struct wpabuf *in_data)
6fc6879b 462{
dbdcfa39
JM
463 return tls_connection_decrypt2(tls_ctx, conn, in_data, NULL);
464}
465
466
467struct 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
6fc6879b
JM
475#ifdef CONFIG_TLS_INTERNAL_CLIENT
476 if (conn->client) {
dbdcfa39
JM
477 return tlsv1_client_decrypt(conn->client, wpabuf_head(in_data),
478 wpabuf_len(in_data),
479 need_more_data);
6fc6879b
JM
480 }
481#endif /* CONFIG_TLS_INTERNAL_CLIENT */
482#ifdef CONFIG_TLS_INTERNAL_SERVER
483 if (conn->server) {
81c85c06
JM
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;
6fc6879b
JM
499 }
500#endif /* CONFIG_TLS_INTERNAL_SERVER */
81c85c06 501 return NULL;
6fc6879b
JM
502}
503
504
505int 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
519int 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
534int 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
551int tls_connection_enable_workaround(void *tls_ctx,
552 struct tls_connection *conn)
553{
554 return -1;
555}
556
557
558int 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
572int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
573{
574 return 0;
575}
576
577
578int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
579{
580 return 0;
581}
582
583
584int tls_connection_get_write_alerts(void *tls_ctx,
585 struct tls_connection *conn)
586{
587 return 0;
588}
589
590
591int 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
606unsigned int tls_capabilities(void *tls_ctx)
607{
608 return 0;
609}
610
611
6fc6879b
JM
612int 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}