qemu/crypto/tlscredsx509.c
<<
>>
Prefs
   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
  36static int
  37qcrypto_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
  76static int
  77qcrypto_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
 128static int
 129qcrypto_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
 187static int
 188qcrypto_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
 280static int
 281qcrypto_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
 318static int
 319qcrypto_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#ifndef GNUTLS_1_0_COMPAT
 358        if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
 359            reason = "The certificate uses an insecure algorithm";
 360        }
 361#endif
 362
 363        error_setg(errp,
 364                   "Our own certificate %s failed validation against %s: %s",
 365                   certFile, cacertFile, reason);
 366        return -1;
 367    }
 368
 369    return 0;
 370}
 371
 372
 373static gnutls_x509_crt_t
 374qcrypto_tls_creds_load_cert(QCryptoTLSCredsX509 *creds,
 375                            const char *certFile,
 376                            bool isServer,
 377                            Error **errp)
 378{
 379    gnutls_datum_t data;
 380    gnutls_x509_crt_t cert = NULL;
 381    g_autofree char *buf = NULL;
 382    gsize buflen;
 383    GError *gerr;
 384    int ret = -1;
 385    int err;
 386
 387    trace_qcrypto_tls_creds_x509_load_cert(creds, isServer, certFile);
 388
 389    err = gnutls_x509_crt_init(&cert);
 390    if (err < 0) {
 391        error_setg(errp, "Unable to initialize certificate: %s",
 392                   gnutls_strerror(err));
 393        goto cleanup;
 394    }
 395
 396    if (!g_file_get_contents(certFile, &buf, &buflen, &gerr)) {
 397        error_setg(errp, "Cannot load CA cert list %s: %s",
 398                   certFile, gerr->message);
 399        g_error_free(gerr);
 400        goto cleanup;
 401    }
 402
 403    data.data = (unsigned char *)buf;
 404    data.size = strlen(buf);
 405
 406    err = gnutls_x509_crt_import(cert, &data, GNUTLS_X509_FMT_PEM);
 407    if (err < 0) {
 408        error_setg(errp, isServer ?
 409                   "Unable to import server certificate %s: %s" :
 410                   "Unable to import client certificate %s: %s",
 411                   certFile,
 412                   gnutls_strerror(err));
 413        goto cleanup;
 414    }
 415
 416    ret = 0;
 417
 418 cleanup:
 419    if (ret != 0) {
 420        gnutls_x509_crt_deinit(cert);
 421        cert = NULL;
 422    }
 423    return cert;
 424}
 425
 426
 427static int
 428qcrypto_tls_creds_load_ca_cert_list(QCryptoTLSCredsX509 *creds,
 429                                    const char *certFile,
 430                                    gnutls_x509_crt_t *certs,
 431                                    unsigned int certMax,
 432                                    size_t *ncerts,
 433                                    Error **errp)
 434{
 435    gnutls_datum_t data;
 436    g_autofree char *buf = NULL;
 437    gsize buflen;
 438    GError *gerr = NULL;
 439
 440    *ncerts = 0;
 441    trace_qcrypto_tls_creds_x509_load_cert_list(creds, certFile);
 442
 443    if (!g_file_get_contents(certFile, &buf, &buflen, &gerr)) {
 444        error_setg(errp, "Cannot load CA cert list %s: %s",
 445                   certFile, gerr->message);
 446        g_error_free(gerr);
 447        return -1;
 448    }
 449
 450    data.data = (unsigned char *)buf;
 451    data.size = strlen(buf);
 452
 453    if (gnutls_x509_crt_list_import(certs, &certMax, &data,
 454                                    GNUTLS_X509_FMT_PEM, 0) < 0) {
 455        error_setg(errp,
 456                   "Unable to import CA certificate list %s",
 457                   certFile);
 458        return -1;
 459    }
 460    *ncerts = certMax;
 461
 462    return 0;
 463}
 464
 465
 466#define MAX_CERTS 16
 467static int
 468qcrypto_tls_creds_x509_sanity_check(QCryptoTLSCredsX509 *creds,
 469                                    bool isServer,
 470                                    const char *cacertFile,
 471                                    const char *certFile,
 472                                    Error **errp)
 473{
 474    gnutls_x509_crt_t cert = NULL;
 475    gnutls_x509_crt_t cacerts[MAX_CERTS];
 476    size_t ncacerts = 0;
 477    size_t i;
 478    int ret = -1;
 479
 480    memset(cacerts, 0, sizeof(cacerts));
 481    if (certFile &&
 482        access(certFile, R_OK) == 0) {
 483        cert = qcrypto_tls_creds_load_cert(creds,
 484                                           certFile, isServer,
 485                                           errp);
 486        if (!cert) {
 487            goto cleanup;
 488        }
 489    }
 490    if (access(cacertFile, R_OK) == 0) {
 491        if (qcrypto_tls_creds_load_ca_cert_list(creds,
 492                                                cacertFile, cacerts,
 493                                                MAX_CERTS, &ncacerts,
 494                                                errp) < 0) {
 495            goto cleanup;
 496        }
 497    }
 498
 499    if (cert &&
 500        qcrypto_tls_creds_check_cert(creds,
 501                                     cert, certFile, isServer,
 502                                     false, errp) < 0) {
 503        goto cleanup;
 504    }
 505
 506    for (i = 0; i < ncacerts; i++) {
 507        if (qcrypto_tls_creds_check_cert(creds,
 508                                         cacerts[i], cacertFile,
 509                                         isServer, true, errp) < 0) {
 510            goto cleanup;
 511        }
 512    }
 513
 514    if (cert && ncacerts &&
 515        qcrypto_tls_creds_check_cert_pair(cert, certFile, cacerts,
 516                                          ncacerts, cacertFile,
 517                                          isServer, errp) < 0) {
 518        goto cleanup;
 519    }
 520
 521    ret = 0;
 522
 523 cleanup:
 524    if (cert) {
 525        gnutls_x509_crt_deinit(cert);
 526    }
 527    for (i = 0; i < ncacerts; i++) {
 528        gnutls_x509_crt_deinit(cacerts[i]);
 529    }
 530    return ret;
 531}
 532
 533
 534static int
 535qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
 536                            Error **errp)
 537{
 538    char *cacert = NULL, *cacrl = NULL, *cert = NULL,
 539        *key = NULL, *dhparams = NULL;
 540    int ret;
 541    int rv = -1;
 542
 543    trace_qcrypto_tls_creds_x509_load(creds,
 544            creds->parent_obj.dir ? creds->parent_obj.dir : "<nodir>");
 545
 546    if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
 547        if (qcrypto_tls_creds_get_path(&creds->parent_obj,
 548                                       QCRYPTO_TLS_CREDS_X509_CA_CERT,
 549                                       true, &cacert, errp) < 0 ||
 550            qcrypto_tls_creds_get_path(&creds->parent_obj,
 551                                       QCRYPTO_TLS_CREDS_X509_CA_CRL,
 552                                       false, &cacrl, errp) < 0 ||
 553            qcrypto_tls_creds_get_path(&creds->parent_obj,
 554                                       QCRYPTO_TLS_CREDS_X509_SERVER_CERT,
 555                                       true, &cert, errp) < 0 ||
 556            qcrypto_tls_creds_get_path(&creds->parent_obj,
 557                                       QCRYPTO_TLS_CREDS_X509_SERVER_KEY,
 558                                       true, &key, errp) < 0 ||
 559            qcrypto_tls_creds_get_path(&creds->parent_obj,
 560                                       QCRYPTO_TLS_CREDS_DH_PARAMS,
 561                                       false, &dhparams, errp) < 0) {
 562            goto cleanup;
 563        }
 564    } else {
 565        if (qcrypto_tls_creds_get_path(&creds->parent_obj,
 566                                       QCRYPTO_TLS_CREDS_X509_CA_CERT,
 567                                       true, &cacert, errp) < 0 ||
 568            qcrypto_tls_creds_get_path(&creds->parent_obj,
 569                                       QCRYPTO_TLS_CREDS_X509_CLIENT_CERT,
 570                                       false, &cert, errp) < 0 ||
 571            qcrypto_tls_creds_get_path(&creds->parent_obj,
 572                                       QCRYPTO_TLS_CREDS_X509_CLIENT_KEY,
 573                                       false, &key, errp) < 0) {
 574            goto cleanup;
 575        }
 576    }
 577
 578    if (creds->sanityCheck &&
 579        qcrypto_tls_creds_x509_sanity_check(creds,
 580            creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
 581            cacert, cert, errp) < 0) {
 582        goto cleanup;
 583    }
 584
 585    ret = gnutls_certificate_allocate_credentials(&creds->data);
 586    if (ret < 0) {
 587        error_setg(errp, "Cannot allocate credentials: '%s'",
 588                   gnutls_strerror(ret));
 589        goto cleanup;
 590    }
 591
 592    ret = gnutls_certificate_set_x509_trust_file(creds->data,
 593                                                 cacert,
 594                                                 GNUTLS_X509_FMT_PEM);
 595    if (ret < 0) {
 596        error_setg(errp, "Cannot load CA certificate '%s': %s",
 597                   cacert, gnutls_strerror(ret));
 598        goto cleanup;
 599    }
 600
 601    if (cert != NULL && key != NULL) {
 602        char *password = NULL;
 603        if (creds->passwordid) {
 604            password = qcrypto_secret_lookup_as_utf8(creds->passwordid,
 605                                                     errp);
 606            if (!password) {
 607                goto cleanup;
 608            }
 609        }
 610        ret = gnutls_certificate_set_x509_key_file2(creds->data,
 611                                                    cert, key,
 612                                                    GNUTLS_X509_FMT_PEM,
 613                                                    password,
 614                                                    0);
 615        g_free(password);
 616        if (ret < 0) {
 617            error_setg(errp, "Cannot load certificate '%s' & key '%s': %s",
 618                       cert, key, gnutls_strerror(ret));
 619            goto cleanup;
 620        }
 621    }
 622
 623    if (cacrl != NULL) {
 624        ret = gnutls_certificate_set_x509_crl_file(creds->data,
 625                                                   cacrl,
 626                                                   GNUTLS_X509_FMT_PEM);
 627        if (ret < 0) {
 628            error_setg(errp, "Cannot load CRL '%s': %s",
 629                       cacrl, gnutls_strerror(ret));
 630            goto cleanup;
 631        }
 632    }
 633
 634    if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
 635        if (qcrypto_tls_creds_get_dh_params_file(&creds->parent_obj, dhparams,
 636                                                 &creds->parent_obj.dh_params,
 637                                                 errp) < 0) {
 638            goto cleanup;
 639        }
 640        gnutls_certificate_set_dh_params(creds->data,
 641                                         creds->parent_obj.dh_params);
 642    }
 643
 644    rv = 0;
 645 cleanup:
 646    g_free(cacert);
 647    g_free(cacrl);
 648    g_free(cert);
 649    g_free(key);
 650    g_free(dhparams);
 651    return rv;
 652}
 653
 654
 655static void
 656qcrypto_tls_creds_x509_unload(QCryptoTLSCredsX509 *creds)
 657{
 658    if (creds->data) {
 659        gnutls_certificate_free_credentials(creds->data);
 660        creds->data = NULL;
 661    }
 662    if (creds->parent_obj.dh_params) {
 663        gnutls_dh_params_deinit(creds->parent_obj.dh_params);
 664        creds->parent_obj.dh_params = NULL;
 665    }
 666}
 667
 668
 669#else /* ! CONFIG_GNUTLS */
 670
 671
 672static void
 673qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds G_GNUC_UNUSED,
 674                            Error **errp)
 675{
 676    error_setg(errp, "TLS credentials support requires GNUTLS");
 677}
 678
 679
 680static void
 681qcrypto_tls_creds_x509_unload(QCryptoTLSCredsX509 *creds G_GNUC_UNUSED)
 682{
 683    /* nada */
 684}
 685
 686
 687#endif /* ! CONFIG_GNUTLS */
 688
 689
 690static void
 691qcrypto_tls_creds_x509_prop_set_loaded(Object *obj,
 692                                       bool value,
 693                                       Error **errp)
 694{
 695    QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
 696
 697    if (value) {
 698        qcrypto_tls_creds_x509_load(creds, errp);
 699    } else {
 700        qcrypto_tls_creds_x509_unload(creds);
 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 /* ! CONFIG_GNUTLS */
 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 /* ! CONFIG_GNUTLS */
 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
 774static void
 775qcrypto_tls_creds_x509_complete(UserCreatable *uc, Error **errp)
 776{
 777    object_property_set_bool(OBJECT(uc), true, "loaded", errp);
 778}
 779
 780
 781static void
 782qcrypto_tls_creds_x509_init(Object *obj)
 783{
 784    QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
 785
 786    creds->sanityCheck = true;
 787}
 788
 789
 790static void
 791qcrypto_tls_creds_x509_finalize(Object *obj)
 792{
 793    QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
 794
 795    g_free(creds->passwordid);
 796    qcrypto_tls_creds_x509_unload(creds);
 797}
 798
 799
 800static void
 801qcrypto_tls_creds_x509_class_init(ObjectClass *oc, void *data)
 802{
 803    UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
 804
 805    ucc->complete = qcrypto_tls_creds_x509_complete;
 806
 807    object_class_property_add_bool(oc, "loaded",
 808                                   qcrypto_tls_creds_x509_prop_get_loaded,
 809                                   qcrypto_tls_creds_x509_prop_set_loaded,
 810                                   NULL);
 811    object_class_property_add_bool(oc, "sanity-check",
 812                                   qcrypto_tls_creds_x509_prop_get_sanity,
 813                                   qcrypto_tls_creds_x509_prop_set_sanity,
 814                                   NULL);
 815    object_class_property_add_str(oc, "passwordid",
 816                                  qcrypto_tls_creds_x509_prop_get_passwordid,
 817                                  qcrypto_tls_creds_x509_prop_set_passwordid,
 818                                  NULL);
 819}
 820
 821
 822static const TypeInfo qcrypto_tls_creds_x509_info = {
 823    .parent = TYPE_QCRYPTO_TLS_CREDS,
 824    .name = TYPE_QCRYPTO_TLS_CREDS_X509,
 825    .instance_size = sizeof(QCryptoTLSCredsX509),
 826    .instance_init = qcrypto_tls_creds_x509_init,
 827    .instance_finalize = qcrypto_tls_creds_x509_finalize,
 828    .class_size = sizeof(QCryptoTLSCredsX509Class),
 829    .class_init = qcrypto_tls_creds_x509_class_init,
 830    .interfaces = (InterfaceInfo[]) {
 831        { TYPE_USER_CREATABLE },
 832        { }
 833    }
 834};
 835
 836
 837static void
 838qcrypto_tls_creds_x509_register_types(void)
 839{
 840    type_register_static(&qcrypto_tls_creds_x509_info);
 841}
 842
 843
 844type_init(qcrypto_tls_creds_x509_register_types);
 845