cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

tlscredsx509.c (27114B)


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