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