tlscredsx509.c (27114B)
1/* 2 * QEMU crypto TLS x509 credential support 3 * 4 * Copyright (c) 2015 Red Hat, Inc. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 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) { /* It is a CA cert */ 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) { /* It is not a CA cert */ 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 /* Missing basicConstraints */ 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 { /* General error */ 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 /* If there is no data at all, then we must allow 212 client/server to pass */ 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 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { 359 reason = "The certificate uses an insecure algorithm"; 360 } 361 362 error_setg(errp, 363 "Our own certificate %s failed validation against %s: %s", 364 certFile, cacertFile, reason); 365 return -1; 366 } 367 368 return 0; 369} 370 371 372static gnutls_x509_crt_t 373qcrypto_tls_creds_load_cert(QCryptoTLSCredsX509 *creds, 374 const char *certFile, 375 bool isServer, 376 Error **errp) 377{ 378 gnutls_datum_t data; 379 gnutls_x509_crt_t cert = NULL; 380 g_autofree char *buf = NULL; 381 gsize buflen; 382 GError *gerr = NULL; 383 int ret = -1; 384 int err; 385 386 trace_qcrypto_tls_creds_x509_load_cert(creds, isServer, certFile); 387 388 err = gnutls_x509_crt_init(&cert); 389 if (err < 0) { 390 error_setg(errp, "Unable to initialize certificate: %s", 391 gnutls_strerror(err)); 392 goto cleanup; 393 } 394 395 if (!g_file_get_contents(certFile, &buf, &buflen, &gerr)) { 396 error_setg(errp, "Cannot load CA cert list %s: %s", 397 certFile, gerr->message); 398 g_error_free(gerr); 399 goto cleanup; 400 } 401 402 data.data = (unsigned char *)buf; 403 data.size = strlen(buf); 404 405 err = gnutls_x509_crt_import(cert, &data, GNUTLS_X509_FMT_PEM); 406 if (err < 0) { 407 error_setg(errp, isServer ? 408 "Unable to import server certificate %s: %s" : 409 "Unable to import client certificate %s: %s", 410 certFile, 411 gnutls_strerror(err)); 412 goto cleanup; 413 } 414 415 ret = 0; 416 417 cleanup: 418 if (ret != 0) { 419 gnutls_x509_crt_deinit(cert); 420 cert = NULL; 421 } 422 return cert; 423} 424 425 426static int 427qcrypto_tls_creds_load_ca_cert_list(QCryptoTLSCredsX509 *creds, 428 const char *certFile, 429 gnutls_x509_crt_t *certs, 430 unsigned int certMax, 431 size_t *ncerts, 432 Error **errp) 433{ 434 gnutls_datum_t data; 435 g_autofree char *buf = NULL; 436 gsize buflen; 437 GError *gerr = NULL; 438 439 *ncerts = 0; 440 trace_qcrypto_tls_creds_x509_load_cert_list(creds, certFile); 441 442 if (!g_file_get_contents(certFile, &buf, &buflen, &gerr)) { 443 error_setg(errp, "Cannot load CA cert list %s: %s", 444 certFile, gerr->message); 445 g_error_free(gerr); 446 return -1; 447 } 448 449 data.data = (unsigned char *)buf; 450 data.size = strlen(buf); 451 452 if (gnutls_x509_crt_list_import(certs, &certMax, &data, 453 GNUTLS_X509_FMT_PEM, 0) < 0) { 454 error_setg(errp, 455 "Unable to import CA certificate list %s", 456 certFile); 457 return -1; 458 } 459 *ncerts = certMax; 460 461 return 0; 462} 463 464 465#define MAX_CERTS 16 466static int 467qcrypto_tls_creds_x509_sanity_check(QCryptoTLSCredsX509 *creds, 468 bool isServer, 469 const char *cacertFile, 470 const char *certFile, 471 Error **errp) 472{ 473 gnutls_x509_crt_t cert = NULL; 474 gnutls_x509_crt_t cacerts[MAX_CERTS]; 475 size_t ncacerts = 0; 476 size_t i; 477 int ret = -1; 478 479 memset(cacerts, 0, sizeof(cacerts)); 480 if (certFile && 481 access(certFile, R_OK) == 0) { 482 cert = qcrypto_tls_creds_load_cert(creds, 483 certFile, isServer, 484 errp); 485 if (!cert) { 486 goto cleanup; 487 } 488 } 489 if (access(cacertFile, R_OK) == 0) { 490 if (qcrypto_tls_creds_load_ca_cert_list(creds, 491 cacertFile, cacerts, 492 MAX_CERTS, &ncacerts, 493 errp) < 0) { 494 goto cleanup; 495 } 496 } 497 498 if (cert && 499 qcrypto_tls_creds_check_cert(creds, 500 cert, certFile, isServer, 501 false, errp) < 0) { 502 goto cleanup; 503 } 504 505 for (i = 0; i < ncacerts; i++) { 506 if (qcrypto_tls_creds_check_cert(creds, 507 cacerts[i], cacertFile, 508 isServer, true, errp) < 0) { 509 goto cleanup; 510 } 511 } 512 513 if (cert && ncacerts && 514 qcrypto_tls_creds_check_cert_pair(cert, certFile, cacerts, 515 ncacerts, cacertFile, 516 isServer, errp) < 0) { 517 goto cleanup; 518 } 519 520 ret = 0; 521 522 cleanup: 523 if (cert) { 524 gnutls_x509_crt_deinit(cert); 525 } 526 for (i = 0; i < ncacerts; i++) { 527 gnutls_x509_crt_deinit(cacerts[i]); 528 } 529 return ret; 530} 531 532 533static int 534qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds, 535 Error **errp) 536{ 537 char *cacert = NULL, *cacrl = NULL, *cert = NULL, 538 *key = NULL, *dhparams = NULL; 539 int ret; 540 int rv = -1; 541 542 trace_qcrypto_tls_creds_x509_load(creds, 543 creds->parent_obj.dir ? creds->parent_obj.dir : "<nodir>"); 544 545 if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { 546 if (qcrypto_tls_creds_get_path(&creds->parent_obj, 547 QCRYPTO_TLS_CREDS_X509_CA_CERT, 548 true, &cacert, errp) < 0 || 549 qcrypto_tls_creds_get_path(&creds->parent_obj, 550 QCRYPTO_TLS_CREDS_X509_CA_CRL, 551 false, &cacrl, errp) < 0 || 552 qcrypto_tls_creds_get_path(&creds->parent_obj, 553 QCRYPTO_TLS_CREDS_X509_SERVER_CERT, 554 true, &cert, errp) < 0 || 555 qcrypto_tls_creds_get_path(&creds->parent_obj, 556 QCRYPTO_TLS_CREDS_X509_SERVER_KEY, 557 true, &key, errp) < 0 || 558 qcrypto_tls_creds_get_path(&creds->parent_obj, 559 QCRYPTO_TLS_CREDS_DH_PARAMS, 560 false, &dhparams, errp) < 0) { 561 goto cleanup; 562 } 563 } else { 564 if (qcrypto_tls_creds_get_path(&creds->parent_obj, 565 QCRYPTO_TLS_CREDS_X509_CA_CERT, 566 true, &cacert, errp) < 0 || 567 qcrypto_tls_creds_get_path(&creds->parent_obj, 568 QCRYPTO_TLS_CREDS_X509_CLIENT_CERT, 569 false, &cert, errp) < 0 || 570 qcrypto_tls_creds_get_path(&creds->parent_obj, 571 QCRYPTO_TLS_CREDS_X509_CLIENT_KEY, 572 false, &key, errp) < 0) { 573 goto cleanup; 574 } 575 } 576 577 if (creds->sanityCheck && 578 qcrypto_tls_creds_x509_sanity_check(creds, 579 creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER, 580 cacert, cert, errp) < 0) { 581 goto cleanup; 582 } 583 584 ret = gnutls_certificate_allocate_credentials(&creds->data); 585 if (ret < 0) { 586 error_setg(errp, "Cannot allocate credentials: '%s'", 587 gnutls_strerror(ret)); 588 goto cleanup; 589 } 590 591 ret = gnutls_certificate_set_x509_trust_file(creds->data, 592 cacert, 593 GNUTLS_X509_FMT_PEM); 594 if (ret < 0) { 595 error_setg(errp, "Cannot load CA certificate '%s': %s", 596 cacert, gnutls_strerror(ret)); 597 goto cleanup; 598 } 599 600 if (cert != NULL && key != NULL) { 601 char *password = NULL; 602 if (creds->passwordid) { 603 password = qcrypto_secret_lookup_as_utf8(creds->passwordid, 604 errp); 605 if (!password) { 606 goto cleanup; 607 } 608 } 609 ret = gnutls_certificate_set_x509_key_file2(creds->data, 610 cert, key, 611 GNUTLS_X509_FMT_PEM, 612 password, 613 0); 614 g_free(password); 615 if (ret < 0) { 616 error_setg(errp, "Cannot load certificate '%s' & key '%s': %s", 617 cert, key, gnutls_strerror(ret)); 618 goto cleanup; 619 } 620 } 621 622 if (cacrl != NULL) { 623 ret = gnutls_certificate_set_x509_crl_file(creds->data, 624 cacrl, 625 GNUTLS_X509_FMT_PEM); 626 if (ret < 0) { 627 error_setg(errp, "Cannot load CRL '%s': %s", 628 cacrl, gnutls_strerror(ret)); 629 goto cleanup; 630 } 631 } 632 633 if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { 634 if (qcrypto_tls_creds_get_dh_params_file(&creds->parent_obj, dhparams, 635 &creds->parent_obj.dh_params, 636 errp) < 0) { 637 goto cleanup; 638 } 639 gnutls_certificate_set_dh_params(creds->data, 640 creds->parent_obj.dh_params); 641 } 642 643 rv = 0; 644 cleanup: 645 g_free(cacert); 646 g_free(cacrl); 647 g_free(cert); 648 g_free(key); 649 g_free(dhparams); 650 return rv; 651} 652 653 654static void 655qcrypto_tls_creds_x509_unload(QCryptoTLSCredsX509 *creds) 656{ 657 if (creds->data) { 658 gnutls_certificate_free_credentials(creds->data); 659 creds->data = NULL; 660 } 661 if (creds->parent_obj.dh_params) { 662 gnutls_dh_params_deinit(creds->parent_obj.dh_params); 663 creds->parent_obj.dh_params = NULL; 664 } 665} 666 667 668#else /* ! CONFIG_GNUTLS */ 669 670 671static void 672qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds G_GNUC_UNUSED, 673 Error **errp) 674{ 675 error_setg(errp, "TLS credentials support requires GNUTLS"); 676} 677 678 679static void 680qcrypto_tls_creds_x509_unload(QCryptoTLSCredsX509 *creds G_GNUC_UNUSED) 681{ 682 /* nada */ 683} 684 685 686#endif /* ! CONFIG_GNUTLS */ 687 688 689static void 690qcrypto_tls_creds_x509_prop_set_loaded(Object *obj, 691 bool value, 692 Error **errp) 693{ 694 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj); 695 696 qcrypto_tls_creds_x509_unload(creds); 697 if (value) { 698 qcrypto_tls_creds_x509_load(creds, errp); 699 } 700} 701 702 703#ifdef CONFIG_GNUTLS 704 705 706static bool 707qcrypto_tls_creds_x509_prop_get_loaded(Object *obj, 708 Error **errp G_GNUC_UNUSED) 709{ 710 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj); 711 712 return creds->data != NULL; 713} 714 715 716#else /* ! CONFIG_GNUTLS */ 717 718 719static bool 720qcrypto_tls_creds_x509_prop_get_loaded(Object *obj G_GNUC_UNUSED, 721 Error **errp G_GNUC_UNUSED) 722{ 723 return false; 724} 725 726 727#endif /* ! CONFIG_GNUTLS */ 728 729 730static void 731qcrypto_tls_creds_x509_prop_set_sanity(Object *obj, 732 bool value, 733 Error **errp G_GNUC_UNUSED) 734{ 735 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj); 736 737 creds->sanityCheck = value; 738} 739 740 741static void 742qcrypto_tls_creds_x509_prop_set_passwordid(Object *obj, 743 const char *value, 744 Error **errp G_GNUC_UNUSED) 745{ 746 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj); 747 748 creds->passwordid = g_strdup(value); 749} 750 751 752static char * 753qcrypto_tls_creds_x509_prop_get_passwordid(Object *obj, 754 Error **errp G_GNUC_UNUSED) 755{ 756 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj); 757 758 return g_strdup(creds->passwordid); 759} 760 761 762static bool 763qcrypto_tls_creds_x509_prop_get_sanity(Object *obj, 764 Error **errp G_GNUC_UNUSED) 765{ 766 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj); 767 768 return creds->sanityCheck; 769} 770 771 772#ifdef CONFIG_GNUTLS 773 774 775static bool 776qcrypto_tls_creds_x509_reload(QCryptoTLSCreds *creds, Error **errp) 777{ 778 QCryptoTLSCredsX509 *x509_creds = QCRYPTO_TLS_CREDS_X509(creds); 779 Error *local_err = NULL; 780 gnutls_certificate_credentials_t creds_data = x509_creds->data; 781 gnutls_dh_params_t creds_dh_params = x509_creds->parent_obj.dh_params; 782 783 x509_creds->data = NULL; 784 x509_creds->parent_obj.dh_params = NULL; 785 qcrypto_tls_creds_x509_load(x509_creds, &local_err); 786 if (local_err) { 787 qcrypto_tls_creds_x509_unload(x509_creds); 788 x509_creds->data = creds_data; 789 x509_creds->parent_obj.dh_params = creds_dh_params; 790 error_propagate(errp, local_err); 791 return false; 792 } 793 794 if (creds_data) { 795 gnutls_certificate_free_credentials(creds_data); 796 } 797 if (creds_dh_params) { 798 gnutls_dh_params_deinit(creds_dh_params); 799 } 800 return true; 801} 802 803 804#else /* ! CONFIG_GNUTLS */ 805 806 807static bool 808qcrypto_tls_creds_x509_reload(QCryptoTLSCreds *creds, Error **errp) 809{ 810 return false; 811} 812 813 814#endif /* ! CONFIG_GNUTLS */ 815 816 817static void 818qcrypto_tls_creds_x509_complete(UserCreatable *uc, Error **errp) 819{ 820 object_property_set_bool(OBJECT(uc), "loaded", true, errp); 821} 822 823 824static void 825qcrypto_tls_creds_x509_init(Object *obj) 826{ 827 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj); 828 829 creds->sanityCheck = true; 830} 831 832 833static void 834qcrypto_tls_creds_x509_finalize(Object *obj) 835{ 836 QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj); 837 838 g_free(creds->passwordid); 839 qcrypto_tls_creds_x509_unload(creds); 840} 841 842 843static void 844qcrypto_tls_creds_x509_class_init(ObjectClass *oc, void *data) 845{ 846 UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); 847 QCryptoTLSCredsClass *ctcc = QCRYPTO_TLS_CREDS_CLASS(oc); 848 849 ctcc->reload = qcrypto_tls_creds_x509_reload; 850 851 ucc->complete = qcrypto_tls_creds_x509_complete; 852 853 object_class_property_add_bool(oc, "loaded", 854 qcrypto_tls_creds_x509_prop_get_loaded, 855 qcrypto_tls_creds_x509_prop_set_loaded); 856 object_class_property_add_bool(oc, "sanity-check", 857 qcrypto_tls_creds_x509_prop_get_sanity, 858 qcrypto_tls_creds_x509_prop_set_sanity); 859 object_class_property_add_str(oc, "passwordid", 860 qcrypto_tls_creds_x509_prop_get_passwordid, 861 qcrypto_tls_creds_x509_prop_set_passwordid); 862} 863 864 865static const TypeInfo qcrypto_tls_creds_x509_info = { 866 .parent = TYPE_QCRYPTO_TLS_CREDS, 867 .name = TYPE_QCRYPTO_TLS_CREDS_X509, 868 .instance_size = sizeof(QCryptoTLSCredsX509), 869 .instance_init = qcrypto_tls_creds_x509_init, 870 .instance_finalize = qcrypto_tls_creds_x509_finalize, 871 .class_size = sizeof(QCryptoTLSCredsX509Class), 872 .class_init = qcrypto_tls_creds_x509_class_init, 873 .interfaces = (InterfaceInfo[]) { 874 { TYPE_USER_CREATABLE }, 875 { } 876 } 877}; 878 879 880static void 881qcrypto_tls_creds_x509_register_types(void) 882{ 883 type_register_static(&qcrypto_tls_creds_x509_info); 884} 885 886 887type_init(qcrypto_tls_creds_x509_register_types);