xref: /qemu/crypto/tlscreds.c (revision 0e1d02452bf2c3486406dd48524a5b1de3c0eba8)
1a090187dSDaniel P. Berrange /*
2a090187dSDaniel P. Berrange  * QEMU crypto TLS credential support
3a090187dSDaniel P. Berrange  *
4a090187dSDaniel P. Berrange  * Copyright (c) 2015 Red Hat, Inc.
5a090187dSDaniel P. Berrange  *
6a090187dSDaniel P. Berrange  * This library is free software; you can redistribute it and/or
7a090187dSDaniel P. Berrange  * modify it under the terms of the GNU Lesser General Public
8a090187dSDaniel P. Berrange  * License as published by the Free Software Foundation; either
9a090187dSDaniel P. Berrange  * version 2 of the License, or (at your option) any later version.
10a090187dSDaniel P. Berrange  *
11a090187dSDaniel P. Berrange  * This library is distributed in the hope that it will be useful,
12a090187dSDaniel P. Berrange  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13a090187dSDaniel P. Berrange  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14a090187dSDaniel P. Berrange  * Lesser General Public License for more details.
15a090187dSDaniel P. Berrange  *
16a090187dSDaniel P. Berrange  * You should have received a copy of the GNU Lesser General Public
17a090187dSDaniel P. Berrange  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18a090187dSDaniel P. Berrange  *
19a090187dSDaniel P. Berrange  */
20a090187dSDaniel P. Berrange 
21a090187dSDaniel P. Berrange #include "crypto/tlscredspriv.h"
22a090187dSDaniel P. Berrange #include "trace.h"
23a090187dSDaniel P. Berrange 
24a090187dSDaniel P. Berrange #define DH_BITS 2048
25a090187dSDaniel P. Berrange 
26a090187dSDaniel P. Berrange #ifdef CONFIG_GNUTLS
27a090187dSDaniel P. Berrange int
28a090187dSDaniel P. Berrange qcrypto_tls_creds_get_dh_params_file(QCryptoTLSCreds *creds,
29a090187dSDaniel P. Berrange                                      const char *filename,
30a090187dSDaniel P. Berrange                                      gnutls_dh_params_t *dh_params,
31a090187dSDaniel P. Berrange                                      Error **errp)
32a090187dSDaniel P. Berrange {
33a090187dSDaniel P. Berrange     int ret;
34a090187dSDaniel P. Berrange 
35a090187dSDaniel P. Berrange     trace_qcrypto_tls_creds_load_dh(creds, filename ? filename : "<generated>");
36a090187dSDaniel P. Berrange 
37a090187dSDaniel P. Berrange     if (filename == NULL) {
38a090187dSDaniel P. Berrange         ret = gnutls_dh_params_init(dh_params);
39a090187dSDaniel P. Berrange         if (ret < 0) {
40a090187dSDaniel P. Berrange             error_setg(errp, "Unable to initialize DH parameters: %s",
41a090187dSDaniel P. Berrange                        gnutls_strerror(ret));
42a090187dSDaniel P. Berrange             return -1;
43a090187dSDaniel P. Berrange         }
44a090187dSDaniel P. Berrange         ret = gnutls_dh_params_generate2(*dh_params, DH_BITS);
45a090187dSDaniel P. Berrange         if (ret < 0) {
46a090187dSDaniel P. Berrange             gnutls_dh_params_deinit(*dh_params);
47a090187dSDaniel P. Berrange             *dh_params = NULL;
48a090187dSDaniel P. Berrange             error_setg(errp, "Unable to generate DH parameters: %s",
49a090187dSDaniel P. Berrange                        gnutls_strerror(ret));
50a090187dSDaniel P. Berrange             return -1;
51a090187dSDaniel P. Berrange         }
52a090187dSDaniel P. Berrange     } else {
53a090187dSDaniel P. Berrange         GError *gerr = NULL;
54a090187dSDaniel P. Berrange         gchar *contents;
55a090187dSDaniel P. Berrange         gsize len;
56a090187dSDaniel P. Berrange         gnutls_datum_t data;
57a090187dSDaniel P. Berrange         if (!g_file_get_contents(filename,
58a090187dSDaniel P. Berrange                                  &contents,
59a090187dSDaniel P. Berrange                                  &len,
60a090187dSDaniel P. Berrange                                  &gerr)) {
61a090187dSDaniel P. Berrange 
62a090187dSDaniel P. Berrange             error_setg(errp, "%s", gerr->message);
63a090187dSDaniel P. Berrange             g_error_free(gerr);
64a090187dSDaniel P. Berrange             return -1;
65a090187dSDaniel P. Berrange         }
66a090187dSDaniel P. Berrange         data.data = (unsigned char *)contents;
67a090187dSDaniel P. Berrange         data.size = len;
68a090187dSDaniel P. Berrange         ret = gnutls_dh_params_init(dh_params);
69a090187dSDaniel P. Berrange         if (ret < 0) {
70a090187dSDaniel P. Berrange             g_free(contents);
71a090187dSDaniel P. Berrange             error_setg(errp, "Unable to initialize DH parameters: %s",
72a090187dSDaniel P. Berrange                        gnutls_strerror(ret));
73a090187dSDaniel P. Berrange             return -1;
74a090187dSDaniel P. Berrange         }
75a090187dSDaniel P. Berrange         ret = gnutls_dh_params_import_pkcs3(*dh_params,
76a090187dSDaniel P. Berrange                                             &data,
77a090187dSDaniel P. Berrange                                             GNUTLS_X509_FMT_PEM);
78a090187dSDaniel P. Berrange         g_free(contents);
79a090187dSDaniel P. Berrange         if (ret < 0) {
80a090187dSDaniel P. Berrange             gnutls_dh_params_deinit(*dh_params);
81a090187dSDaniel P. Berrange             *dh_params = NULL;
82a090187dSDaniel P. Berrange             error_setg(errp, "Unable to load DH parameters from %s: %s",
83a090187dSDaniel P. Berrange                        filename, gnutls_strerror(ret));
84a090187dSDaniel P. Berrange             return -1;
85a090187dSDaniel P. Berrange         }
86a090187dSDaniel P. Berrange     }
87a090187dSDaniel P. Berrange 
88a090187dSDaniel P. Berrange     return 0;
89a090187dSDaniel P. Berrange }
90a090187dSDaniel P. Berrange 
91a090187dSDaniel P. Berrange 
92a090187dSDaniel P. Berrange int
93a090187dSDaniel P. Berrange qcrypto_tls_creds_get_path(QCryptoTLSCreds *creds,
94a090187dSDaniel P. Berrange                            const char *filename,
95a090187dSDaniel P. Berrange                            bool required,
96a090187dSDaniel P. Berrange                            char **cred,
97a090187dSDaniel P. Berrange                            Error **errp)
98a090187dSDaniel P. Berrange {
99a090187dSDaniel P. Berrange     struct stat sb;
100a090187dSDaniel P. Berrange     int ret = -1;
101a090187dSDaniel P. Berrange 
102a090187dSDaniel P. Berrange     if (!creds->dir) {
103a090187dSDaniel P. Berrange         if (required) {
104a090187dSDaniel P. Berrange             error_setg(errp, "Missing 'dir' property value");
105a090187dSDaniel P. Berrange             return -1;
106a090187dSDaniel P. Berrange         } else {
107a090187dSDaniel P. Berrange             return 0;
108a090187dSDaniel P. Berrange         }
109a090187dSDaniel P. Berrange     }
110a090187dSDaniel P. Berrange 
111a090187dSDaniel P. Berrange     *cred = g_strdup_printf("%s/%s", creds->dir, filename);
112a090187dSDaniel P. Berrange 
113a090187dSDaniel P. Berrange     if (stat(*cred, &sb) < 0) {
114a090187dSDaniel P. Berrange         if (errno == ENOENT && !required) {
115a090187dSDaniel P. Berrange             ret = 0;
116a090187dSDaniel P. Berrange         } else {
117a090187dSDaniel P. Berrange             error_setg_errno(errp, errno,
118a090187dSDaniel P. Berrange                              "Unable to access credentials %s",
119a090187dSDaniel P. Berrange                              *cred);
120a090187dSDaniel P. Berrange         }
121a090187dSDaniel P. Berrange         g_free(*cred);
122a090187dSDaniel P. Berrange         *cred = NULL;
123a090187dSDaniel P. Berrange         goto cleanup;
124a090187dSDaniel P. Berrange     }
125a090187dSDaniel P. Berrange 
126a090187dSDaniel P. Berrange     ret = 0;
127a090187dSDaniel P. Berrange  cleanup:
128*0e1d0245SDaniel P. Berrange     trace_qcrypto_tls_creds_get_path(creds, filename,
129*0e1d0245SDaniel P. Berrange                                      *cred ? *cred : "<none>");
130a090187dSDaniel P. Berrange     return ret;
131a090187dSDaniel P. Berrange }
132a090187dSDaniel P. Berrange 
133a090187dSDaniel P. Berrange 
134a090187dSDaniel P. Berrange #endif /* ! CONFIG_GNUTLS */
135a090187dSDaniel P. Berrange 
136a090187dSDaniel P. Berrange 
137a090187dSDaniel P. Berrange static void
138a090187dSDaniel P. Berrange qcrypto_tls_creds_prop_set_verify(Object *obj,
139a090187dSDaniel P. Berrange                                   bool value,
140a090187dSDaniel P. Berrange                                   Error **errp G_GNUC_UNUSED)
141a090187dSDaniel P. Berrange {
142a090187dSDaniel P. Berrange     QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
143a090187dSDaniel P. Berrange 
144a090187dSDaniel P. Berrange     creds->verifyPeer = value;
145a090187dSDaniel P. Berrange }
146a090187dSDaniel P. Berrange 
147a090187dSDaniel P. Berrange 
148a090187dSDaniel P. Berrange static bool
149a090187dSDaniel P. Berrange qcrypto_tls_creds_prop_get_verify(Object *obj,
150a090187dSDaniel P. Berrange                                   Error **errp G_GNUC_UNUSED)
151a090187dSDaniel P. Berrange {
152a090187dSDaniel P. Berrange     QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
153a090187dSDaniel P. Berrange 
154a090187dSDaniel P. Berrange     return creds->verifyPeer;
155a090187dSDaniel P. Berrange }
156a090187dSDaniel P. Berrange 
157a090187dSDaniel P. Berrange 
158a090187dSDaniel P. Berrange static void
159a090187dSDaniel P. Berrange qcrypto_tls_creds_prop_set_dir(Object *obj,
160a090187dSDaniel P. Berrange                                const char *value,
161a090187dSDaniel P. Berrange                                Error **errp G_GNUC_UNUSED)
162a090187dSDaniel P. Berrange {
163a090187dSDaniel P. Berrange     QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
164a090187dSDaniel P. Berrange 
165a090187dSDaniel P. Berrange     creds->dir = g_strdup(value);
166a090187dSDaniel P. Berrange }
167a090187dSDaniel P. Berrange 
168a090187dSDaniel P. Berrange 
169a090187dSDaniel P. Berrange static char *
170a090187dSDaniel P. Berrange qcrypto_tls_creds_prop_get_dir(Object *obj,
171a090187dSDaniel P. Berrange                                Error **errp G_GNUC_UNUSED)
172a090187dSDaniel P. Berrange {
173a090187dSDaniel P. Berrange     QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
174a090187dSDaniel P. Berrange 
175a090187dSDaniel P. Berrange     return g_strdup(creds->dir);
176a090187dSDaniel P. Berrange }
177a090187dSDaniel P. Berrange 
178a090187dSDaniel P. Berrange 
179a090187dSDaniel P. Berrange static void
180a090187dSDaniel P. Berrange qcrypto_tls_creds_prop_set_endpoint(Object *obj,
181a090187dSDaniel P. Berrange                                     int value,
182a090187dSDaniel P. Berrange                                     Error **errp G_GNUC_UNUSED)
183a090187dSDaniel P. Berrange {
184a090187dSDaniel P. Berrange     QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
185a090187dSDaniel P. Berrange 
186a090187dSDaniel P. Berrange     creds->endpoint = value;
187a090187dSDaniel P. Berrange }
188a090187dSDaniel P. Berrange 
189a090187dSDaniel P. Berrange 
190a090187dSDaniel P. Berrange static int
191a090187dSDaniel P. Berrange qcrypto_tls_creds_prop_get_endpoint(Object *obj,
192a090187dSDaniel P. Berrange                                     Error **errp G_GNUC_UNUSED)
193a090187dSDaniel P. Berrange {
194a090187dSDaniel P. Berrange     QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
195a090187dSDaniel P. Berrange 
196a090187dSDaniel P. Berrange     return creds->endpoint;
197a090187dSDaniel P. Berrange }
198a090187dSDaniel P. Berrange 
199a090187dSDaniel P. Berrange 
200a090187dSDaniel P. Berrange static void
201a090187dSDaniel P. Berrange qcrypto_tls_creds_init(Object *obj)
202a090187dSDaniel P. Berrange {
203a090187dSDaniel P. Berrange     QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
204a090187dSDaniel P. Berrange 
205a090187dSDaniel P. Berrange     creds->verifyPeer = true;
206a090187dSDaniel P. Berrange 
207a090187dSDaniel P. Berrange     object_property_add_bool(obj, "verify-peer",
208a090187dSDaniel P. Berrange                              qcrypto_tls_creds_prop_get_verify,
209a090187dSDaniel P. Berrange                              qcrypto_tls_creds_prop_set_verify,
210a090187dSDaniel P. Berrange                              NULL);
211a090187dSDaniel P. Berrange     object_property_add_str(obj, "dir",
212a090187dSDaniel P. Berrange                             qcrypto_tls_creds_prop_get_dir,
213a090187dSDaniel P. Berrange                             qcrypto_tls_creds_prop_set_dir,
214a090187dSDaniel P. Berrange                             NULL);
215a090187dSDaniel P. Berrange     object_property_add_enum(obj, "endpoint",
216a090187dSDaniel P. Berrange                              "QCryptoTLSCredsEndpoint",
217a090187dSDaniel P. Berrange                              QCryptoTLSCredsEndpoint_lookup,
218a090187dSDaniel P. Berrange                              qcrypto_tls_creds_prop_get_endpoint,
219a090187dSDaniel P. Berrange                              qcrypto_tls_creds_prop_set_endpoint,
220a090187dSDaniel P. Berrange                              NULL);
221a090187dSDaniel P. Berrange }
222a090187dSDaniel P. Berrange 
223a090187dSDaniel P. Berrange 
224a090187dSDaniel P. Berrange static void
225a090187dSDaniel P. Berrange qcrypto_tls_creds_finalize(Object *obj)
226a090187dSDaniel P. Berrange {
227a090187dSDaniel P. Berrange     QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
228a090187dSDaniel P. Berrange 
229a090187dSDaniel P. Berrange     g_free(creds->dir);
230a090187dSDaniel P. Berrange }
231a090187dSDaniel P. Berrange 
232a090187dSDaniel P. Berrange 
233a090187dSDaniel P. Berrange static const TypeInfo qcrypto_tls_creds_info = {
234a090187dSDaniel P. Berrange     .parent = TYPE_OBJECT,
235a090187dSDaniel P. Berrange     .name = TYPE_QCRYPTO_TLS_CREDS,
236a090187dSDaniel P. Berrange     .instance_size = sizeof(QCryptoTLSCreds),
237a090187dSDaniel P. Berrange     .instance_init = qcrypto_tls_creds_init,
238a090187dSDaniel P. Berrange     .instance_finalize = qcrypto_tls_creds_finalize,
239a090187dSDaniel P. Berrange     .class_size = sizeof(QCryptoTLSCredsClass),
240a090187dSDaniel P. Berrange     .abstract = true,
241a090187dSDaniel P. Berrange };
242a090187dSDaniel P. Berrange 
243a090187dSDaniel P. Berrange 
244a090187dSDaniel P. Berrange static void
245a090187dSDaniel P. Berrange qcrypto_tls_creds_register_types(void)
246a090187dSDaniel P. Berrange {
247a090187dSDaniel P. Berrange     type_register_static(&qcrypto_tls_creds_info);
248a090187dSDaniel P. Berrange }
249a090187dSDaniel P. Berrange 
250a090187dSDaniel P. Berrange 
251a090187dSDaniel P. Berrange type_init(qcrypto_tls_creds_register_types);
252