Disconnect hostapd from building in base
[dragonfly.git] / contrib / hostapd / 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 };
32
33
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
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
74 int tls_get_errors(void *tls_ctx)
75 {
76         return 0;
77 }
78
79
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
551 int tls_connection_enable_workaround(void *tls_ctx,
552                                      struct tls_connection *conn)
553 {
554         return -1;
555 }
556
557
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
572 int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
573 {
574         return 0;
575 }
576
577
578 int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
579 {
580         return 0;
581 }
582
583
584 int tls_connection_get_write_alerts(void *tls_ctx,
585                                     struct tls_connection *conn)
586 {
587         return 0;
588 }
589
590
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
606 unsigned int tls_capabilities(void *tls_ctx)
607 {
608         return 0;
609 }
610
611
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 }