]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa/src/crypto/tls_internal.c
Add ELF Tool Chain's ar(1) and elfdump(1) to contrib
[FreeBSD/FreeBSD.git] / contrib / wpa / src / crypto / tls_internal.c
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         struct tls_global *global;
32 };
33
34
35 void * 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
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
75 int tls_get_errors(void *tls_ctx)
76 {
77         return 0;
78 }
79
80
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 = os_zalloc(sizeof(*conn));
87         if (conn == NULL)
88                 return NULL;
89         conn->global = global;
90
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
114 #ifdef CONFIG_TESTING_OPTIONS
115 #ifdef CONFIG_TLS_INTERNAL_SERVER
116 void 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
125 void 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
136 void 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
152 int 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
166 int 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
180 int 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
193         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
208         if (params->domain_match) {
209                 wpa_printf(MSG_INFO, "TLS: domain_match not supported");
210                 return -1;
211         }
212
213         if (params->openssl_ciphers) {
214                 wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
215                 return -1;
216         }
217
218         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
257         tlsv1_client_set_time_checks(
258                 conn->client, !(params->flags & TLS_CONN_DISABLE_TIME_CHECKS));
259
260         return 0;
261 #else /* CONFIG_TLS_INTERNAL_CLIENT */
262         return -1;
263 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
264 }
265
266
267 int 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
317 int 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
325 int 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
336 int 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
351 int 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
373 struct wpabuf * tls_connection_handshake(void *tls_ctx,
374                                          struct tls_connection *conn,
375                                          const struct wpabuf *in_data,
376                                          struct wpabuf **appl_data)
377 {
378         return tls_connection_handshake2(tls_ctx, conn, in_data, appl_data,
379                                          NULL);
380 }
381
382
383 struct 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 {
389 #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,
401                                      &res_len, &ad, &ad_len, need_more_data);
402         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
427 struct 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
462 struct 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
508 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
509                                        struct tls_connection *conn,
510                                        const struct wpabuf *in_data)
511 {
512         return tls_connection_decrypt2(tls_ctx, conn, in_data, NULL);
513 }
514
515
516 struct 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
524 #ifdef CONFIG_TLS_INTERNAL_CLIENT
525         if (conn->client) {
526                 return tlsv1_client_decrypt(conn->client, wpabuf_head(in_data),
527                                             wpabuf_len(in_data),
528                                             need_more_data);
529         }
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
554 int 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
568 int 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
583 int 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
600 int tls_connection_enable_workaround(void *tls_ctx,
601                                      struct tls_connection *conn)
602 {
603         return -1;
604 }
605
606
607 int 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
621 int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
622 {
623         return 0;
624 }
625
626
627 int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
628 {
629         return 0;
630 }
631
632
633 int tls_connection_get_write_alerts(void *tls_ctx,
634                                     struct tls_connection *conn)
635 {
636         return 0;
637 }
638
639
640 int 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
655 unsigned int tls_capabilities(void *tls_ctx)
656 {
657         return 0;
658 }
659
660
661 int 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 }
680
681
682 int tls_get_library_version(char *buf, size_t buf_len)
683 {
684         return os_snprintf(buf, buf_len, "internal");
685 }