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