/* * QEMU crypto secret support * * Copyright (c) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . * */ #include "qemu/osdep.h" #include "crypto/secret.h" #include "crypto/cipher.h" #include "qapi/error.h" #include "qom/object_interfaces.h" #include "qemu/base64.h" #include "trace.h" static void qcrypto_secret_load_data(QCryptoSecret *secret, uint8_t **output, size_t *outputlen, Error **errp) { char *data = NULL; size_t length = 0; GError *gerr = NULL; *output = NULL; *outputlen = 0; if (secret->file) { if (secret->data) { error_setg(errp, "'file' and 'data' are mutually exclusive"); return; } if (!g_file_get_contents(secret->file, &data, &length, &gerr)) { error_setg(errp, "Unable to read %s: %s", secret->file, gerr->message); g_error_free(gerr); return; } *output = (uint8_t *)data; *outputlen = length; } else if (secret->data) { *outputlen = strlen(secret->data); *output = (uint8_t *)g_strdup(secret->data); } else { error_setg(errp, "Either 'file' or 'data' must be provided"); } } static void qcrypto_secret_decrypt(QCryptoSecret *secret, const uint8_t *input, size_t inputlen, uint8_t **output, size_t *outputlen, Error **errp) { uint8_t *key = NULL, *ciphertext = NULL, *iv = NULL; size_t keylen, ciphertextlen, ivlen; QCryptoCipher *aes = NULL; uint8_t *plaintext = NULL; *output = NULL; *outputlen = 0; if (qcrypto_secret_lookup(secret->keyid, &key, &keylen, errp) < 0) { goto cleanup; } if (keylen != 32) { error_setg(errp, "Key should be 32 bytes in length"); goto cleanup; } if (!secret->iv) { error_setg(errp, "IV is required to decrypt secret"); goto cleanup; } iv = qbase64_decode(secret->iv, -1, &ivlen, errp); if (!iv) { goto cleanup; } if (ivlen != 16) { error_setg(errp, "IV should be 16 bytes in length not %zu", ivlen); goto cleanup; } aes = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_256, QCRYPTO_CIPHER_MODE_CBC, key, keylen, errp); if (!aes) { goto cleanup; } if (qcrypto_cipher_setiv(a
---
- project:
    name: kuberef-project-view
    project-name: kuberef
    views:
      - project-view

- project:
    name: kuberef-info
    project: kuberef
    project-name: kuberef
    build-node: centos7-builder-2c-1g
    jobs:
      - gerrit-info-yaml-verify
operty_add_str(oc, "iv", qcrypto_secret_prop_get_iv, qcrypto_secret_prop_set_iv, NULL); } int qcrypto_secret_lookup(const char *secretid, uint8_t **data, size_t *datalen, Error **errp) { Object *obj; QCryptoSecret *secret; obj = object_resolve_path_component( object_get_objects_root(), secretid); if (!obj) { error_setg(errp, "No secret with id '%s'", secretid); return -1; } secret = (QCryptoSecret *) object_dynamic_cast(obj, TYPE_QCRYPTO_SECRET); if (!secret) { error_setg(errp, "Object with id '%s' is not a secret", secretid); return -1; } if (!secret->rawdata) { error_setg(errp, "Secret with id '%s' has no data", secretid); return -1; } *data = g_new0(uint8_t, secret->rawlen + 1); memcpy(*data, secret->rawdata, secret->rawlen); (*data)[secret->rawlen] = '\0'; *datalen = secret->rawlen; return 0; } char *qcrypto_secret_lookup_as_utf8(const char *secretid, Error **errp) { uint8_t *data; size_t datalen; if (qcrypto_secret_lookup(secretid, &data, &datalen, errp) < 0) { return NULL; } if (!g_utf8_validate((const gchar*)data, datalen, NULL)) { error_setg(errp, "Data from secret %s is not valid UTF-8", secretid); g_free(data); return NULL; } return (char *)data; } char *qcrypto_secret_lookup_as_base64(const char *secretid, Error **errp) { uint8_t *data; size_t datalen; char *ret; if (qcrypto_secret_lookup(secretid, &data, &datalen, errp) < 0) { return NULL; } ret = g_base64_encode(data, datalen); g_free(data); return ret; } static const TypeInfo qcrypto_secret_info = { .parent = TYPE_OBJECT, .name = TYPE_QCRYPTO_SECRET, .instance_size = sizeof(QCryptoSecret), .instance_finalize = qcrypto_secret_finalize, .class_size = sizeof(QCryptoSecretClass), .class_init = qcrypto_secret_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_USER_CREATABLE }, { } } }; static void qcrypto_secret_register_types(void) { type_register_static(&qcrypto_secret_info); } type_init(qcrypto_secret_register_types);