1ac1d8878SDaniel P. Berrange /* 2ac1d8878SDaniel P. Berrange * QEMU crypto secret support 3ac1d8878SDaniel P. Berrange * 4ac1d8878SDaniel P. Berrange * Copyright (c) 2015 Red Hat, Inc. 5ac1d8878SDaniel P. Berrange * 6ac1d8878SDaniel P. Berrange * This library is free software; you can redistribute it and/or 7ac1d8878SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 8ac1d8878SDaniel P. Berrange * License as published by the Free Software Foundation; either 9*b7cbb874SThomas Huth * version 2.1 of the License, or (at your option) any later version. 10ac1d8878SDaniel P. Berrange * 11ac1d8878SDaniel P. Berrange * This library is distributed in the hope that it will be useful, 12ac1d8878SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 13ac1d8878SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14ac1d8878SDaniel P. Berrange * Lesser General Public License for more details. 15ac1d8878SDaniel P. Berrange * 16ac1d8878SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 17ac1d8878SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18ac1d8878SDaniel P. Berrange * 19ac1d8878SDaniel P. Berrange */ 20ac1d8878SDaniel P. Berrange 2142f7a448SPeter Maydell #include "qemu/osdep.h" 22ac1d8878SDaniel P. Berrange #include "crypto/secret.h" 23ac1d8878SDaniel P. Berrange #include "crypto/cipher.h" 24da34e65cSMarkus Armbruster #include "qapi/error.h" 25ac1d8878SDaniel P. Berrange #include "qom/object_interfaces.h" 26ac1d8878SDaniel P. Berrange #include "qemu/base64.h" 270b8fa32fSMarkus Armbruster #include "qemu/module.h" 28ac1d8878SDaniel P. Berrange #include "trace.h" 29ac1d8878SDaniel P. Berrange 30ac1d8878SDaniel P. Berrange 31ac1d8878SDaniel P. Berrange static void 32ac1d8878SDaniel P. Berrange qcrypto_secret_load_data(QCryptoSecret *secret, 33ac1d8878SDaniel P. Berrange uint8_t **output, 34ac1d8878SDaniel P. Berrange size_t *outputlen, 35ac1d8878SDaniel P. Berrange Error **errp) 36ac1d8878SDaniel P. Berrange { 37ac1d8878SDaniel P. Berrange char *data = NULL; 38ac1d8878SDaniel P. Berrange size_t length = 0; 39ac1d8878SDaniel P. Berrange GError *gerr = NULL; 40ac1d8878SDaniel P. Berrange 41ac1d8878SDaniel P. Berrange *output = NULL; 42ac1d8878SDaniel P. Berrange *outputlen = 0; 43ac1d8878SDaniel P. Berrange 44ac1d8878SDaniel P. Berrange if (secret->file) { 45ac1d8878SDaniel P. Berrange if (secret->data) { 46ac1d8878SDaniel P. Berrange error_setg(errp, 47ac1d8878SDaniel P. Berrange "'file' and 'data' are mutually exclusive"); 48ac1d8878SDaniel P. Berrange return; 49ac1d8878SDaniel P. Berrange } 50ac1d8878SDaniel P. Berrange if (!g_file_get_contents(secret->file, &data, &length, &gerr)) { 51ac1d8878SDaniel P. Berrange error_setg(errp, 52ac1d8878SDaniel P. Berrange "Unable to read %s: %s", 53ac1d8878SDaniel P. Berrange secret->file, gerr->message); 54ac1d8878SDaniel P. Berrange g_error_free(gerr); 55ac1d8878SDaniel P. Berrange return; 56ac1d8878SDaniel P. Berrange } 57ac1d8878SDaniel P. Berrange *output = (uint8_t *)data; 58ac1d8878SDaniel P. Berrange *outputlen = length; 59ac1d8878SDaniel P. Berrange } else if (secret->data) { 60ac1d8878SDaniel P. Berrange *outputlen = strlen(secret->data); 61ac1d8878SDaniel P. Berrange *output = (uint8_t *)g_strdup(secret->data); 62ac1d8878SDaniel P. Berrange } else { 63ac1d8878SDaniel P. Berrange error_setg(errp, "Either 'file' or 'data' must be provided"); 64ac1d8878SDaniel P. Berrange } 65ac1d8878SDaniel P. Berrange } 66ac1d8878SDaniel P. Berrange 67ac1d8878SDaniel P. Berrange 68ac1d8878SDaniel P. Berrange static void qcrypto_secret_decrypt(QCryptoSecret *secret, 69ac1d8878SDaniel P. Berrange const uint8_t *input, 70ac1d8878SDaniel P. Berrange size_t inputlen, 71ac1d8878SDaniel P. Berrange uint8_t **output, 72ac1d8878SDaniel P. Berrange size_t *outputlen, 73ac1d8878SDaniel P. Berrange Error **errp) 74ac1d8878SDaniel P. Berrange { 75ac1d8878SDaniel P. Berrange uint8_t *key = NULL, *ciphertext = NULL, *iv = NULL; 76ac1d8878SDaniel P. Berrange size_t keylen, ciphertextlen, ivlen; 77ac1d8878SDaniel P. Berrange QCryptoCipher *aes = NULL; 78ac1d8878SDaniel P. Berrange uint8_t *plaintext = NULL; 79ac1d8878SDaniel P. Berrange 80ac1d8878SDaniel P. Berrange *output = NULL; 81ac1d8878SDaniel P. Berrange *outputlen = 0; 82ac1d8878SDaniel P. Berrange 83ac1d8878SDaniel P. Berrange if (qcrypto_secret_lookup(secret->keyid, 84ac1d8878SDaniel P. Berrange &key, &keylen, 85ac1d8878SDaniel P. Berrange errp) < 0) { 86ac1d8878SDaniel P. Berrange goto cleanup; 87ac1d8878SDaniel P. Berrange } 88ac1d8878SDaniel P. Berrange 89ac1d8878SDaniel P. Berrange if (keylen != 32) { 90ac1d8878SDaniel P. Berrange error_setg(errp, "Key should be 32 bytes in length"); 91ac1d8878SDaniel P. Berrange goto cleanup; 92ac1d8878SDaniel P. Berrange } 93ac1d8878SDaniel P. Berrange 94ac1d8878SDaniel P. Berrange if (!secret->iv) { 95ac1d8878SDaniel P. Berrange error_setg(errp, "IV is required to decrypt secret"); 96ac1d8878SDaniel P. Berrange goto cleanup; 97ac1d8878SDaniel P. Berrange } 98ac1d8878SDaniel P. Berrange 99ac1d8878SDaniel P. Berrange iv = qbase64_decode(secret->iv, -1, &ivlen, errp); 100ac1d8878SDaniel P. Berrange if (!iv) { 101ac1d8878SDaniel P. Berrange goto cleanup; 102ac1d8878SDaniel P. Berrange } 103ac1d8878SDaniel P. Berrange if (ivlen != 16) { 104ac1d8878SDaniel P. Berrange error_setg(errp, "IV should be 16 bytes in length not %zu", 105ac1d8878SDaniel P. Berrange ivlen); 106ac1d8878SDaniel P. Berrange goto cleanup; 107ac1d8878SDaniel P. Berrange } 108ac1d8878SDaniel P. Berrange 109ac1d8878SDaniel P. Berrange aes = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_256, 110ac1d8878SDaniel P. Berrange QCRYPTO_CIPHER_MODE_CBC, 111ac1d8878SDaniel P. Berrange key, keylen, 112ac1d8878SDaniel P. Berrange errp); 113ac1d8878SDaniel P. Berrange if (!aes) { 114ac1d8878SDaniel P. Berrange goto cleanup; 115ac1d8878SDaniel P. Berrange } 116ac1d8878SDaniel P. Berrange 117ac1d8878SDaniel P. Berrange if (qcrypto_cipher_setiv(aes, iv, ivlen, errp) < 0) { 118ac1d8878SDaniel P. Berrange goto cleanup; 119ac1d8878SDaniel P. Berrange } 120ac1d8878SDaniel P. Berrange 121ac1d8878SDaniel P. Berrange if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) { 122ac1d8878SDaniel P. Berrange ciphertext = qbase64_decode((const gchar*)input, 123ac1d8878SDaniel P. Berrange inputlen, 124ac1d8878SDaniel P. Berrange &ciphertextlen, 125ac1d8878SDaniel P. Berrange errp); 126ac1d8878SDaniel P. Berrange if (!ciphertext) { 127ac1d8878SDaniel P. Berrange goto cleanup; 128ac1d8878SDaniel P. Berrange } 129ac1d8878SDaniel P. Berrange plaintext = g_new0(uint8_t, ciphertextlen + 1); 130ac1d8878SDaniel P. Berrange } else { 131ac1d8878SDaniel P. Berrange ciphertextlen = inputlen; 132ac1d8878SDaniel P. Berrange plaintext = g_new0(uint8_t, inputlen + 1); 133ac1d8878SDaniel P. Berrange } 134ac1d8878SDaniel P. Berrange if (qcrypto_cipher_decrypt(aes, 135ac1d8878SDaniel P. Berrange ciphertext ? ciphertext : input, 136ac1d8878SDaniel P. Berrange plaintext, 137ac1d8878SDaniel P. Berrange ciphertextlen, 138ac1d8878SDaniel P. Berrange errp) < 0) { 139ac1d8878SDaniel P. Berrange plaintext = NULL; 140ac1d8878SDaniel P. Berrange goto cleanup; 141ac1d8878SDaniel P. Berrange } 142ac1d8878SDaniel P. Berrange 143ac1d8878SDaniel P. Berrange if (plaintext[ciphertextlen - 1] > 16 || 144ac1d8878SDaniel P. Berrange plaintext[ciphertextlen - 1] > ciphertextlen) { 145ac1d8878SDaniel P. Berrange error_setg(errp, "Incorrect number of padding bytes (%d) " 146ac1d8878SDaniel P. Berrange "found on decrypted data", 147ac1d8878SDaniel P. Berrange (int)plaintext[ciphertextlen - 1]); 148ac1d8878SDaniel P. Berrange g_free(plaintext); 149ac1d8878SDaniel P. Berrange plaintext = NULL; 150ac1d8878SDaniel P. Berrange goto cleanup; 151ac1d8878SDaniel P. Berrange } 152ac1d8878SDaniel P. Berrange 153ac1d8878SDaniel P. Berrange /* Even though plaintext may contain arbitrary NUL 154ac1d8878SDaniel P. Berrange * ensure it is explicitly NUL terminated. 155ac1d8878SDaniel P. Berrange */ 156ac1d8878SDaniel P. Berrange ciphertextlen -= plaintext[ciphertextlen - 1]; 157ac1d8878SDaniel P. Berrange plaintext[ciphertextlen] = '\0'; 158ac1d8878SDaniel P. Berrange 159ac1d8878SDaniel P. Berrange *output = plaintext; 160ac1d8878SDaniel P. Berrange *outputlen = ciphertextlen; 161ac1d8878SDaniel P. Berrange 162ac1d8878SDaniel P. Berrange cleanup: 163ac1d8878SDaniel P. Berrange g_free(ciphertext); 164ac1d8878SDaniel P. Berrange g_free(iv); 165ac1d8878SDaniel P. Berrange g_free(key); 166ac1d8878SDaniel P. Berrange qcrypto_cipher_free(aes); 167ac1d8878SDaniel P. Berrange } 168ac1d8878SDaniel P. Berrange 169ac1d8878SDaniel P. Berrange 170ac1d8878SDaniel P. Berrange static void qcrypto_secret_decode(const uint8_t *input, 171ac1d8878SDaniel P. Berrange size_t inputlen, 172ac1d8878SDaniel P. Berrange uint8_t **output, 173ac1d8878SDaniel P. Berrange size_t *outputlen, 174ac1d8878SDaniel P. Berrange Error **errp) 175ac1d8878SDaniel P. Berrange { 176ac1d8878SDaniel P. Berrange *output = qbase64_decode((const gchar*)input, 177ac1d8878SDaniel P. Berrange inputlen, 178ac1d8878SDaniel P. Berrange outputlen, 179ac1d8878SDaniel P. Berrange errp); 180ac1d8878SDaniel P. Berrange } 181ac1d8878SDaniel P. Berrange 182ac1d8878SDaniel P. Berrange 183ac1d8878SDaniel P. Berrange static void 184ac1d8878SDaniel P. Berrange qcrypto_secret_prop_set_loaded(Object *obj, 185ac1d8878SDaniel P. Berrange bool value, 186ac1d8878SDaniel P. Berrange Error **errp) 187ac1d8878SDaniel P. Berrange { 188ac1d8878SDaniel P. Berrange QCryptoSecret *secret = QCRYPTO_SECRET(obj); 189ac1d8878SDaniel P. Berrange 190ac1d8878SDaniel P. Berrange if (value) { 191ac1d8878SDaniel P. Berrange Error *local_err = NULL; 192ac1d8878SDaniel P. Berrange uint8_t *input = NULL; 193ac1d8878SDaniel P. Berrange size_t inputlen = 0; 194ac1d8878SDaniel P. Berrange uint8_t *output = NULL; 195ac1d8878SDaniel P. Berrange size_t outputlen = 0; 196ac1d8878SDaniel P. Berrange 197ac1d8878SDaniel P. Berrange qcrypto_secret_load_data(secret, &input, &inputlen, &local_err); 198ac1d8878SDaniel P. Berrange if (local_err) { 199ac1d8878SDaniel P. Berrange error_propagate(errp, local_err); 200ac1d8878SDaniel P. Berrange return; 201ac1d8878SDaniel P. Berrange } 202ac1d8878SDaniel P. Berrange 203ac1d8878SDaniel P. Berrange if (secret->keyid) { 204ac1d8878SDaniel P. Berrange qcrypto_secret_decrypt(secret, input, inputlen, 205ac1d8878SDaniel P. Berrange &output, &outputlen, &local_err); 206ac1d8878SDaniel P. Berrange g_free(input); 207ac1d8878SDaniel P. Berrange if (local_err) { 208ac1d8878SDaniel P. Berrange error_propagate(errp, local_err); 209ac1d8878SDaniel P. Berrange return; 210ac1d8878SDaniel P. Berrange } 211ac1d8878SDaniel P. Berrange input = output; 212ac1d8878SDaniel P. Berrange inputlen = outputlen; 213ac1d8878SDaniel P. Berrange } else { 214ac1d8878SDaniel P. Berrange if (secret->format != QCRYPTO_SECRET_FORMAT_RAW) { 215ac1d8878SDaniel P. Berrange qcrypto_secret_decode(input, inputlen, 216ac1d8878SDaniel P. Berrange &output, &outputlen, &local_err); 217ac1d8878SDaniel P. Berrange g_free(input); 218ac1d8878SDaniel P. Berrange if (local_err) { 219ac1d8878SDaniel P. Berrange error_propagate(errp, local_err); 220ac1d8878SDaniel P. Berrange return; 221ac1d8878SDaniel P. Berrange } 222ac1d8878SDaniel P. Berrange input = output; 223ac1d8878SDaniel P. Berrange inputlen = outputlen; 224ac1d8878SDaniel P. Berrange } 225ac1d8878SDaniel P. Berrange } 226ac1d8878SDaniel P. Berrange 227ac1d8878SDaniel P. Berrange secret->rawdata = input; 228ac1d8878SDaniel P. Berrange secret->rawlen = inputlen; 229ac1d8878SDaniel P. Berrange } else { 230ac1d8878SDaniel P. Berrange g_free(secret->rawdata); 231ac1d8878SDaniel P. Berrange secret->rawlen = 0; 232ac1d8878SDaniel P. Berrange } 233ac1d8878SDaniel P. Berrange } 234ac1d8878SDaniel P. Berrange 235ac1d8878SDaniel P. Berrange 236ac1d8878SDaniel P. Berrange static bool 237ac1d8878SDaniel P. Berrange qcrypto_secret_prop_get_loaded(Object *obj, 238ac1d8878SDaniel P. Berrange Error **errp G_GNUC_UNUSED) 239ac1d8878SDaniel P. Berrange { 240ac1d8878SDaniel P. Berrange QCryptoSecret *secret = QCRYPTO_SECRET(obj); 241ac1d8878SDaniel P. Berrange return secret->data != NULL; 242ac1d8878SDaniel P. Berrange } 243ac1d8878SDaniel P. Berrange 244ac1d8878SDaniel P. Berrange 245ac1d8878SDaniel P. Berrange static void 246ac1d8878SDaniel P. Berrange qcrypto_secret_prop_set_format(Object *obj, 247ac1d8878SDaniel P. Berrange int value, 248ac1d8878SDaniel P. Berrange Error **errp G_GNUC_UNUSED) 249ac1d8878SDaniel P. Berrange { 250ac1d8878SDaniel P. Berrange QCryptoSecret *creds = QCRYPTO_SECRET(obj); 251ac1d8878SDaniel P. Berrange 252ac1d8878SDaniel P. Berrange creds->format = value; 253ac1d8878SDaniel P. Berrange } 254ac1d8878SDaniel P. Berrange 255ac1d8878SDaniel P. Berrange 256ac1d8878SDaniel P. Berrange static int 257ac1d8878SDaniel P. Berrange qcrypto_secret_prop_get_format(Object *obj, 258ac1d8878SDaniel P. Berrange Error **errp G_GNUC_UNUSED) 259ac1d8878SDaniel P. Berrange { 260ac1d8878SDaniel P. Berrange QCryptoSecret *creds = QCRYPTO_SECRET(obj); 261ac1d8878SDaniel P. Berrange 262ac1d8878SDaniel P. Berrange return creds->format; 263ac1d8878SDaniel P. Berrange } 264ac1d8878SDaniel P. Berrange 265ac1d8878SDaniel P. Berrange 266ac1d8878SDaniel P. Berrange static void 267ac1d8878SDaniel P. Berrange qcrypto_secret_prop_set_data(Object *obj, 268ac1d8878SDaniel P. Berrange const char *value, 269ac1d8878SDaniel P. Berrange Error **errp) 270ac1d8878SDaniel P. Berrange { 271ac1d8878SDaniel P. Berrange QCryptoSecret *secret = QCRYPTO_SECRET(obj); 272ac1d8878SDaniel P. Berrange 273ac1d8878SDaniel P. Berrange g_free(secret->data); 274ac1d8878SDaniel P. Berrange secret->data = g_strdup(value); 275ac1d8878SDaniel P. Berrange } 276ac1d8878SDaniel P. Berrange 277ac1d8878SDaniel P. Berrange 278ac1d8878SDaniel P. Berrange static char * 279ac1d8878SDaniel P. Berrange qcrypto_secret_prop_get_data(Object *obj, 280ac1d8878SDaniel P. Berrange Error **errp) 281ac1d8878SDaniel P. Berrange { 282ac1d8878SDaniel P. Berrange QCryptoSecret *secret = QCRYPTO_SECRET(obj); 283ac1d8878SDaniel P. Berrange return g_strdup(secret->data); 284ac1d8878SDaniel P. Berrange } 285ac1d8878SDaniel P. Berrange 286ac1d8878SDaniel P. Berrange 287ac1d8878SDaniel P. Berrange static void 288ac1d8878SDaniel P. Berrange qcrypto_secret_prop_set_file(Object *obj, 289ac1d8878SDaniel P. Berrange const char *value, 290ac1d8878SDaniel P. Berrange Error **errp) 291ac1d8878SDaniel P. Berrange { 292ac1d8878SDaniel P. Berrange QCryptoSecret *secret = QCRYPTO_SECRET(obj); 293ac1d8878SDaniel P. Berrange 294ac1d8878SDaniel P. Berrange g_free(secret->file); 295ac1d8878SDaniel P. Berrange secret->file = g_strdup(value); 296ac1d8878SDaniel P. Berrange } 297ac1d8878SDaniel P. Berrange 298ac1d8878SDaniel P. Berrange 299ac1d8878SDaniel P. Berrange static char * 300ac1d8878SDaniel P. Berrange qcrypto_secret_prop_get_file(Object *obj, 301ac1d8878SDaniel P. Berrange Error **errp) 302ac1d8878SDaniel P. Berrange { 303ac1d8878SDaniel P. Berrange QCryptoSecret *secret = QCRYPTO_SECRET(obj); 304ac1d8878SDaniel P. Berrange return g_strdup(secret->file); 305ac1d8878SDaniel P. Berrange } 306ac1d8878SDaniel P. Berrange 307ac1d8878SDaniel P. Berrange 308ac1d8878SDaniel P. Berrange static void 309ac1d8878SDaniel P. Berrange qcrypto_secret_prop_set_iv(Object *obj, 310ac1d8878SDaniel P. Berrange const char *value, 311ac1d8878SDaniel P. Berrange Error **errp) 312ac1d8878SDaniel P. Berrange { 313ac1d8878SDaniel P. Berrange QCryptoSecret *secret = QCRYPTO_SECRET(obj); 314ac1d8878SDaniel P. Berrange 315ac1d8878SDaniel P. Berrange g_free(secret->iv); 316ac1d8878SDaniel P. Berrange secret->iv = g_strdup(value); 317ac1d8878SDaniel P. Berrange } 318ac1d8878SDaniel P. Berrange 319ac1d8878SDaniel P. Berrange 320ac1d8878SDaniel P. Berrange static char * 321ac1d8878SDaniel P. Berrange qcrypto_secret_prop_get_iv(Object *obj, 322ac1d8878SDaniel P. Berrange Error **errp) 323ac1d8878SDaniel P. Berrange { 324ac1d8878SDaniel P. Berrange QCryptoSecret *secret = QCRYPTO_SECRET(obj); 325ac1d8878SDaniel P. Berrange return g_strdup(secret->iv); 326ac1d8878SDaniel P. Berrange } 327ac1d8878SDaniel P. Berrange 328ac1d8878SDaniel P. Berrange 329ac1d8878SDaniel P. Berrange static void 330ac1d8878SDaniel P. Berrange qcrypto_secret_prop_set_keyid(Object *obj, 331ac1d8878SDaniel P. Berrange const char *value, 332ac1d8878SDaniel P. Berrange Error **errp) 333ac1d8878SDaniel P. Berrange { 334ac1d8878SDaniel P. Berrange QCryptoSecret *secret = QCRYPTO_SECRET(obj); 335ac1d8878SDaniel P. Berrange 336ac1d8878SDaniel P. Berrange g_free(secret->keyid); 337ac1d8878SDaniel P. Berrange secret->keyid = g_strdup(value); 338ac1d8878SDaniel P. Berrange } 339ac1d8878SDaniel P. Berrange 340ac1d8878SDaniel P. Berrange 341ac1d8878SDaniel P. Berrange static char * 342ac1d8878SDaniel P. Berrange qcrypto_secret_prop_get_keyid(Object *obj, 343ac1d8878SDaniel P. Berrange Error **errp) 344ac1d8878SDaniel P. Berrange { 345ac1d8878SDaniel P. Berrange QCryptoSecret *secret = QCRYPTO_SECRET(obj); 346ac1d8878SDaniel P. Berrange return g_strdup(secret->keyid); 347ac1d8878SDaniel P. Berrange } 348ac1d8878SDaniel P. Berrange 349ac1d8878SDaniel P. Berrange 350ac1d8878SDaniel P. Berrange static void 351ac1d8878SDaniel P. Berrange qcrypto_secret_complete(UserCreatable *uc, Error **errp) 352ac1d8878SDaniel P. Berrange { 353ac1d8878SDaniel P. Berrange object_property_set_bool(OBJECT(uc), true, "loaded", errp); 354ac1d8878SDaniel P. Berrange } 355ac1d8878SDaniel P. Berrange 356ac1d8878SDaniel P. Berrange 357ac1d8878SDaniel P. Berrange static void 358ac1d8878SDaniel P. Berrange qcrypto_secret_finalize(Object *obj) 359ac1d8878SDaniel P. Berrange { 360ac1d8878SDaniel P. Berrange QCryptoSecret *secret = QCRYPTO_SECRET(obj); 361ac1d8878SDaniel P. Berrange 362ac1d8878SDaniel P. Berrange g_free(secret->iv); 363ac1d8878SDaniel P. Berrange g_free(secret->file); 364ac1d8878SDaniel P. Berrange g_free(secret->keyid); 365ac1d8878SDaniel P. Berrange g_free(secret->rawdata); 366ac1d8878SDaniel P. Berrange g_free(secret->data); 367ac1d8878SDaniel P. Berrange } 368ac1d8878SDaniel P. Berrange 369ac1d8878SDaniel P. Berrange static void 370ac1d8878SDaniel P. Berrange qcrypto_secret_class_init(ObjectClass *oc, void *data) 371ac1d8878SDaniel P. Berrange { 372ac1d8878SDaniel P. Berrange UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); 373ac1d8878SDaniel P. Berrange 374ac1d8878SDaniel P. Berrange ucc->complete = qcrypto_secret_complete; 3759884abeeSDaniel P. Berrange 3769884abeeSDaniel P. Berrange object_class_property_add_bool(oc, "loaded", 3779884abeeSDaniel P. Berrange qcrypto_secret_prop_get_loaded, 3789884abeeSDaniel P. Berrange qcrypto_secret_prop_set_loaded, 3799884abeeSDaniel P. Berrange NULL); 3809884abeeSDaniel P. Berrange object_class_property_add_enum(oc, "format", 3819884abeeSDaniel P. Berrange "QCryptoSecretFormat", 382f7abe0ecSMarc-André Lureau &QCryptoSecretFormat_lookup, 3839884abeeSDaniel P. Berrange qcrypto_secret_prop_get_format, 3849884abeeSDaniel P. Berrange qcrypto_secret_prop_set_format, 3859884abeeSDaniel P. Berrange NULL); 3869884abeeSDaniel P. Berrange object_class_property_add_str(oc, "data", 3879884abeeSDaniel P. Berrange qcrypto_secret_prop_get_data, 3889884abeeSDaniel P. Berrange qcrypto_secret_prop_set_data, 3899884abeeSDaniel P. Berrange NULL); 3909884abeeSDaniel P. Berrange object_class_property_add_str(oc, "file", 3919884abeeSDaniel P. Berrange qcrypto_secret_prop_get_file, 3929884abeeSDaniel P. Berrange qcrypto_secret_prop_set_file, 3939884abeeSDaniel P. Berrange NULL); 3949884abeeSDaniel P. Berrange object_class_property_add_str(oc, "keyid", 3959884abeeSDaniel P. Berrange qcrypto_secret_prop_get_keyid, 3969884abeeSDaniel P. Berrange qcrypto_secret_prop_set_keyid, 3979884abeeSDaniel P. Berrange NULL); 3989884abeeSDaniel P. Berrange object_class_property_add_str(oc, "iv", 3999884abeeSDaniel P. Berrange qcrypto_secret_prop_get_iv, 4009884abeeSDaniel P. Berrange qcrypto_secret_prop_set_iv, 4019884abeeSDaniel P. Berrange NULL); 402ac1d8878SDaniel P. Berrange } 403ac1d8878SDaniel P. Berrange 404ac1d8878SDaniel P. Berrange 405ac1d8878SDaniel P. Berrange int qcrypto_secret_lookup(const char *secretid, 406ac1d8878SDaniel P. Berrange uint8_t **data, 407ac1d8878SDaniel P. Berrange size_t *datalen, 408ac1d8878SDaniel P. Berrange Error **errp) 409ac1d8878SDaniel P. Berrange { 410ac1d8878SDaniel P. Berrange Object *obj; 411ac1d8878SDaniel P. Berrange QCryptoSecret *secret; 412ac1d8878SDaniel P. Berrange 413ac1d8878SDaniel P. Berrange obj = object_resolve_path_component( 414ac1d8878SDaniel P. Berrange object_get_objects_root(), secretid); 415ac1d8878SDaniel P. Berrange if (!obj) { 416ac1d8878SDaniel P. Berrange error_setg(errp, "No secret with id '%s'", secretid); 417ac1d8878SDaniel P. Berrange return -1; 418ac1d8878SDaniel P. Berrange } 419ac1d8878SDaniel P. Berrange 420ac1d8878SDaniel P. Berrange secret = (QCryptoSecret *) 421ac1d8878SDaniel P. Berrange object_dynamic_cast(obj, 422ac1d8878SDaniel P. Berrange TYPE_QCRYPTO_SECRET); 423ac1d8878SDaniel P. Berrange if (!secret) { 424ac1d8878SDaniel P. Berrange error_setg(errp, "Object with id '%s' is not a secret", 425ac1d8878SDaniel P. Berrange secretid); 426ac1d8878SDaniel P. Berrange return -1; 427ac1d8878SDaniel P. Berrange } 428ac1d8878SDaniel P. Berrange 429ac1d8878SDaniel P. Berrange if (!secret->rawdata) { 430ac1d8878SDaniel P. Berrange error_setg(errp, "Secret with id '%s' has no data", 431ac1d8878SDaniel P. Berrange secretid); 432ac1d8878SDaniel P. Berrange return -1; 433ac1d8878SDaniel P. Berrange } 434ac1d8878SDaniel P. Berrange 435d341d9f3SPeter Maydell *data = g_new0(uint8_t, secret->rawlen + 1); 436ac1d8878SDaniel P. Berrange memcpy(*data, secret->rawdata, secret->rawlen); 437ac1d8878SDaniel P. Berrange (*data)[secret->rawlen] = '\0'; 438ac1d8878SDaniel P. Berrange *datalen = secret->rawlen; 439ac1d8878SDaniel P. Berrange 440ac1d8878SDaniel P. Berrange return 0; 441ac1d8878SDaniel P. Berrange } 442ac1d8878SDaniel P. Berrange 443ac1d8878SDaniel P. Berrange 444ac1d8878SDaniel P. Berrange char *qcrypto_secret_lookup_as_utf8(const char *secretid, 445ac1d8878SDaniel P. Berrange Error **errp) 446ac1d8878SDaniel P. Berrange { 447ac1d8878SDaniel P. Berrange uint8_t *data; 448ac1d8878SDaniel P. Berrange size_t datalen; 449ac1d8878SDaniel P. Berrange 450ac1d8878SDaniel P. Berrange if (qcrypto_secret_lookup(secretid, 451ac1d8878SDaniel P. Berrange &data, 452ac1d8878SDaniel P. Berrange &datalen, 453ac1d8878SDaniel P. Berrange errp) < 0) { 454ac1d8878SDaniel P. Berrange return NULL; 455ac1d8878SDaniel P. Berrange } 456ac1d8878SDaniel P. Berrange 457ac1d8878SDaniel P. Berrange if (!g_utf8_validate((const gchar*)data, datalen, NULL)) { 458ac1d8878SDaniel P. Berrange error_setg(errp, 459ac1d8878SDaniel P. Berrange "Data from secret %s is not valid UTF-8", 460ac1d8878SDaniel P. Berrange secretid); 461ac1d8878SDaniel P. Berrange g_free(data); 462ac1d8878SDaniel P. Berrange return NULL; 463ac1d8878SDaniel P. Berrange } 464ac1d8878SDaniel P. Berrange 465ac1d8878SDaniel P. Berrange return (char *)data; 466ac1d8878SDaniel P. Berrange } 467ac1d8878SDaniel P. Berrange 468ac1d8878SDaniel P. Berrange 469ac1d8878SDaniel P. Berrange char *qcrypto_secret_lookup_as_base64(const char *secretid, 470ac1d8878SDaniel P. Berrange Error **errp) 471ac1d8878SDaniel P. Berrange { 472ac1d8878SDaniel P. Berrange uint8_t *data; 473ac1d8878SDaniel P. Berrange size_t datalen; 474ac1d8878SDaniel P. Berrange char *ret; 475ac1d8878SDaniel P. Berrange 476ac1d8878SDaniel P. Berrange if (qcrypto_secret_lookup(secretid, 477ac1d8878SDaniel P. Berrange &data, 478ac1d8878SDaniel P. Berrange &datalen, 479ac1d8878SDaniel P. Berrange errp) < 0) { 480ac1d8878SDaniel P. Berrange return NULL; 481ac1d8878SDaniel P. Berrange } 482ac1d8878SDaniel P. Berrange 483ac1d8878SDaniel P. Berrange ret = g_base64_encode(data, datalen); 484ac1d8878SDaniel P. Berrange g_free(data); 485ac1d8878SDaniel P. Berrange return ret; 486ac1d8878SDaniel P. Berrange } 487ac1d8878SDaniel P. Berrange 488ac1d8878SDaniel P. Berrange 489ac1d8878SDaniel P. Berrange static const TypeInfo qcrypto_secret_info = { 490ac1d8878SDaniel P. Berrange .parent = TYPE_OBJECT, 491ac1d8878SDaniel P. Berrange .name = TYPE_QCRYPTO_SECRET, 492ac1d8878SDaniel P. Berrange .instance_size = sizeof(QCryptoSecret), 493ac1d8878SDaniel P. Berrange .instance_finalize = qcrypto_secret_finalize, 494ac1d8878SDaniel P. Berrange .class_size = sizeof(QCryptoSecretClass), 495ac1d8878SDaniel P. Berrange .class_init = qcrypto_secret_class_init, 496ac1d8878SDaniel P. Berrange .interfaces = (InterfaceInfo[]) { 497ac1d8878SDaniel P. Berrange { TYPE_USER_CREATABLE }, 498ac1d8878SDaniel P. Berrange { } 499ac1d8878SDaniel P. Berrange } 500ac1d8878SDaniel P. Berrange }; 501ac1d8878SDaniel P. Berrange 502ac1d8878SDaniel P. Berrange 503ac1d8878SDaniel P. Berrange static void 504ac1d8878SDaniel P. Berrange qcrypto_secret_register_types(void) 505ac1d8878SDaniel P. Berrange { 506ac1d8878SDaniel P. Berrange type_register_static(&qcrypto_secret_info); 507ac1d8878SDaniel P. Berrange } 508ac1d8878SDaniel P. Berrange 509ac1d8878SDaniel P. Berrange 510ac1d8878SDaniel P. Berrange type_init(qcrypto_secret_register_types); 511