14862bd3cSAlexey Krasikov /*
24862bd3cSAlexey Krasikov * QEMU crypto secret support
34862bd3cSAlexey Krasikov *
44862bd3cSAlexey Krasikov * Copyright (c) 2015 Red Hat, Inc.
54862bd3cSAlexey Krasikov *
64862bd3cSAlexey Krasikov * This library is free software; you can redistribute it and/or
74862bd3cSAlexey Krasikov * modify it under the terms of the GNU Lesser General Public
84862bd3cSAlexey Krasikov * License as published by the Free Software Foundation; either
94862bd3cSAlexey Krasikov * version 2.1 of the License, or (at your option) any later version.
104862bd3cSAlexey Krasikov *
114862bd3cSAlexey Krasikov * This library is distributed in the hope that it will be useful,
124862bd3cSAlexey Krasikov * but WITHOUT ANY WARRANTY; without even the implied warranty of
134862bd3cSAlexey Krasikov * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
144862bd3cSAlexey Krasikov * Lesser General Public License for more details.
154862bd3cSAlexey Krasikov *
164862bd3cSAlexey Krasikov * You should have received a copy of the GNU Lesser General Public
174862bd3cSAlexey Krasikov * License along with this library; if not, see <http://www.gnu.org/licenses/>.
184862bd3cSAlexey Krasikov *
194862bd3cSAlexey Krasikov */
204862bd3cSAlexey Krasikov
214862bd3cSAlexey Krasikov #include "qemu/osdep.h"
224862bd3cSAlexey Krasikov #include "crypto/secret_common.h"
234862bd3cSAlexey Krasikov #include "crypto/cipher.h"
244862bd3cSAlexey Krasikov #include "qapi/error.h"
254862bd3cSAlexey Krasikov #include "qom/object_interfaces.h"
264862bd3cSAlexey Krasikov #include "qemu/base64.h"
274862bd3cSAlexey Krasikov #include "qemu/module.h"
284862bd3cSAlexey Krasikov #include "trace.h"
294862bd3cSAlexey Krasikov
304862bd3cSAlexey Krasikov
qcrypto_secret_decrypt(QCryptoSecretCommon * secret,const uint8_t * input,size_t inputlen,uint8_t ** output,size_t * outputlen,Error ** errp)314862bd3cSAlexey Krasikov static void qcrypto_secret_decrypt(QCryptoSecretCommon *secret,
324862bd3cSAlexey Krasikov const uint8_t *input,
334862bd3cSAlexey Krasikov size_t inputlen,
344862bd3cSAlexey Krasikov uint8_t **output,
354862bd3cSAlexey Krasikov size_t *outputlen,
364862bd3cSAlexey Krasikov Error **errp)
374862bd3cSAlexey Krasikov {
384862bd3cSAlexey Krasikov g_autofree uint8_t *iv = NULL;
394862bd3cSAlexey Krasikov g_autofree uint8_t *key = NULL;
404862bd3cSAlexey Krasikov g_autofree uint8_t *ciphertext = NULL;
414862bd3cSAlexey Krasikov size_t keylen, ciphertextlen, ivlen;
424862bd3cSAlexey Krasikov g_autoptr(QCryptoCipher) aes = NULL;
434862bd3cSAlexey Krasikov g_autofree uint8_t *plaintext = NULL;
444862bd3cSAlexey Krasikov
454862bd3cSAlexey Krasikov *output = NULL;
464862bd3cSAlexey Krasikov *outputlen = 0;
474862bd3cSAlexey Krasikov
484862bd3cSAlexey Krasikov if (qcrypto_secret_lookup(secret->keyid,
494862bd3cSAlexey Krasikov &key, &keylen,
504862bd3cSAlexey Krasikov errp) < 0) {
514862bd3cSAlexey Krasikov return;
524862bd3cSAlexey Krasikov }
534862bd3cSAlexey Krasikov
544862bd3cSAlexey Krasikov if (keylen != 32) {
554862bd3cSAlexey Krasikov error_setg(errp, "Key should be 32 bytes in length");
564862bd3cSAlexey Krasikov return;
574862bd3cSAlexey Krasikov }
584862bd3cSAlexey Krasikov
594862bd3cSAlexey Krasikov if (!secret->iv) {
604862bd3cSAlexey Krasikov error_setg(errp, "IV is required to decrypt secret");
614862bd3cSAlexey Krasikov return;
624862bd3cSAlexey Krasikov }
634862bd3cSAlexey Krasikov
644862bd3cSAlexey Krasikov iv = qbase64_decode(secret->iv, -1, &ivlen, errp);
654862bd3cSAlexey Krasikov if (!iv) {
664862bd3cSAlexey Krasikov return;
674862bd3cSAlexey Krasikov }
684862bd3cSAlexey Krasikov if (ivlen != 16) {
694862bd3cSAlexey Krasikov error_setg(errp, "IV should be 16 bytes in length not %zu",
704862bd3cSAlexey Krasikov ivlen);
714862bd3cSAlexey Krasikov return;
724862bd3cSAlexey Krasikov }
734862bd3cSAlexey Krasikov
744862bd3cSAlexey Krasikov aes = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_256,
754862bd3cSAlexey Krasikov QCRYPTO_CIPHER_MODE_CBC,
764862bd3cSAlexey Krasikov key, keylen,
774862bd3cSAlexey Krasikov errp);
784862bd3cSAlexey Krasikov if (!aes) {
794862bd3cSAlexey Krasikov return;
804862bd3cSAlexey Krasikov }
814862bd3cSAlexey Krasikov
824862bd3cSAlexey Krasikov if (qcrypto_cipher_setiv(aes, iv, ivlen, errp) < 0) {
834862bd3cSAlexey Krasikov return;
844862bd3cSAlexey Krasikov }
854862bd3cSAlexey Krasikov
864862bd3cSAlexey Krasikov if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) {
874862bd3cSAlexey Krasikov ciphertext = qbase64_decode((const gchar *)input,
884862bd3cSAlexey Krasikov inputlen,
894862bd3cSAlexey Krasikov &ciphertextlen,
904862bd3cSAlexey Krasikov errp);
914862bd3cSAlexey Krasikov if (!ciphertext) {
924862bd3cSAlexey Krasikov return;
934862bd3cSAlexey Krasikov }
944862bd3cSAlexey Krasikov plaintext = g_new0(uint8_t, ciphertextlen + 1);
954862bd3cSAlexey Krasikov } else {
964862bd3cSAlexey Krasikov ciphertextlen = inputlen;
974862bd3cSAlexey Krasikov plaintext = g_new0(uint8_t, inputlen + 1);
984862bd3cSAlexey Krasikov }
994862bd3cSAlexey Krasikov if (qcrypto_cipher_decrypt(aes,
1004862bd3cSAlexey Krasikov ciphertext ? ciphertext : input,
1014862bd3cSAlexey Krasikov plaintext,
1024862bd3cSAlexey Krasikov ciphertextlen,
1034862bd3cSAlexey Krasikov errp) < 0) {
1044862bd3cSAlexey Krasikov return;
1054862bd3cSAlexey Krasikov }
1064862bd3cSAlexey Krasikov
1074862bd3cSAlexey Krasikov if (plaintext[ciphertextlen - 1] > 16 ||
1084862bd3cSAlexey Krasikov plaintext[ciphertextlen - 1] > ciphertextlen) {
1094862bd3cSAlexey Krasikov error_setg(errp, "Incorrect number of padding bytes (%d) "
1104862bd3cSAlexey Krasikov "found on decrypted data",
1114862bd3cSAlexey Krasikov (int)plaintext[ciphertextlen - 1]);
1124862bd3cSAlexey Krasikov return;
1134862bd3cSAlexey Krasikov }
1144862bd3cSAlexey Krasikov
1154862bd3cSAlexey Krasikov /*
1164862bd3cSAlexey Krasikov * Even though plaintext may contain arbitrary NUL
1174862bd3cSAlexey Krasikov * ensure it is explicitly NUL terminated.
1184862bd3cSAlexey Krasikov */
1194862bd3cSAlexey Krasikov ciphertextlen -= plaintext[ciphertextlen - 1];
1204862bd3cSAlexey Krasikov plaintext[ciphertextlen] = '\0';
1214862bd3cSAlexey Krasikov
1224862bd3cSAlexey Krasikov *output = g_steal_pointer(&plaintext);
1234862bd3cSAlexey Krasikov *outputlen = ciphertextlen;
1244862bd3cSAlexey Krasikov }
1254862bd3cSAlexey Krasikov
1264862bd3cSAlexey Krasikov
qcrypto_secret_decode(const uint8_t * input,size_t inputlen,uint8_t ** output,size_t * outputlen,Error ** errp)1274862bd3cSAlexey Krasikov static void qcrypto_secret_decode(const uint8_t *input,
1284862bd3cSAlexey Krasikov size_t inputlen,
1294862bd3cSAlexey Krasikov uint8_t **output,
1304862bd3cSAlexey Krasikov size_t *outputlen,
1314862bd3cSAlexey Krasikov Error **errp)
1324862bd3cSAlexey Krasikov {
1334862bd3cSAlexey Krasikov *output = qbase64_decode((const gchar *)input,
1344862bd3cSAlexey Krasikov inputlen,
1354862bd3cSAlexey Krasikov outputlen,
1364862bd3cSAlexey Krasikov errp);
1374862bd3cSAlexey Krasikov }
1384862bd3cSAlexey Krasikov
1394862bd3cSAlexey Krasikov
1404862bd3cSAlexey Krasikov static void
qcrypto_secret_complete(UserCreatable * uc,Error ** errp)141*0310641cSPaolo Bonzini qcrypto_secret_complete(UserCreatable *uc, Error **errp)
1424862bd3cSAlexey Krasikov {
143*0310641cSPaolo Bonzini QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(uc);
1444862bd3cSAlexey Krasikov QCryptoSecretCommonClass *sec_class
145*0310641cSPaolo Bonzini = QCRYPTO_SECRET_COMMON_GET_CLASS(uc);
1464862bd3cSAlexey Krasikov
1474862bd3cSAlexey Krasikov Error *local_err = NULL;
1484862bd3cSAlexey Krasikov uint8_t *input = NULL;
1494862bd3cSAlexey Krasikov size_t inputlen = 0;
1504862bd3cSAlexey Krasikov uint8_t *output = NULL;
1514862bd3cSAlexey Krasikov size_t outputlen = 0;
1524862bd3cSAlexey Krasikov
1534862bd3cSAlexey Krasikov if (sec_class->load_data) {
1544862bd3cSAlexey Krasikov sec_class->load_data(secret, &input, &inputlen, &local_err);
1554862bd3cSAlexey Krasikov if (local_err) {
1564862bd3cSAlexey Krasikov error_propagate(errp, local_err);
1574862bd3cSAlexey Krasikov return;
1584862bd3cSAlexey Krasikov }
1594862bd3cSAlexey Krasikov } else {
1604862bd3cSAlexey Krasikov error_setg(errp, "%s provides no 'load_data' method'",
161*0310641cSPaolo Bonzini object_get_typename(OBJECT(uc)));
1624862bd3cSAlexey Krasikov return;
1634862bd3cSAlexey Krasikov }
1644862bd3cSAlexey Krasikov
1654862bd3cSAlexey Krasikov if (secret->keyid) {
1664862bd3cSAlexey Krasikov qcrypto_secret_decrypt(secret, input, inputlen,
1674862bd3cSAlexey Krasikov &output, &outputlen, &local_err);
1684862bd3cSAlexey Krasikov g_free(input);
1694862bd3cSAlexey Krasikov if (local_err) {
1704862bd3cSAlexey Krasikov error_propagate(errp, local_err);
1714862bd3cSAlexey Krasikov return;
1724862bd3cSAlexey Krasikov }
1734862bd3cSAlexey Krasikov input = output;
1744862bd3cSAlexey Krasikov inputlen = outputlen;
1754862bd3cSAlexey Krasikov } else {
1764862bd3cSAlexey Krasikov if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) {
1774862bd3cSAlexey Krasikov qcrypto_secret_decode(input, inputlen,
1784862bd3cSAlexey Krasikov &output, &outputlen, &local_err);
1794862bd3cSAlexey Krasikov g_free(input);
1804862bd3cSAlexey Krasikov if (local_err) {
1814862bd3cSAlexey Krasikov error_propagate(errp, local_err);
1824862bd3cSAlexey Krasikov return;
1834862bd3cSAlexey Krasikov }
1844862bd3cSAlexey Krasikov input = output;
1854862bd3cSAlexey Krasikov inputlen = outputlen;
1864862bd3cSAlexey Krasikov }
1874862bd3cSAlexey Krasikov }
1884862bd3cSAlexey Krasikov
1894862bd3cSAlexey Krasikov secret->rawdata = input;
1904862bd3cSAlexey Krasikov secret->rawlen = inputlen;
1914862bd3cSAlexey Krasikov }
1924862bd3cSAlexey Krasikov
1934862bd3cSAlexey Krasikov
1944862bd3cSAlexey Krasikov static bool
qcrypto_secret_prop_get_loaded(Object * obj,Error ** errp G_GNUC_UNUSED)1954862bd3cSAlexey Krasikov qcrypto_secret_prop_get_loaded(Object *obj,
1964862bd3cSAlexey Krasikov Error **errp G_GNUC_UNUSED)
1974862bd3cSAlexey Krasikov {
1984862bd3cSAlexey Krasikov QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj);
1994862bd3cSAlexey Krasikov return secret->rawdata != NULL;
2004862bd3cSAlexey Krasikov }
2014862bd3cSAlexey Krasikov
2024862bd3cSAlexey Krasikov
2034862bd3cSAlexey Krasikov static void
qcrypto_secret_prop_set_format(Object * obj,int value,Error ** errp G_GNUC_UNUSED)2044862bd3cSAlexey Krasikov qcrypto_secret_prop_set_format(Object *obj,
2054862bd3cSAlexey Krasikov int value,
2064862bd3cSAlexey Krasikov Error **errp G_GNUC_UNUSED)
2074862bd3cSAlexey Krasikov {
2084862bd3cSAlexey Krasikov QCryptoSecretCommon *creds = QCRYPTO_SECRET_COMMON(obj);
2094862bd3cSAlexey Krasikov creds->format = value;
2104862bd3cSAlexey Krasikov }
2114862bd3cSAlexey Krasikov
2124862bd3cSAlexey Krasikov
2134862bd3cSAlexey Krasikov static int
qcrypto_secret_prop_get_format(Object * obj,Error ** errp G_GNUC_UNUSED)2144862bd3cSAlexey Krasikov qcrypto_secret_prop_get_format(Object *obj,
2154862bd3cSAlexey Krasikov Error **errp G_GNUC_UNUSED)
2164862bd3cSAlexey Krasikov {
2174862bd3cSAlexey Krasikov QCryptoSecretCommon *creds = QCRYPTO_SECRET_COMMON(obj);
2184862bd3cSAlexey Krasikov return creds->format;
2194862bd3cSAlexey Krasikov }
2204862bd3cSAlexey Krasikov
2214862bd3cSAlexey Krasikov
2224862bd3cSAlexey Krasikov static void
qcrypto_secret_prop_set_iv(Object * obj,const char * value,Error ** errp)2234862bd3cSAlexey Krasikov qcrypto_secret_prop_set_iv(Object *obj,
2244862bd3cSAlexey Krasikov const char *value,
2254862bd3cSAlexey Krasikov Error **errp)
2264862bd3cSAlexey Krasikov {
2274862bd3cSAlexey Krasikov QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj);
2284862bd3cSAlexey Krasikov
2294862bd3cSAlexey Krasikov g_free(secret->iv);
2304862bd3cSAlexey Krasikov secret->iv = g_strdup(value);
2314862bd3cSAlexey Krasikov }
2324862bd3cSAlexey Krasikov
2334862bd3cSAlexey Krasikov
2344862bd3cSAlexey Krasikov static char *
qcrypto_secret_prop_get_iv(Object * obj,Error ** errp)2354862bd3cSAlexey Krasikov qcrypto_secret_prop_get_iv(Object *obj,
2364862bd3cSAlexey Krasikov Error **errp)
2374862bd3cSAlexey Krasikov {
2384862bd3cSAlexey Krasikov QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj);
2394862bd3cSAlexey Krasikov return g_strdup(secret->iv);
2404862bd3cSAlexey Krasikov }
2414862bd3cSAlexey Krasikov
2424862bd3cSAlexey Krasikov
2434862bd3cSAlexey Krasikov static void
qcrypto_secret_prop_set_keyid(Object * obj,const char * value,Error ** errp)2444862bd3cSAlexey Krasikov qcrypto_secret_prop_set_keyid(Object *obj,
2454862bd3cSAlexey Krasikov const char *value,
2464862bd3cSAlexey Krasikov Error **errp)
2474862bd3cSAlexey Krasikov {
2484862bd3cSAlexey Krasikov QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj);
2494862bd3cSAlexey Krasikov
2504862bd3cSAlexey Krasikov g_free(secret->keyid);
2514862bd3cSAlexey Krasikov secret->keyid = g_strdup(value);
2524862bd3cSAlexey Krasikov }
2534862bd3cSAlexey Krasikov
2544862bd3cSAlexey Krasikov
2554862bd3cSAlexey Krasikov static char *
qcrypto_secret_prop_get_keyid(Object * obj,Error ** errp)2564862bd3cSAlexey Krasikov qcrypto_secret_prop_get_keyid(Object *obj,
2574862bd3cSAlexey Krasikov Error **errp)
2584862bd3cSAlexey Krasikov {
2594862bd3cSAlexey Krasikov QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj);
2604862bd3cSAlexey Krasikov return g_strdup(secret->keyid);
2614862bd3cSAlexey Krasikov }
2624862bd3cSAlexey Krasikov
2634862bd3cSAlexey Krasikov
2644862bd3cSAlexey Krasikov static void
qcrypto_secret_finalize(Object * obj)2654862bd3cSAlexey Krasikov qcrypto_secret_finalize(Object *obj)
2664862bd3cSAlexey Krasikov {
2674862bd3cSAlexey Krasikov QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj);
2684862bd3cSAlexey Krasikov
2694862bd3cSAlexey Krasikov g_free(secret->iv);
2704862bd3cSAlexey Krasikov g_free(secret->keyid);
2714862bd3cSAlexey Krasikov g_free(secret->rawdata);
2724862bd3cSAlexey Krasikov }
2734862bd3cSAlexey Krasikov
2744862bd3cSAlexey Krasikov static void
qcrypto_secret_class_init(ObjectClass * oc,void * data)2754862bd3cSAlexey Krasikov qcrypto_secret_class_init(ObjectClass *oc, void *data)
2764862bd3cSAlexey Krasikov {
27731b6aefdSKevin Wolf UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
27831b6aefdSKevin Wolf
27931b6aefdSKevin Wolf ucc->complete = qcrypto_secret_complete;
28031b6aefdSKevin Wolf
2814862bd3cSAlexey Krasikov object_class_property_add_bool(oc, "loaded",
2824862bd3cSAlexey Krasikov qcrypto_secret_prop_get_loaded,
283*0310641cSPaolo Bonzini NULL);
2844862bd3cSAlexey Krasikov object_class_property_add_enum(oc, "format",
2854862bd3cSAlexey Krasikov "QCryptoSecretFormat",
2864862bd3cSAlexey Krasikov &QCryptoSecretFormat_lookup,
2874862bd3cSAlexey Krasikov qcrypto_secret_prop_get_format,
2884862bd3cSAlexey Krasikov qcrypto_secret_prop_set_format);
2894862bd3cSAlexey Krasikov object_class_property_add_str(oc, "keyid",
2904862bd3cSAlexey Krasikov qcrypto_secret_prop_get_keyid,
2914862bd3cSAlexey Krasikov qcrypto_secret_prop_set_keyid);
2924862bd3cSAlexey Krasikov object_class_property_add_str(oc, "iv",
2934862bd3cSAlexey Krasikov qcrypto_secret_prop_get_iv,
2944862bd3cSAlexey Krasikov qcrypto_secret_prop_set_iv);
2954862bd3cSAlexey Krasikov }
2964862bd3cSAlexey Krasikov
2974862bd3cSAlexey Krasikov
qcrypto_secret_lookup(const char * secretid,uint8_t ** data,size_t * datalen,Error ** errp)2984862bd3cSAlexey Krasikov int qcrypto_secret_lookup(const char *secretid,
2994862bd3cSAlexey Krasikov uint8_t **data,
3004862bd3cSAlexey Krasikov size_t *datalen,
3014862bd3cSAlexey Krasikov Error **errp)
3024862bd3cSAlexey Krasikov {
3034862bd3cSAlexey Krasikov Object *obj;
3044862bd3cSAlexey Krasikov QCryptoSecretCommon *secret;
3054862bd3cSAlexey Krasikov
3064862bd3cSAlexey Krasikov obj = object_resolve_path_component(
3074862bd3cSAlexey Krasikov object_get_objects_root(), secretid);
3084862bd3cSAlexey Krasikov if (!obj) {
3094862bd3cSAlexey Krasikov error_setg(errp, "No secret with id '%s'", secretid);
3104862bd3cSAlexey Krasikov return -1;
3114862bd3cSAlexey Krasikov }
3124862bd3cSAlexey Krasikov
3134862bd3cSAlexey Krasikov secret = (QCryptoSecretCommon *)
3144862bd3cSAlexey Krasikov object_dynamic_cast(obj,
3154862bd3cSAlexey Krasikov TYPE_QCRYPTO_SECRET_COMMON);
3164862bd3cSAlexey Krasikov if (!secret) {
3174862bd3cSAlexey Krasikov error_setg(errp, "Object with id '%s' is not a secret",
3184862bd3cSAlexey Krasikov secretid);
3194862bd3cSAlexey Krasikov return -1;
3204862bd3cSAlexey Krasikov }
3214862bd3cSAlexey Krasikov
3224862bd3cSAlexey Krasikov if (!secret->rawdata) {
3234862bd3cSAlexey Krasikov error_setg(errp, "Secret with id '%s' has no data",
3244862bd3cSAlexey Krasikov secretid);
3254862bd3cSAlexey Krasikov return -1;
3264862bd3cSAlexey Krasikov }
3274862bd3cSAlexey Krasikov
3284862bd3cSAlexey Krasikov *data = g_new0(uint8_t, secret->rawlen + 1);
3294862bd3cSAlexey Krasikov memcpy(*data, secret->rawdata, secret->rawlen);
3304862bd3cSAlexey Krasikov (*data)[secret->rawlen] = '\0';
3314862bd3cSAlexey Krasikov *datalen = secret->rawlen;
3324862bd3cSAlexey Krasikov
3334862bd3cSAlexey Krasikov return 0;
3344862bd3cSAlexey Krasikov }
3354862bd3cSAlexey Krasikov
3364862bd3cSAlexey Krasikov
qcrypto_secret_lookup_as_utf8(const char * secretid,Error ** errp)3374862bd3cSAlexey Krasikov char *qcrypto_secret_lookup_as_utf8(const char *secretid,
3384862bd3cSAlexey Krasikov Error **errp)
3394862bd3cSAlexey Krasikov {
3404862bd3cSAlexey Krasikov uint8_t *data;
3414862bd3cSAlexey Krasikov size_t datalen;
3424862bd3cSAlexey Krasikov
3434862bd3cSAlexey Krasikov if (qcrypto_secret_lookup(secretid,
3444862bd3cSAlexey Krasikov &data,
3454862bd3cSAlexey Krasikov &datalen,
3464862bd3cSAlexey Krasikov errp) < 0) {
3474862bd3cSAlexey Krasikov return NULL;
3484862bd3cSAlexey Krasikov }
3494862bd3cSAlexey Krasikov
3504862bd3cSAlexey Krasikov if (!g_utf8_validate((const gchar *)data, datalen, NULL)) {
3514862bd3cSAlexey Krasikov error_setg(errp,
3524862bd3cSAlexey Krasikov "Data from secret %s is not valid UTF-8",
3534862bd3cSAlexey Krasikov secretid);
3544862bd3cSAlexey Krasikov g_free(data);
3554862bd3cSAlexey Krasikov return NULL;
3564862bd3cSAlexey Krasikov }
3574862bd3cSAlexey Krasikov
3584862bd3cSAlexey Krasikov return (char *)data;
3594862bd3cSAlexey Krasikov }
3604862bd3cSAlexey Krasikov
3614862bd3cSAlexey Krasikov
qcrypto_secret_lookup_as_base64(const char * secretid,Error ** errp)3624862bd3cSAlexey Krasikov char *qcrypto_secret_lookup_as_base64(const char *secretid,
3634862bd3cSAlexey Krasikov Error **errp)
3644862bd3cSAlexey Krasikov {
3654862bd3cSAlexey Krasikov uint8_t *data;
3664862bd3cSAlexey Krasikov size_t datalen;
3674862bd3cSAlexey Krasikov char *ret;
3684862bd3cSAlexey Krasikov
3694862bd3cSAlexey Krasikov if (qcrypto_secret_lookup(secretid,
3704862bd3cSAlexey Krasikov &data,
3714862bd3cSAlexey Krasikov &datalen,
3724862bd3cSAlexey Krasikov errp) < 0) {
3734862bd3cSAlexey Krasikov return NULL;
3744862bd3cSAlexey Krasikov }
3754862bd3cSAlexey Krasikov
3764862bd3cSAlexey Krasikov ret = g_base64_encode(data, datalen);
3774862bd3cSAlexey Krasikov g_free(data);
3784862bd3cSAlexey Krasikov return ret;
3794862bd3cSAlexey Krasikov }
3804862bd3cSAlexey Krasikov
3814862bd3cSAlexey Krasikov
3824862bd3cSAlexey Krasikov static const TypeInfo qcrypto_secret_info = {
3834862bd3cSAlexey Krasikov .parent = TYPE_OBJECT,
3844862bd3cSAlexey Krasikov .name = TYPE_QCRYPTO_SECRET_COMMON,
3854862bd3cSAlexey Krasikov .instance_size = sizeof(QCryptoSecretCommon),
3864862bd3cSAlexey Krasikov .instance_finalize = qcrypto_secret_finalize,
3874862bd3cSAlexey Krasikov .class_size = sizeof(QCryptoSecretCommonClass),
3884862bd3cSAlexey Krasikov .class_init = qcrypto_secret_class_init,
3894862bd3cSAlexey Krasikov .abstract = true,
39031b6aefdSKevin Wolf .interfaces = (InterfaceInfo[]) {
39131b6aefdSKevin Wolf { TYPE_USER_CREATABLE },
39231b6aefdSKevin Wolf { }
39331b6aefdSKevin Wolf }
3944862bd3cSAlexey Krasikov };
3954862bd3cSAlexey Krasikov
3964862bd3cSAlexey Krasikov
3974862bd3cSAlexey Krasikov static void
qcrypto_secret_register_types(void)3984862bd3cSAlexey Krasikov qcrypto_secret_register_types(void)
3994862bd3cSAlexey Krasikov {
4004862bd3cSAlexey Krasikov type_register_static(&qcrypto_secret_info);
4014862bd3cSAlexey Krasikov }
4024862bd3cSAlexey Krasikov
4034862bd3cSAlexey Krasikov
4044862bd3cSAlexey Krasikov type_init(qcrypto_secret_register_types);
405