xref: /qemu/crypto/secret.c (revision b7cbb874)
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