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