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    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    g_free(buf);
 424    return cert;
 425}
 426
 427
 428static int
 429qcrypto_tls_creds_load_ca_cert_list(QCryptoTLSCredsX509 *creds,
 430                                    const char *certFile,
 431                                    gnutls_x509_crt_t *certs,
 432                                    unsigned int certMax,
 433                                    size_t *ncerts,
 434                                    Error **errp)
 435{
 436    gnutls_datum_t data;
 437    char *buf = NULL;
 438    gsize buflen;
 439    int ret = -1;
 440    GError *gerr = NULL;
 441
 442    *ncerts = 0;
 443    trace_qcrypto_tls_creds_x509_load_cert_list(creds, certFile);
 444
 445    if (!g_file_get_contents(certFile, &buf, &buflen, &gerr)) {
 446        error_setg(errp, "Cannot load CA cert list %s: %s",
 447                   certFile, gerr->message);
 448        g_error_free(gerr);
 449        goto cleanup;
 450    }
 451
 452    data.data = (unsigned char *)buf;
 453    data.size = strlen(buf);
 454
 455    if (gnutls_x509_crt_list_import(certs, &certMax, &data,
 456                                    GNUTLS_X509_FMT_PEM, 0) < 0) {
 457        error_setg(errp,
 458                   "Unable to import CA certificate list %s",
 459                   certFile);
 460        goto cleanup;
 461    }
 462    *ncerts = certMax;
 463
 464    ret = 0;
 465
 466 cleanup:
 467    g_free(buf);
 468    return ret;
 469}
 470
 471
 472#define MAX_CERTS 16
 473static int
 474qcrypto_tls_creds_x509_sanity_check(QCryptoTLSCredsX509 *creds,
 475                                    bool isServer,
 476                                    const char *cacertFile,
 477                                    const char *certFile,
 478                                    Error **errp)
 479{
 480    gnutls_x509_crt_t cert = NULL;
 481    gnutls_x509_crt_t cacerts[MAX_CERTS];
 482    size_t ncacerts = 0;
 483    size_t i;
 484    int ret = -1;
 485
 486    memset(cacerts, 0, sizeof(cacerts));
 487    if (certFile &&
 488        access(certFile, R_OK) == 0) {
 489        cert = qcrypto_tls_creds_load_cert(creds,
 490                                           certFile, isServer,
 491                                           errp);
 492        if (!cert) {
 493            goto cleanup;
 494        }
 495    }
 496    if (access(cacertFile, R_OK) == 0) {
 497        if (qcrypto_tls_creds_load_ca_cert_list(creds,
 498                                                cacertFile, cacerts,
 499                                                MAX_CERTS, &ncacerts,
 500                                                errp) < 0) {
 501            goto cleanup;
 502        }
 503    }
 504
 505    if (cert &&
 506        qcrypto_tls_creds_check_cert(creds,
 507                                     cert, certFile, isServer,
 508                                     false, errp) < 0) {
 509        goto cleanup;
 510    }
 511
 512    for (i = 0; i < ncacerts; i++) {
 513        if (qcrypto_tls_creds_check_cert(creds,
 514                                         cacerts[i], cacertFile,
 515                                         isServer, true, errp) < 0) {
 516            goto cleanup;
 517        }
 518    }
 519
 520    if (cert && ncacerts &&
 521        qcrypto_tls_creds_check_cert_pair(cert, certFile, cacerts,
 522                                          ncacerts, cacertFile,
 523                                          isServer, errp) < 0) {
 524        goto cleanup;
 525    }
 526
 527    ret = 0;
 528
 529 cleanup:
 530    if (cert) {
 531        gnutls_x509_crt_deinit(cert);
 532    }
 533    for (i = 0; i < ncacerts; i++) {
 534        gnutls_x509_crt_deinit(cacerts[i]);
 535    }
 536    return ret;
 537}
 538
 539
 540static int
 541qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
 542                            Error **errp)
 543{
 544    char *cacert = NULL, *cacrl = NULL, *cert = NULL,
 545        *key = NULL, *dhparams = NULL;
 546    int ret;
 547    int rv = -1;
 548
 549    trace_qcrypto_tls_creds_x509_load(creds,
 550            creds->parent_obj.dir ? creds->parent_obj.dir : "<nodir>");
 551
 552    if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
 553        if (qcrypto_tls_creds_get_path(&creds->parent_obj,
 554                                       QCRYPTO_TLS_CREDS_X509_CA_CERT,
 555                                       true, &cacert, errp) < 0 ||
 556            qcrypto_tls_creds_get_path(&creds->parent_obj,
 557                                       QCRYPTO_TLS_CREDS_X509_CA_CRL,
 558                                       false, &cacrl, errp) < 0 ||
 559            qcrypto_tls_creds_get_path(&creds->parent_obj,
 560                                       QCRYPTO_TLS_CREDS_X509_SERVER_CERT,
 561                                       true, &cert, errp) < 0 ||
 562            qcrypto_tls_creds_get_path(&creds->parent_obj,
 563                                       QCRYPTO_TLS_CREDS_X509_SERVER_KEY,
 564                                       true, &key, errp) < 0 ||
 565            qcrypto_tls_creds_get_path(&creds->parent_obj,
 566                                       QCRYPTO_TLS_CREDS_DH_PARAMS,
 567                                       false, &dhparams, errp) < 0) {
 568            goto cleanup;
 569        }
 570    } else {
 571        if (qcrypto_tls_creds_get_path(&creds->parent_obj,
 572                                       QCRYPTO_TLS_CREDS_X509_CA_CERT,
 573                                       true, &cacert, errp) < 0 ||
 574            qcrypto_tls_creds_get_path(&creds->parent_obj,
 575                                       QCRYPTO_TLS_CREDS_X509_CLIENT_CERT,
 576                                       false, &cert, errp) < 0 ||
 577            qcrypto_tls_creds_get_path(&creds->parent_obj,
 578                                       QCRYPTO_TLS_CREDS_X509_CLIENT_KEY,
 579                                       false, &key, errp) < 0) {
 580            goto cleanup;
 581        }
 582    }
 583
 584    if (creds->sanityCheck &&
 585        qcrypto_tls_creds_x509_sanity_check(creds,
 586            creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
 587            cacert, cert, errp) < 0) {
 588        goto cleanup;
 589    }
 590
 591    ret = gnutls_certificate_allocate_credentials(&creds->data);
 592    if (ret < 0) {
 593        error_setg(errp, "Cannot allocate credentials: '%s'",
 594                   gnutls_strerror(ret));
 595        goto cleanup;
 596    }
 597
 598    ret = gnutls_certificate_set_x509_trust_file(creds->data,
 599                                                 cacert,
 600                                                 GNUTLS_X509_FMT_PEM);
 601    if (ret < 0) {
 602        error_setg(errp, "Cannot load CA certificate '%s': %s",
 603                   cacert, gnutls_strerror(ret));
 604        goto cleanup;
 605    }
 606
 607    if (cert != NULL && key != NULL) {
 608        char *password = NULL;
 609        if (creds->passwordid) {
 610            password = qcrypto_secret_lookup_as_utf8(creds->passwordid,
 611                                                     errp);
 612            if (!password) {
 613                goto cleanup;
 614            }
 615        }
 616        ret = gnutls_certificate_set_x509_key_file2(creds->data,
 617                                                    cert, key,
 618                                                    GNUTLS_X509_FMT_PEM,
 619                                                    password,
 620                                                    0);
 621        g_free(password);
 622        if (ret < 0) {
 623            error_setg(errp, "Cannot load certificate '%s' & key '%s': %s",
 624                       cert, key, gnutls_strerror(ret));
 625            goto cleanup;
 626        }
 627    }
 628
 629    if (cacrl != NULL) {
 630        ret = gnutls_certificate_set_x509_crl_file(creds->data,
 631                                                   cacrl,
 632                                                   GNUTLS_X509_FMT_PEM);
 633        if (ret < 0) {
 634            error_setg(errp, "Cannot load CRL '%s': %s",
 635                       cacrl, gnutls_strerror(ret));
 636            goto cleanup;
 637        }
 638    }
 639
 640    if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
 641        if (qcrypto_tls_creds_get_dh_params_file(&creds->parent_obj, dhparams,
 642                                                 &creds->parent_obj.dh_params,
 643                                                 errp) < 0) {
 644            goto cleanup;
 645        }
 646        gnutls_certificate_set_dh_params(creds->data,
 647                                         creds->parent_obj.dh_params);
 648    }
 649
 650    rv = 0;
 651 cleanup:
 652    g_free(cacert);
 653    g_free(cacrl);
 654    g_free(cert);
 655    g_free(key);
 656    g_free(dhparams);
 657    return rv;
 658}
 659
 660
 661static void
 662qcrypto_tls_creds_x509_unload(QCryptoTLSCredsX509 *creds)
 663{
 664    if (creds->data) {
 665        gnutls_certificate_free_credentials(creds->data);
 666        creds->data = NULL;
 667    }
 668    if (creds->parent_obj.dh_params) {
 669        gnutls_dh_params_deinit(creds->parent_obj.dh_params);
 670        creds->parent_obj.dh_params = NULL;
 671    }
 672}
 673
 674
 675#else /* ! CONFIG_GNUTLS */
 676
 677
 678static void
 679qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds G_GNUC_UNUSED,
 680                            Error **errp)
 681{
 682    error_setg(errp, "TLS credentials support requires GNUTLS");
 683}
 684
 685
 686static void
 687qcrypto_tls_creds_x509_unload(QCryptoTLSCredsX509 *creds G_GNUC_UNUSED)
 688{
 689    /* nada */
 690}
 691
 692
 693#endif /* ! CONFIG_GNUTLS */
 694
 695
 696static void
 697qcrypto_tls_creds_x509_prop_set_loaded(Object *obj,
 698                                       bool value,
 699                                       Error **errp)
 700{
 701    QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
 702
 703    if (value) {
 704        qcrypto_tls_creds_x509_load(creds, errp);
 705    } else {
 706        qcrypto_tls_creds_x509_unload(creds);
 707    }
 708}
 709
 710
 711#ifdef CONFIG_GNUTLS
 712
 713
 714static bool
 715qcrypto_tls_creds_x509_prop_get_loaded(Object *obj,
 716                                       Error **errp G_GNUC_UNUSED)
 717{
 718    QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
 719
 720    return creds->data != NULL;
 721}
 722
 723
 724#else /* ! CONFIG_GNUTLS */
 725
 726
 727static bool
 728qcrypto_tls_creds_x509_prop_get_loaded(Object *obj G_GNUC_UNUSED,
 729                                       Error **errp G_GNUC_UNUSED)
 730{
 731    return false;
 732}
 733
 734
 735#endif /* ! CONFIG_GNUTLS */
 736
 737
 738static void
 739qcrypto_tls_creds_x509_prop_set_sanity(Object *obj,
 740                                       bool value,
 741                                       Error **errp G_GNUC_UNUSED)
 742{
 743    QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
 744
 745    creds->sanityCheck = value;
 746}
 747
 748
 749static void
 750qcrypto_tls_creds_x509_prop_set_passwordid(Object *obj,
 751                                           const char *value,
 752                                           Error **errp G_GNUC_UNUSED)
 753{
 754    QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
 755
 756    creds->passwordid = g_strdup(value);
 757}
 758
 759
 760static char *
 761qcrypto_tls_creds_x509_prop_get_passwordid(Object *obj,
 762                                           Error **errp G_GNUC_UNUSED)
 763{
 764    QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
 765
 766    return g_strdup(creds->passwordid);
 767}
 768
 769
 770static bool
 771qcrypto_tls_creds_x509_prop_get_sanity(Object *obj,
 772                                       Error **errp G_GNUC_UNUSED)
 773{
 774    QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
 775
 776    return creds->sanityCheck;
 777}
 778
 779
 780static void
 781qcrypto_tls_creds_x509_complete(UserCreatable *uc, Error **errp)
 782{
 783    object_property_set_bool(OBJECT(uc), true, "loaded", errp);
 784}
 785
 786
 787static void
 788qcrypto_tls_creds_x509_init(Object *obj)
 789{
 790    QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
 791
 792    creds->sanityCheck = true;
 793}
 794
 795
 796static void
 797qcrypto_tls_creds_x509_finalize(Object *obj)
 798{
 799    QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
 800
 801    g_free(creds->passwordid);
 802    qcrypto_tls_creds_x509_unload(creds);
 803}
 804
 805
 806static void
 807qcrypto_tls_creds_x509_class_init(ObjectClass *oc, void *data)
 808{
 809    UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
 810
 811    ucc->complete = qcrypto_tls_creds_x509_complete;
 812
 813    object_class_property_add_bool(oc, "loaded",
 814                                   qcrypto_tls_creds_x509_prop_get_loaded,
 815                                   qcrypto_tls_creds_x509_prop_set_loaded,
 816                                   NULL);
 817    object_class_property_add_bool(oc, "sanity-check",
 818                                   qcrypto_tls_creds_x509_prop_get_sanity,
 819                                   qcrypto_tls_creds_x509_prop_set_sanity,
 820                                   NULL);
 821    object_class_property_add_str(oc, "passwordid",
 822                                  qcrypto_tls_creds_x509_prop_get_passwordid,
 823                                  qcrypto_tls_creds_x509_prop_set_passwordid,
 824                                  NULL);
 825}
 826
 827
 828static const TypeInfo qcrypto_tls_creds_x509_info = {
 829    .parent = TYPE_QCRYPTO_TLS_CREDS,
 830    .name = TYPE_QCRYPTO_TLS_CREDS_X509,
 831    .instance_size = sizeof(QCryptoTLSCredsX509),
 832    .instance_init = qcrypto_tls_creds_x509_init,
 833    .instance_finalize = qcrypto_tls_creds_x509_finalize,
 834    .class_size = sizeof(QCryptoTLSCredsX509Class),
 835    .class_init = qcrypto_tls_creds_x509_class_init,
 836    .interfaces = (InterfaceInfo[]) {
 837        { TYPE_USER_CREATABLE },
 838        { }
 839    }
 840};
 841
 842
 843static void
 844qcrypto_tls_creds_x509_register_types(void)
 845{
 846    type_register_static(&qcrypto_tls_creds_x509_info);
 847}
 848
 849
 850type_init(qcrypto_tls_creds_x509_register_types);
 851