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