qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

secret_keyring.c (3637B)


      1 /*
      2  * QEMU crypto secret support
      3  *
      4  * Copyright 2020 Yandex N.V.
      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 <asm/unistd.h>
     23 #include <linux/keyctl.h>
     24 #include "qapi/error.h"
     25 #include "qom/object_interfaces.h"
     26 #include "trace.h"
     27 #include "crypto/secret_keyring.h"
     28 
     29 
     30 static inline
     31 long keyctl_read(int32_t key, uint8_t *buffer, size_t buflen)
     32 {
     33     return syscall(__NR_keyctl, KEYCTL_READ, key, buffer, buflen, 0);
     34 }
     35 
     36 
     37 static void
     38 qcrypto_secret_keyring_load_data(QCryptoSecretCommon *sec_common,
     39                                  uint8_t **output,
     40                                  size_t *outputlen,
     41                                  Error **errp)
     42 {
     43     QCryptoSecretKeyring *secret = QCRYPTO_SECRET_KEYRING(sec_common);
     44     uint8_t *buffer = NULL;
     45     long retcode;
     46 
     47     *output = NULL;
     48     *outputlen = 0;
     49 
     50     if (!secret->serial) {
     51         error_setg(errp, "'serial' parameter must be provided");
     52         return;
     53     }
     54 
     55     retcode = keyctl_read(secret->serial, NULL, 0);
     56     if (retcode <= 0) {
     57         goto keyctl_error;
     58     }
     59 
     60     buffer = g_new0(uint8_t, retcode);
     61 
     62     retcode = keyctl_read(secret->serial, buffer, retcode);
     63     if (retcode < 0) {
     64         g_free(buffer);
     65         goto keyctl_error;
     66     }
     67 
     68     *outputlen = retcode;
     69     *output = buffer;
     70     return;
     71 
     72 keyctl_error:
     73     error_setg_errno(errp, errno,
     74                      "Unable to read serial key %08x",
     75                      secret->serial);
     76 }
     77 
     78 
     79 static void
     80 qcrypto_secret_prop_set_key(Object *obj, Visitor *v,
     81                             const char *name, void *opaque,
     82                             Error **errp)
     83 {
     84     QCryptoSecretKeyring *secret = QCRYPTO_SECRET_KEYRING(obj);
     85     int32_t value;
     86     visit_type_int32(v, name, &value, errp);
     87     if (!value) {
     88         error_setg(errp, "'serial' should not be equal to 0");
     89     }
     90     secret->serial = value;
     91 }
     92 
     93 
     94 static void
     95 qcrypto_secret_prop_get_key(Object *obj, Visitor *v,
     96                             const char *name, void *opaque,
     97                             Error **errp)
     98 {
     99     QCryptoSecretKeyring *secret = QCRYPTO_SECRET_KEYRING(obj);
    100     int32_t value = secret->serial;
    101     visit_type_int32(v, name, &value, errp);
    102 }
    103 
    104 
    105 static void
    106 qcrypto_secret_keyring_class_init(ObjectClass *oc, void *data)
    107 {
    108     QCryptoSecretCommonClass *sic = QCRYPTO_SECRET_COMMON_CLASS(oc);
    109     sic->load_data = qcrypto_secret_keyring_load_data;
    110 
    111     object_class_property_add(oc, "serial", "int32_t",
    112                                   qcrypto_secret_prop_get_key,
    113                                   qcrypto_secret_prop_set_key,
    114                                   NULL, NULL);
    115 }
    116 
    117 
    118 static const TypeInfo qcrypto_secret_info = {
    119     .parent = TYPE_QCRYPTO_SECRET_COMMON,
    120     .name = TYPE_QCRYPTO_SECRET_KEYRING,
    121     .instance_size = sizeof(QCryptoSecretKeyring),
    122     .class_init = qcrypto_secret_keyring_class_init,
    123 };
    124 
    125 
    126 static void
    127 qcrypto_secret_register_types(void)
    128 {
    129     type_register_static(&qcrypto_secret_info);
    130 }
    131 
    132 
    133 type_init(qcrypto_secret_register_types);