1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "crypto/tlscredsx509.h"
23#include "tlscredspriv.h"
24#include "crypto/secret.h"
25#include "qapi/error.h"
26#include "qemu/module.h"
27#include "qom/object_interfaces.h"
28#include "trace.h"
29
30
31#ifdef CONFIG_GNUTLS
32
33#include <gnutls/gnutls.h>
34#include <gnutls/x509.h>
35
36
37static int
38qcrypto_tls_creds_check_cert_times(gnutls_x509_crt_t cert,
39 const char *certFile,
40 bool isServer,
41 bool isCA,
42 Error **errp)
43{
44 time_t now = time(NULL);
45
46 if (now == ((time_t)-1)) {
47 error_setg_errno(errp, errno, "cannot get current time");
48 return -1;
49 }
50
51 if (gnutls_x509_crt_get_expiration_time(cert) < now) {
52 error_setg(errp,
53 (isCA ?
54 "The CA certificate %s has expired" :
55 (isServer ?
56 "The server certificate %s has expired" :
57 "The client certificate %s has expired")),
58 certFile);
59 return -1;
60 }
61
62 if (gnutls_x509_crt_get_activation_time(cert) > now) {
63 error_setg(errp,
64 (isCA ?
65 "The CA certificate %s is not yet active" :
66 (isServer ?
67 "The server certificate %s is not yet active" :
68 "The client certificate %s is not yet active")),
69 certFile);
70 return -1;
71 }
72
73 return 0;
74}
75
76
77static int
78qcrypto_tls_creds_check_cert_basic_constraints(QCryptoTLSCredsX509 *creds,
79 gnutls_x509_crt_t cert,
80 const char *certFile,
81 bool isServer,
82 bool isCA,
83 Error **errp)
84{
85 int status;
86
87 status = gnutls_x509_crt_get_basic_constraints(cert, NULL, NULL, NULL);
88 trace_qcrypto_tls_creds_x509_check_basic_constraints(
89 creds, certFile, status);
90
91 if (status > 0) {
92 if (!isCA) {
93 error_setg(errp, isServer ?
94 "The certificate %s basic constraints show a CA, "
95 "but we need one for a server" :
96 "The certificate %s basic constraints show a CA, "
97 "but we need one for a client",
98 certFile);
99 return -1;
100 }
101 } else if (status == 0) {
102 if (isCA) {
103 error_setg(errp,
104 "The certificate %s basic constraints do not "
105 "show a CA",
106 certFile);
107 return -1;
108 }
109 } else if (status == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
110
111 if (isCA) {
112 error_setg(errp,
113 "The certificate %s is missing basic constraints "
114 "for a CA",
115 certFile);
116 return -1;
117 }
118 } else {
119 error_setg(errp,
120 "Unable to query certificate %s basic constraints: %s",
121 certFile, gnutls_strerror(status));
122 return -1;
123 }
124
125 return 0;
126}
127
128
129static int
130qcrypto_tls_creds_check_cert_key_usage(QCryptoTLSCredsX509 *creds,
131 gnutls_x509_crt_t cert,
132 const char *certFile,
133 bool isCA,
134 Error **errp)
135{
136 int status;
137 unsigned int usage = 0;
138 unsigned int critical = 0;
139
140 status = gnutls_x509_crt_get_key_usage(cert, &usage, &critical);
141 trace_qcrypto_tls_creds_x509_check_key_usage(
142 creds, certFile, status, usage, critical);
143
144 if (status < 0) {
145 if (status == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
146 usage = isCA ? GNUTLS_KEY_KEY_CERT_SIGN :
147 GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT;
148 } else {
149 error_setg(errp,
150 "Unable to query certificate %s key usage: %s",
151 certFile, gnutls_strerror(status));
152 return -1;
153 }
154 }
155
156 if (isCA) {
157 if (!(usage & GNUTLS_KEY_KEY_CERT_SIGN)) {
158 if (critical) {
159 error_setg(errp,
160 "Certificate %s usage does not permit "
161 "certificate signing", certFile);
162 return -1;
163 }
164 }
165 } else {
166 if (!(usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
167 if (critical) {
168 error_setg(errp,
169 "Certificate %s usage does not permit digital "
170 "signature", certFile);
171 return -1;
172 }
173 }
174 if (!(usage & GNUTLS_KEY_KEY_ENCIPHERMENT)) {
175 if (critical) {
176 error_setg(errp,
177 "Certificate %s usage does not permit key "
178 "encipherment", certFile);
179 return -1;
180 }
181 }
182 }
183
184 return 0;
185}
186
187
188static int
189qcrypto_tls_creds_check_cert_key_purpose(QCryptoTLSCredsX509 *creds,
190 gnutls_x509_crt_t cert,
191 const char *certFile,
192 bool isServer,
193 Error **errp)
194{
195 int status;
196 size_t i;
197 unsigned int purposeCritical;
198 unsigned int critical;
199 char *buffer = NULL;
200 size_t size;
201 bool allowClient = false, allowServer = false;
202
203 critical = 0;
204 for (i = 0; ; i++) {
205 size = 0;
206 status = gnutls_x509_crt_get_key_purpose_oid(cert, i, buffer,
207 &size, NULL);
208
209 if (status == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
210
211
212
213 if (i == 0) {
214 allowServer = allowClient = true;
215 }
216 break;
217 }
218 if (status != GNUTLS_E_SHORT_MEMORY_BUFFER) {
219 error_setg(errp,
220 "Unable to query certificate %s key purpose: %s",
221 certFile, gnutls_strerror(status));
222 return -1;
223 }
224
225 buffer = g_new0(char, size);
226
227 status = gnutls_x509_crt_get_key_purpose_oid(cert, i, buffer,
228 &size, &purposeCritical);
229
230 if (status < 0) {
231 trace_qcrypto_tls_creds_x509_check_key_purpose(
232 creds, certFile, status, "<none>", purposeCritical);
233 g_free(buffer);
234 error_setg(errp,
235 "Unable to query certificate %s key purpose: %s",
236 certFile, gnutls_strerror(status));
237 return -1;
238 }
239 trace_qcrypto_tls_creds_x509_check_key_purpose(
240 creds, certFile, status, buffer, purposeCritical);
241 if (purposeCritical) {
242 critical = true;
243 }
244
245 if (g_str_equal(buffer, GNUTLS_KP_TLS_WWW_SERVER)) {
246 allowServer = true;
247 } else if (g_str_equal(buffer, GNUTLS_KP_TLS_WWW_CLIENT)) {
248 allowClient = true;
249 } else if (g_str_equal(buffer, GNUTLS_KP_ANY)) {
250 allowServer = allowClient = true;
251 }
252
253 g_free(buffer);
254 buffer = NULL;
255 }
256
257 if (isServer) {
258 if (!allowServer) {
259 if (critical) {
260 error_setg(errp,
261 "Certificate %s purpose does not allow "
262 "use with a TLS server", certFile);
263 return -1;
264 }
265 }
266 } else {
267 if (!allowClient) {
268 if (critical) {
269 error_setg(errp,
270 "Certificate %s purpose does not allow use "
271 "with a TLS client", certFile);
272 return -1;
273 }
274 }
275 }
276
277 return 0;
278}
279
280
281static int
282qcrypto_tls_creds_check_cert(QCryptoTLSCredsX509 *creds,
283 gnutls_x509_crt_t cert,
284 const char *certFile,
285 bool isServer,
286 bool isCA,
287 Error **errp)
288{
289 if (qcrypto_tls_creds_check_cert_times(cert, certFile,
290 isServer, isCA,
291 errp) < 0) {
292 return -1;
293 }
294
295 if (qcrypto_tls_creds_check_cert_basic_constraints(creds,
296 cert, certFile,
297 isServer, isCA,
298 errp) < 0) {
299 return -1;
300 }
301
302 if (qcrypto_tls_creds_check_cert_key_usage(creds,
303 cert, certFile,
304 isCA, errp) < 0) {
305 return -1;
306 }
307
308 if (!isCA &&
309 qcrypto_tls_creds_check_cert_key_purpose(creds,
310 cert, certFile,
311 isServer, errp) < 0) {
312 return -1;
313 }
314
315 return 0;
316}
317
318
319static int
320qcrypto_tls_creds_check_cert_pair(gnutls_x509_crt_t cert,
321 const char *certFile,
322 gnutls_x509_crt_t *cacerts,
323 size_t ncacerts,
324 const char *cacertFile,
325 bool isServer,
326 Error **errp)
327{
328 unsigned int status;
329
330 if (gnutls_x509_crt_list_verify(&cert, 1,
331 cacerts, ncacerts,
332 NULL, 0,
333 0, &status) < 0) {
334 error_setg(errp, isServer ?
335 "Unable to verify server certificate %s against "
336 "CA certificate %s" :
337 "Unable to verify client certificate %s against "
338 "CA certificate %s",
339 certFile, cacertFile);
340 return -1;
341 }
342
343 if (status != 0) {
344 const char *reason = "Invalid certificate";
345
346 if (status & GNUTLS_CERT_INVALID) {
347 reason = "The certificate is not trusted";
348 }
349
350 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
351 reason = "The certificate hasn't got a known issuer";
352 }
353
354 if (status & GNUTLS_CERT_REVOKED) {
355 reason = "The certificate has been revoked";
356 }
357
358#ifndef GNUTLS_1_0_COMPAT
359 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
360 reason = "The certificate uses an insecure algorithm";
361 }
362#endif
363
364 error_setg(errp,
365 "Our own certificate %s failed validation against %s: %s",
366 certFile, cacertFile, reason);
367 return -1;
368 }
369
370 return 0;
371}
372
373
374static gnutls_x509_crt_t
375qcrypto_tls_creds_load_cert(QCryptoTLSCredsX509 *creds,
376 const char *certFile,
377 bool isServer,
378 Error **errp)
379{
380 gnutls_datum_t data;
381 gnutls_x509_crt_t cert = NULL;
382 g_autofree char *buf = NULL;
383 gsize buflen;
384 GError *gerr = NULL;
385 int ret = -1;
386 int err;
387
388 trace_qcrypto_tls_creds_x509_load_cert(creds, isServer, certFile);
389
390 err = gnutls_x509_crt_init(&cert);
391 if (err < 0) {
392 error_setg(errp, "Unable to initialize certificate: %s",
393 gnutls_strerror(err));
394 goto cleanup;
395 }
396
397 if (!g_file_get_contents(certFile, &buf, &buflen, &gerr)) {
398 error_setg(errp, "Cannot load CA cert list %s: %s",
399 certFile, gerr->message);
400 g_error_free(gerr);
401 goto cleanup;
402 }
403
404 data.data = (unsigned char *)buf;
405 data.size = strlen(buf);
406
407 err = gnutls_x509_crt_import(cert, &data, GNUTLS_X509_FMT_PEM);
408 if (err < 0) {
409 error_setg(errp, isServer ?
410 "Unable to import server certificate %s: %s" :
411 "Unable to import client certificate %s: %s",
412 certFile,
413 gnutls_strerror(err));
414 goto cleanup;
415 }
416
417 ret = 0;
418
419 cleanup:
420 if (ret != 0) {
421 gnutls_x509_crt_deinit(cert);
422 cert = NULL;
423 }
424 return cert;
425}
426
427
428static int
429qcrypto_tls_creds_load_ca_cert_list(QCryptoTLSCredsX509 *creds,
430 const char *certFile,
431 gnutls_x509_crt_t *certs,
432 unsigned int certMax,
433 size_t *ncerts,
434 Error **errp)
435{
436 gnutls_datum_t data;
437 g_autofree char *buf = NULL;
438 gsize buflen;
439 GError *gerr = NULL;
440
441 *ncerts = 0;
442 trace_qcrypto_tls_creds_x509_load_cert_list(creds, certFile);
443
444 if (!g_file_get_contents(certFile, &buf, &buflen, &gerr)) {
445 error_setg(errp, "Cannot load CA cert list %s: %s",
446 certFile, gerr->message);
447 g_error_free(gerr);
448 return -1;
449 }
450
451 data.data = (unsigned char *)buf;
452 data.size = strlen(buf);
453
454 if (gnutls_x509_crt_list_import(certs, &certMax, &data,
455 GNUTLS_X509_FMT_PEM, 0) < 0) {
456 error_setg(errp,
457 "Unable to import CA certificate list %s",
458 certFile);
459 return -1;
460 }
461 *ncerts = certMax;
462
463 return 0;
464}
465
466
467#define MAX_CERTS 16
468static int
469qcrypto_tls_creds_x509_sanity_check(QCryptoTLSCredsX509 *creds,
470 bool isServer,
471 const char *cacertFile,
472 const char *certFile,
473 Error **errp)
474{
475 gnutls_x509_crt_t cert = NULL;
476 gnutls_x509_crt_t cacerts[MAX_CERTS];
477 size_t ncacerts = 0;
478 size_t i;
479 int ret = -1;
480
481 memset(cacerts, 0, sizeof(cacerts));
482 if (certFile &&
483 access(certFile, R_OK) == 0) {
484 cert = qcrypto_tls_creds_load_cert(creds,
485 certFile, isServer,
486 errp);
487 if (!cert) {
488 goto cleanup;
489 }
490 }
491 if (access(cacertFile, R_OK) == 0) {
492 if (qcrypto_tls_creds_load_ca_cert_list(creds,
493 cacertFile, cacerts,
494 MAX_CERTS, &ncacerts,
495 errp) < 0) {
496 goto cleanup;
497 }
498 }
499
500 if (cert &&
501 qcrypto_tls_creds_check_cert(creds,
502 cert, certFile, isServer,
503 false, errp) < 0) {
504 goto cleanup;
505 }
506
507 for (i = 0; i < ncacerts; i++) {
508 if (qcrypto_tls_creds_check_cert(creds,
509 cacerts[i], cacertFile,
510 isServer, true, errp) < 0) {
511 goto cleanup;
512 }
513 }
514
515 if (cert && ncacerts &&
516 qcrypto_tls_creds_check_cert_pair(cert, certFile, cacerts,
517 ncacerts, cacertFile,
518 isServer, errp) < 0) {
519 goto cleanup;
520 }
521
522 ret = 0;
523
524 cleanup:
525 if (cert) {
526 gnutls_x509_crt_deinit(cert);
527 }
528 for (i = 0; i < ncacerts; i++) {
529 gnutls_x509_crt_deinit(cacerts[i]);
530 }
531 return ret;
532}
533
534
535static int
536qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
537 Error **errp)
538{
539 char *cacert = NULL, *cacrl = NULL, *cert = NULL,
540 *key = NULL, *dhparams = NULL;
541 int ret;
542 int rv = -1;
543
544 trace_qcrypto_tls_creds_x509_load(creds,
545 creds->parent_obj.dir ? creds->parent_obj.dir : "<nodir>");
546
547 if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
548 if (qcrypto_tls_creds_get_path(&creds->parent_obj,
549 QCRYPTO_TLS_CREDS_X509_CA_CERT,
550 true, &cacert, errp) < 0 ||
551 qcrypto_tls_creds_get_path(&creds->parent_obj,
552 QCRYPTO_TLS_CREDS_X509_CA_CRL,
553 false, &cacrl, errp) < 0 ||
554 qcrypto_tls_creds_get_path(&creds->parent_obj,
555 QCRYPTO_TLS_CREDS_X509_SERVER_CERT,
556 true, &cert, errp) < 0 ||
557 qcrypto_tls_creds_get_path(&creds->parent_obj,
558 QCRYPTO_TLS_CREDS_X509_SERVER_KEY,
559 true, &key, errp) < 0 ||
560 qcrypto_tls_creds_get_path(&creds->parent_obj,
561 QCRYPTO_TLS_CREDS_DH_PARAMS,
562 false, &dhparams, errp) < 0) {
563 goto cleanup;
564 }
565 } else {
566 if (qcrypto_tls_creds_get_path(&creds->parent_obj,
567 QCRYPTO_TLS_CREDS_X509_CA_CERT,
568 true, &cacert, errp) < 0 ||
569 qcrypto_tls_creds_get_path(&creds->parent_obj,
570 QCRYPTO_TLS_CREDS_X509_CLIENT_CERT,
571 false, &cert, errp) < 0 ||
572 qcrypto_tls_creds_get_path(&creds->parent_obj,
573 QCRYPTO_TLS_CREDS_X509_CLIENT_KEY,
574 false, &key, errp) < 0) {
575 goto cleanup;
576 }
577 }
578
579 if (creds->sanityCheck &&
580 qcrypto_tls_creds_x509_sanity_check(creds,
581 creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
582 cacert, cert, errp) < 0) {
583 goto cleanup;
584 }
585
586 ret = gnutls_certificate_allocate_credentials(&creds->data);
587 if (ret < 0) {
588 error_setg(errp, "Cannot allocate credentials: '%s'",
589 gnutls_strerror(ret));
590 goto cleanup;
591 }
592
593 ret = gnutls_certificate_set_x509_trust_file(creds->data,
594 cacert,
595 GNUTLS_X509_FMT_PEM);
596 if (ret < 0) {
597 error_setg(errp, "Cannot load CA certificate '%s': %s",
598 cacert, gnutls_strerror(ret));
599 goto cleanup;
600 }
601
602 if (cert != NULL && key != NULL) {
603 char *password = NULL;
604 if (creds->passwordid) {
605 password = qcrypto_secret_lookup_as_utf8(creds->passwordid,
606 errp);
607 if (!password) {
608 goto cleanup;
609 }
610 }
611 ret = gnutls_certificate_set_x509_key_file2(creds->data,
612 cert, key,
613 GNUTLS_X509_FMT_PEM,
614 password,
615 0);
616 g_free(password);
617 if (ret < 0) {
618 error_setg(errp, "Cannot load certificate '%s' & key '%s': %s",
619 cert, key, gnutls_strerror(ret));
620 goto cleanup;
621 }
622 }
623
624 if (cacrl != NULL) {
625 ret = gnutls_certificate_set_x509_crl_file(creds->data,
626 cacrl,
627 GNUTLS_X509_FMT_PEM);
628 if (ret < 0) {
629 error_setg(errp, "Cannot load CRL '%s': %s",
630 cacrl, gnutls_strerror(ret));
631 goto cleanup;
632 }
633 }
634
635 if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
636 if (qcrypto_tls_creds_get_dh_params_file(&creds->parent_obj, dhparams,
637 &creds->parent_obj.dh_params,
638 errp) < 0) {
639 goto cleanup;
640 }
641 gnutls_certificate_set_dh_params(creds->data,
642 creds->parent_obj.dh_params);
643 }
644
645 rv = 0;
646 cleanup:
647 g_free(cacert);
648 g_free(cacrl);
649 g_free(cert);
650 g_free(key);
651 g_free(dhparams);
652 return rv;
653}
654
655
656static void
657qcrypto_tls_creds_x509_unload(QCryptoTLSCredsX509 *creds)
658{
659 if (creds->data) {
660 gnutls_certificate_free_credentials(creds->data);
661 creds->data = NULL;
662 }
663 if (creds->parent_obj.dh_params) {
664 gnutls_dh_params_deinit(creds->parent_obj.dh_params);
665 creds->parent_obj.dh_params = NULL;
666 }
667}
668
669
670#else
671
672
673static void
674qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds G_GNUC_UNUSED,
675 Error **errp)
676{
677 error_setg(errp, "TLS credentials support requires GNUTLS");
678}
679
680
681static void
682qcrypto_tls_creds_x509_unload(QCryptoTLSCredsX509 *creds G_GNUC_UNUSED)
683{
684
685}
686
687
688#endif
689
690
691static void
692qcrypto_tls_creds_x509_prop_set_loaded(Object *obj,
693 bool value,
694 Error **errp)
695{
696 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
697
698 qcrypto_tls_creds_x509_unload(creds);
699 if (value) {
700 qcrypto_tls_creds_x509_load(creds, errp);
701 }
702}
703
704
705#ifdef CONFIG_GNUTLS
706
707
708static bool
709qcrypto_tls_creds_x509_prop_get_loaded(Object *obj,
710 Error **errp G_GNUC_UNUSED)
711{
712 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
713
714 return creds->data != NULL;
715}
716
717
718#else
719
720
721static bool
722qcrypto_tls_creds_x509_prop_get_loaded(Object *obj G_GNUC_UNUSED,
723 Error **errp G_GNUC_UNUSED)
724{
725 return false;
726}
727
728
729#endif
730
731
732static void
733qcrypto_tls_creds_x509_prop_set_sanity(Object *obj,
734 bool value,
735 Error **errp G_GNUC_UNUSED)
736{
737 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
738
739 creds->sanityCheck = value;
740}
741
742
743static void
744qcrypto_tls_creds_x509_prop_set_passwordid(Object *obj,
745 const char *value,
746 Error **errp G_GNUC_UNUSED)
747{
748 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
749
750 creds->passwordid = g_strdup(value);
751}
752
753
754static char *
755qcrypto_tls_creds_x509_prop_get_passwordid(Object *obj,
756 Error **errp G_GNUC_UNUSED)
757{
758 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
759
760 return g_strdup(creds->passwordid);
761}
762
763
764static bool
765qcrypto_tls_creds_x509_prop_get_sanity(Object *obj,
766 Error **errp G_GNUC_UNUSED)
767{
768 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
769
770 return creds->sanityCheck;
771}
772
773
774#ifdef CONFIG_GNUTLS
775
776
777static bool
778qcrypto_tls_creds_x509_reload(QCryptoTLSCreds *creds, Error **errp)
779{
780 QCryptoTLSCredsX509 *x509_creds = QCRYPTO_TLS_CREDS_X509(creds);
781 Error *local_err = NULL;
782 gnutls_certificate_credentials_t creds_data = x509_creds->data;
783 gnutls_dh_params_t creds_dh_params = x509_creds->parent_obj.dh_params;
784
785 x509_creds->data = NULL;
786 x509_creds->parent_obj.dh_params = NULL;
787 qcrypto_tls_creds_x509_load(x509_creds, &local_err);
788 if (local_err) {
789 qcrypto_tls_creds_x509_unload(x509_creds);
790 x509_creds->data = creds_data;
791 x509_creds->parent_obj.dh_params = creds_dh_params;
792 error_propagate(errp, local_err);
793 return false;
794 }
795
796 if (creds_data) {
797 gnutls_certificate_free_credentials(creds_data);
798 }
799 if (creds_dh_params) {
800 gnutls_dh_params_deinit(creds_dh_params);
801 }
802 return true;
803}
804
805
806#else
807
808
809static bool
810qcrypto_tls_creds_x509_reload(QCryptoTLSCreds *creds, Error **errp)
811{
812 return false;
813}
814
815
816#endif
817
818
819static void
820qcrypto_tls_creds_x509_complete(UserCreatable *uc, Error **errp)
821{
822 object_property_set_bool(OBJECT(uc), "loaded", true, errp);
823}
824
825
826static void
827qcrypto_tls_creds_x509_init(Object *obj)
828{
829 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
830
831 creds->sanityCheck = true;
832}
833
834
835static void
836qcrypto_tls_creds_x509_finalize(Object *obj)
837{
838 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
839
840 g_free(creds->passwordid);
841 qcrypto_tls_creds_x509_unload(creds);
842}
843
844
845static void
846qcrypto_tls_creds_x509_class_init(ObjectClass *oc, void *data)
847{
848 UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
849 QCryptoTLSCredsClass *ctcc = QCRYPTO_TLS_CREDS_CLASS(oc);
850
851 ctcc->reload = qcrypto_tls_creds_x509_reload;
852
853 ucc->complete = qcrypto_tls_creds_x509_complete;
854
855 object_class_property_add_bool(oc, "loaded",
856 qcrypto_tls_creds_x509_prop_get_loaded,
857 qcrypto_tls_creds_x509_prop_set_loaded);
858 object_class_property_add_bool(oc, "sanity-check",
859 qcrypto_tls_creds_x509_prop_get_sanity,
860 qcrypto_tls_creds_x509_prop_set_sanity);
861 object_class_property_add_str(oc, "passwordid",
862 qcrypto_tls_creds_x509_prop_get_passwordid,
863 qcrypto_tls_creds_x509_prop_set_passwordid);
864}
865
866
867static const TypeInfo qcrypto_tls_creds_x509_info = {
868 .parent = TYPE_QCRYPTO_TLS_CREDS,
869 .name = TYPE_QCRYPTO_TLS_CREDS_X509,
870 .instance_size = sizeof(QCryptoTLSCredsX509),
871 .instance_init = qcrypto_tls_creds_x509_init,
872 .instance_finalize = qcrypto_tls_creds_x509_finalize,
873 .class_size = sizeof(QCryptoTLSCredsX509Class),
874 .class_init = qcrypto_tls_creds_x509_class_init,
875 .interfaces = (InterfaceInfo[]) {
876 { TYPE_USER_CREATABLE },
877 { }
878 }
879};
880
881
882static void
883qcrypto_tls_creds_x509_register_types(void)
884{
885 type_register_static(&qcrypto_tls_creds_x509_info);
886}
887
888
889type_init(qcrypto_tls_creds_x509_register_types);
890