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 "utils/includes.h"
13
14 #include "utils/common.h"
15 #include "crypto/sha1.h"
16 #include "crypto/md5.h"
17 #include "tls/tls.h"
18 #include "tls/tlsv1_client.h"
19 #include "tls/tlsv1_server.h"
20
21 static int tls_ref_count = 0;
22
23 struct tls_global {
24 int server;
25 struct tlsv1_credentials *server_cred;
26 int check_crl;
27 };
28
29 struct tls_connection {
30 struct tlsv1_client *client;
31 struct tlsv1_server *server;
32 };
33
34
tls_init(void)35 void * tls_init(void)
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 = (struct tls_global *)os_zalloc(sizeof(*global));
52 if (global == NULL)
53 return NULL;
54
55 return global;
56 }
57
tls_deinit(void * ssl_ctx)58 void 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
tls_get_errors(void * tls_ctx)75 int tls_get_errors(void *tls_ctx)
76 {
77 return 0;
78 }
79
80
tls_connection_init(void * tls_ctx)81 struct tls_connection * tls_connection_init(void *tls_ctx)
82 {
83 struct tls_connection *conn;
84 struct tls_global *global = tls_ctx;
85
86 conn = (struct tls_connection *)os_zalloc(sizeof(*conn));
87 if (conn == NULL)
88 return NULL;
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_client_set_cred(conn->client, cred) < 0) {
197 tlsv1_cred_free(cred);
198 return -1;
199 }
200
201 tlsv1_client_set_time_checks(
202 conn->client, !(params->flags & TLS_CONN_DISABLE_TIME_CHECKS));
203
204 return 0;
205 #else /* CONFIG_TLS_INTERNAL_CLIENT */
206 return -1;
207 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
208 }
209
210
tls_global_set_params(void * tls_ctx,const struct tls_connection_params * params)211 int tls_global_set_params(void *tls_ctx,
212 const struct tls_connection_params *params)
213 {
214 #ifdef CONFIG_TLS_INTERNAL_SERVER
215 struct tls_global *global = tls_ctx;
216 struct tlsv1_credentials *cred;
217
218 /* Currently, global parameters are only set when running in server
219 * mode. */
220 global->server = 1;
221 tlsv1_cred_free(global->server_cred);
222 global->server_cred = cred = tlsv1_cred_alloc();
223 if (cred == NULL)
224 return -1;
225
226 if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob,
227 params->ca_cert_blob_len, params->ca_path)) {
228 wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA "
229 "certificates");
230 return -1;
231 }
232
233 if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob,
234 params->client_cert_blob_len)) {
235 wpa_printf(MSG_INFO, "TLS: Failed to configure server "
236 "certificate");
237 return -1;
238 }
239
240 if (tlsv1_set_private_key(cred, params->private_key,
241 params->private_key_passwd,
242 params->private_key_blob,
243 params->private_key_blob_len)) {
244 wpa_printf(MSG_INFO, "TLS: Failed to load private key");
245 return -1;
246 }
247
248 if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
249 params->dh_blob_len)) {
250 wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
251 return -1;
252 }
253
254 return 0;
255 #else /* CONFIG_TLS_INTERNAL_SERVER */
256 return -1;
257 #endif /* CONFIG_TLS_INTERNAL_SERVER */
258 }
259
260
tls_global_set_verify(void * tls_ctx,int check_crl)261 int tls_global_set_verify(void *tls_ctx, int check_crl)
262 {
263 struct tls_global *global = tls_ctx;
264 global->check_crl = check_crl;
265 return 0;
266 }
267
268
tls_connection_set_verify(void * tls_ctx,struct tls_connection * conn,int verify_peer)269 int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
270 int verify_peer)
271 {
272 #ifdef CONFIG_TLS_INTERNAL_SERVER
273 if (conn->server)
274 return tlsv1_server_set_verify(conn->server, verify_peer);
275 #endif /* CONFIG_TLS_INTERNAL_SERVER */
276 return -1;
277 }
278
tls_connection_get_random(void * tls_ctx,struct tls_connection * conn,struct tls_random * data)279 int tls_connection_get_random(void *tls_ctx, struct tls_connection *conn,
280 struct tls_random *data)
281 {
282 #ifdef CONFIG_TLS_INTERNAL_CLIENT
283 if (conn->client)
284 return tlsv1_client_get_random(conn->client, data);
285 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
286 #ifdef CONFIG_TLS_INTERNAL_SERVER
287 if (conn->server)
288 return tlsv1_server_get_random(conn->server, data);
289 #endif /* CONFIG_TLS_INTERNAL_SERVER */
290 return -1;
291 }
292
tls_get_keyblock_size(struct tls_connection * conn)293 static int tls_get_keyblock_size(struct tls_connection *conn)
294 {
295 #ifdef CONFIG_TLS_INTERNAL_CLIENT
296 if (conn->client)
297 return tlsv1_client_get_keyblock_size(conn->client);
298 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
299 #ifdef CONFIG_TLS_INTERNAL_SERVER
300 if (conn->server)
301 return tlsv1_server_get_keyblock_size(conn->server);
302 #endif /* CONFIG_TLS_INTERNAL_SERVER */
303 return -1;
304 }
305
tls_connection_prf(void * tls_ctx,struct tls_connection * conn,const char * label,int server_random_first,int skip_keyblock,u8 * out,size_t out_len)306 static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
307 const char *label, int server_random_first,
308 int skip_keyblock, u8 *out, size_t out_len)
309 {
310 int ret = -1, skip = 0;
311 u8 *tmp_out = NULL;
312 u8 *_out = out;
313
314 if (skip_keyblock) {
315 skip = tls_get_keyblock_size(conn);
316 if (skip < 0)
317 return -1;
318 tmp_out = os_malloc(skip + out_len);
319 if (!tmp_out)
320 return -1;
321 _out = tmp_out;
322 }
323 #ifdef CONFIG_TLS_INTERNAL_CLIENT
324 if (conn->client) {
325 ret = tlsv1_client_prf(conn->client, label,
326 server_random_first,
327 out, out_len);
328 }
329 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
330 #ifdef CONFIG_TLS_INTERNAL_SERVER
331 if (conn->server) {
332 ret = tlsv1_server_prf(conn->server, label,
333 server_random_first,
334 out, out_len);
335 }
336 #endif /* CONFIG_TLS_INTERNAL_SERVER */
337 if (ret == 0 && skip_keyblock)
338 os_memcpy(out, _out + skip, out_len);
339 wpa_bin_clear_free(tmp_out, skip);
340
341 return ret;
342 }
343
tls_connection_export_key(void * tls_ctx,struct tls_connection * conn,const char * label,u8 * out,size_t out_len)344 int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
345 const char *label, u8 *out, size_t out_len)
346 {
347 return tls_connection_prf(tls_ctx, conn, label, 0, 0, out, out_len);
348 }
349
tls_connection_handshake(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)350 struct wpabuf * tls_connection_handshake(void *tls_ctx,
351 struct tls_connection *conn,
352 const struct wpabuf *in_data,
353 struct wpabuf **appl_data)
354 {
355 return tls_connection_handshake2(tls_ctx, conn, in_data, appl_data,
356 NULL);
357 }
358
359
tls_connection_handshake2(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data,int * need_more_data)360 struct wpabuf * tls_connection_handshake2(void *tls_ctx,
361 struct tls_connection *conn,
362 const struct wpabuf *in_data,
363 struct wpabuf **appl_data,
364 int *need_more_data)
365 {
366 #ifdef CONFIG_TLS_INTERNAL_CLIENT
367 u8 *res, *ad;
368 size_t res_len, ad_len;
369 struct wpabuf *out;
370
371 if (conn->client == NULL)
372 return NULL;
373
374 ad = NULL;
375 res = tlsv1_client_handshake(conn->client,
376 in_data ? wpabuf_head(in_data) : NULL,
377 in_data ? wpabuf_len(in_data) : 0,
378 &res_len, &ad, &ad_len, need_more_data);
379 if (res == NULL) {
380 return NULL;
381 }
382 out = wpabuf_alloc_ext_data(res, res_len);
383 if (out == NULL) {
384 os_free(res);
385 os_free(ad);
386 return NULL;
387 }
388 if (appl_data) {
389 if (ad) {
390 *appl_data = wpabuf_alloc_ext_data(ad, ad_len);
391 if (*appl_data == NULL)
392 os_free(ad);
393 } else
394 *appl_data = NULL;
395 } else
396 os_free(ad);
397
398 return out;
399 #else /* CONFIG_TLS_INTERNAL_CLIENT */
400 return NULL;
401 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
402 }
403
404
tls_connection_server_handshake(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)405 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
406 struct tls_connection *conn,
407 const struct wpabuf *in_data,
408 struct wpabuf **appl_data)
409 {
410 #ifdef CONFIG_TLS_INTERNAL_SERVER
411 u8 *res;
412 size_t res_len;
413 struct wpabuf *out;
414
415 if (conn->server == NULL)
416 return NULL;
417
418 if (appl_data)
419 *appl_data = NULL;
420
421 res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data),
422 wpabuf_len(in_data), &res_len);
423 if (res == NULL && tlsv1_server_established(conn->server))
424 return wpabuf_alloc(0);
425 if (res == NULL)
426 return NULL;
427 out = wpabuf_alloc_ext_data(res, res_len);
428 if (out == NULL) {
429 os_free(res);
430 return NULL;
431 }
432
433 return out;
434 #else /* CONFIG_TLS_INTERNAL_SERVER */
435 return NULL;
436 #endif /* CONFIG_TLS_INTERNAL_SERVER */
437 }
438
439
tls_connection_encrypt(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data)440 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
441 struct tls_connection *conn,
442 const struct wpabuf *in_data)
443 {
444 #ifdef CONFIG_TLS_INTERNAL_CLIENT
445 if (conn->client) {
446 struct wpabuf *buf;
447 int res;
448 buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
449 if (buf == NULL)
450 return NULL;
451 res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data),
452 wpabuf_len(in_data),
453 wpabuf_mhead(buf),
454 wpabuf_size(buf));
455 if (res < 0) {
456 wpabuf_free(buf);
457 return NULL;
458 }
459 wpabuf_put(buf, res);
460 return buf;
461 }
462 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
463 #ifdef CONFIG_TLS_INTERNAL_SERVER
464 if (conn->server) {
465 struct wpabuf *buf;
466 int res;
467 buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
468 if (buf == NULL)
469 return NULL;
470 res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data),
471 wpabuf_len(in_data),
472 wpabuf_mhead(buf),
473 wpabuf_size(buf));
474 if (res < 0) {
475 wpabuf_free(buf);
476 return NULL;
477 }
478 wpabuf_put(buf, res);
479 return buf;
480 }
481 #endif /* CONFIG_TLS_INTERNAL_SERVER */
482 return NULL;
483 }
484
485
tls_connection_decrypt(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data)486 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
487 struct tls_connection *conn,
488 const struct wpabuf *in_data)
489 {
490 return tls_connection_decrypt2(tls_ctx, conn, in_data, NULL);
491 }
492
493
tls_connection_decrypt2(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,int * need_more_data)494 struct wpabuf * tls_connection_decrypt2(void *tls_ctx,
495 struct tls_connection *conn,
496 const struct wpabuf *in_data,
497 int *need_more_data)
498 {
499 if (need_more_data)
500 *need_more_data = 0;
501
502 #ifdef CONFIG_TLS_INTERNAL_CLIENT
503 if (conn->client) {
504 return tlsv1_client_decrypt(conn->client, wpabuf_head(in_data),
505 wpabuf_len(in_data),
506 need_more_data);
507 }
508 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
509 #ifdef CONFIG_TLS_INTERNAL_SERVER
510 if (conn->server) {
511 struct wpabuf *buf;
512 int res;
513 buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
514 if (buf == NULL)
515 return NULL;
516 res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data),
517 wpabuf_len(in_data),
518 wpabuf_mhead(buf),
519 wpabuf_size(buf));
520 if (res < 0) {
521 wpabuf_free(buf);
522 return NULL;
523 }
524 wpabuf_put(buf, res);
525 return buf;
526 }
527 #endif /* CONFIG_TLS_INTERNAL_SERVER */
528 return NULL;
529 }
530
531
tls_connection_resumed(void * tls_ctx,struct tls_connection * conn)532 int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
533 {
534 #ifdef CONFIG_TLS_INTERNAL_CLIENT
535 if (conn->client)
536 return tlsv1_client_resumed(conn->client);
537 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
538 #ifdef CONFIG_TLS_INTERNAL_SERVER
539 if (conn->server)
540 return tlsv1_server_resumed(conn->server);
541 #endif /* CONFIG_TLS_INTERNAL_SERVER */
542 return -1;
543 }
544
545
tls_connection_set_cipher_list(void * tls_ctx,struct tls_connection * conn,u8 * ciphers)546 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
547 u8 *ciphers)
548 {
549 #ifdef CONFIG_TLS_INTERNAL_CLIENT
550 if (conn->client)
551 return tlsv1_client_set_cipher_list(conn->client, ciphers);
552 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
553 #ifdef CONFIG_TLS_INTERNAL_SERVER
554 if (conn->server)
555 return tlsv1_server_set_cipher_list(conn->server, ciphers);
556 #endif /* CONFIG_TLS_INTERNAL_SERVER */
557 return -1;
558 }
559
560
tls_get_cipher(void * tls_ctx,struct tls_connection * conn,char * buf,size_t buflen)561 int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
562 char *buf, size_t buflen)
563 {
564 if (conn == NULL)
565 return -1;
566 #ifdef CONFIG_TLS_INTERNAL_CLIENT
567 if (conn->client)
568 return tlsv1_client_get_cipher(conn->client, buf, buflen);
569 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
570 #ifdef CONFIG_TLS_INTERNAL_SERVER
571 if (conn->server)
572 return tlsv1_server_get_cipher(conn->server, buf, buflen);
573 #endif /* CONFIG_TLS_INTERNAL_SERVER */
574 return -1;
575 }
576
577
tls_connection_enable_workaround(void * tls_ctx,struct tls_connection * conn)578 int tls_connection_enable_workaround(void *tls_ctx,
579 struct tls_connection *conn)
580 {
581 return -1;
582 }
583
584
tls_connection_client_hello_ext(void * tls_ctx,struct tls_connection * conn,int ext_type,const u8 * data,size_t data_len)585 int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
586 int ext_type, const u8 *data,
587 size_t data_len)
588 {
589 #ifdef CONFIG_TLS_INTERNAL_CLIENT
590 if (conn->client) {
591 return tlsv1_client_hello_ext(conn->client, ext_type,
592 data, data_len);
593 }
594 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
595 return -1;
596 }
597
598
tls_connection_get_failed(void * tls_ctx,struct tls_connection * conn)599 int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
600 {
601 return 0;
602 }
603
604
tls_connection_get_read_alerts(void * tls_ctx,struct tls_connection * conn)605 int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
606 {
607 return 0;
608 }
609
610
tls_connection_get_write_alerts(void * tls_ctx,struct tls_connection * conn)611 int tls_connection_get_write_alerts(void *tls_ctx,
612 struct tls_connection *conn)
613 {
614 return 0;
615 }
616
tls_capabilities(void * tls_ctx)617 unsigned int tls_capabilities(void *tls_ctx)
618 {
619 return 0;
620 }
621
tls_connection_set_session_ticket_cb(void * tls_ctx,struct tls_connection * conn,tls_session_ticket_cb cb,void * ctx)622 int tls_connection_set_session_ticket_cb(void *tls_ctx,
623 struct tls_connection *conn,
624 tls_session_ticket_cb cb,
625 void *ctx)
626 {
627 #ifdef CONFIG_TLS_INTERNAL_CLIENT
628 if (conn->client) {
629 tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx);
630 return 0;
631 }
632 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
633 #ifdef CONFIG_TLS_INTERNAL_SERVER
634 if (conn->server) {
635 tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx);
636 return 0;
637 }
638 #endif /* CONFIG_TLS_INTERNAL_SERVER */
639 return -1;
640 }
641