xref: /openbmc/qemu/crypto/secret_common.c (revision 0310641c)
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