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