qemu/crypto/tls-cipher-suites.c
<<
>>
Prefs
   1/*
   2 * QEMU TLS Cipher Suites
   3 *
   4 * Copyright (c) 2018-2020 Red Hat, Inc.
   5 *
   6 * Author: Philippe Mathieu-Daudé <philmd@redhat.com>
   7 *
   8 * SPDX-License-Identifier: GPL-2.0-or-later
   9 */
  10
  11#include "qemu/osdep.h"
  12#include "qapi/error.h"
  13#include "qom/object_interfaces.h"
  14#include "crypto/tlscreds.h"
  15#include "crypto/tls-cipher-suites.h"
  16#include "hw/nvram/fw_cfg.h"
  17#include "tlscredspriv.h"
  18#include "trace.h"
  19
  20struct QCryptoTLSCipherSuites {
  21    /* <private> */
  22    QCryptoTLSCreds parent_obj;
  23    /* <public> */
  24};
  25
  26/*
  27 * IANA registered TLS ciphers:
  28 * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4
  29 */
  30typedef struct {
  31    uint8_t data[2];
  32} QEMU_PACKED IANA_TLS_CIPHER;
  33
  34GByteArray *qcrypto_tls_cipher_suites_get_data(QCryptoTLSCipherSuites *obj,
  35                                               Error **errp)
  36{
  37    QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
  38    gnutls_priority_t pcache;
  39    GByteArray *byte_array;
  40    const char *err;
  41    size_t i;
  42    int ret;
  43
  44    trace_qcrypto_tls_cipher_suite_priority(creds->priority);
  45    ret = gnutls_priority_init(&pcache, creds->priority, &err);
  46    if (ret < 0) {
  47        error_setg(errp, "Syntax error using priority '%s': %s",
  48                   creds->priority, gnutls_strerror(ret));
  49        return NULL;
  50    }
  51
  52    byte_array = g_byte_array_new();
  53
  54    for (i = 0;; i++) {
  55        int ret;
  56        unsigned idx;
  57        const char *name;
  58        IANA_TLS_CIPHER cipher;
  59        gnutls_protocol_t protocol;
  60        const char *version;
  61
  62        ret = gnutls_priority_get_cipher_suite_index(pcache, i, &idx);
  63        if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
  64            break;
  65        }
  66        if (ret == GNUTLS_E_UNKNOWN_CIPHER_SUITE) {
  67            continue;
  68        }
  69
  70        name = gnutls_cipher_suite_info(idx, (unsigned char *)&cipher,
  71                                        NULL, NULL, NULL, &protocol);
  72        if (name == NULL) {
  73            continue;
  74        }
  75
  76        version = gnutls_protocol_get_name(protocol);
  77        g_byte_array_append(byte_array, cipher.data, 2);
  78        trace_qcrypto_tls_cipher_suite_info(cipher.data[0],
  79                                            cipher.data[1],
  80                                            version, name);
  81    }
  82    trace_qcrypto_tls_cipher_suite_count(byte_array->len);
  83    gnutls_priority_deinit(pcache);
  84
  85    return byte_array;
  86}
  87
  88static void qcrypto_tls_cipher_suites_complete(UserCreatable *uc,
  89                                               Error **errp)
  90{
  91    QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(uc);
  92
  93    if (!creds->priority) {
  94        error_setg(errp, "'priority' property is not set");
  95        return;
  96    }
  97}
  98
  99static GByteArray *qcrypto_tls_cipher_suites_fw_cfg_gen_data(Object *obj,
 100                                                             Error **errp)
 101{
 102    return qcrypto_tls_cipher_suites_get_data(QCRYPTO_TLS_CIPHER_SUITES(obj),
 103                                              errp);
 104}
 105
 106static void qcrypto_tls_cipher_suites_class_init(ObjectClass *oc, void *data)
 107{
 108    UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
 109    FWCfgDataGeneratorClass *fwgc = FW_CFG_DATA_GENERATOR_CLASS(oc);
 110
 111    ucc->complete = qcrypto_tls_cipher_suites_complete;
 112    fwgc->get_data = qcrypto_tls_cipher_suites_fw_cfg_gen_data;
 113}
 114
 115static const TypeInfo qcrypto_tls_cipher_suites_info = {
 116    .parent = TYPE_QCRYPTO_TLS_CREDS,
 117    .name = TYPE_QCRYPTO_TLS_CIPHER_SUITES,
 118    .instance_size = sizeof(QCryptoTLSCipherSuites),
 119    .class_size = sizeof(QCryptoTLSCredsClass),
 120    .class_init = qcrypto_tls_cipher_suites_class_init,
 121    .interfaces = (InterfaceInfo[]) {
 122        { TYPE_USER_CREATABLE },
 123        { TYPE_FW_CFG_DATA_GENERATOR_INTERFACE },
 124        { }
 125    }
 126};
 127
 128static void qcrypto_tls_cipher_suites_register_types(void)
 129{
 130    type_register_static(&qcrypto_tls_cipher_suites_info);
 131}
 132
 133type_init(qcrypto_tls_cipher_suites_register_types);
 134