xref: /qemu/crypto/secret.c (revision 42f7a448)
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 
21*42f7a448SPeter 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_init(Object *obj)
357ac1d8878SDaniel P. Berrange {
358ac1d8878SDaniel P. Berrange     object_property_add_bool(obj, "loaded",
359ac1d8878SDaniel P. Berrange                              qcrypto_secret_prop_get_loaded,
360ac1d8878SDaniel P. Berrange                              qcrypto_secret_prop_set_loaded,
361ac1d8878SDaniel P. Berrange                              NULL);
362ac1d8878SDaniel P. Berrange     object_property_add_enum(obj, "format",
363ac1d8878SDaniel P. Berrange                              "QCryptoSecretFormat",
364ac1d8878SDaniel P. Berrange                              QCryptoSecretFormat_lookup,
365ac1d8878SDaniel P. Berrange                              qcrypto_secret_prop_get_format,
366ac1d8878SDaniel P. Berrange                              qcrypto_secret_prop_set_format,
367ac1d8878SDaniel P. Berrange                              NULL);
368ac1d8878SDaniel P. Berrange     object_property_add_str(obj, "data",
369ac1d8878SDaniel P. Berrange                             qcrypto_secret_prop_get_data,
370ac1d8878SDaniel P. Berrange                             qcrypto_secret_prop_set_data,
371ac1d8878SDaniel P. Berrange                             NULL);
372ac1d8878SDaniel P. Berrange     object_property_add_str(obj, "file",
373ac1d8878SDaniel P. Berrange                             qcrypto_secret_prop_get_file,
374ac1d8878SDaniel P. Berrange                             qcrypto_secret_prop_set_file,
375ac1d8878SDaniel P. Berrange                             NULL);
376ac1d8878SDaniel P. Berrange     object_property_add_str(obj, "keyid",
377ac1d8878SDaniel P. Berrange                             qcrypto_secret_prop_get_keyid,
378ac1d8878SDaniel P. Berrange                             qcrypto_secret_prop_set_keyid,
379ac1d8878SDaniel P. Berrange                             NULL);
380ac1d8878SDaniel P. Berrange     object_property_add_str(obj, "iv",
381ac1d8878SDaniel P. Berrange                             qcrypto_secret_prop_get_iv,
382ac1d8878SDaniel P. Berrange                             qcrypto_secret_prop_set_iv,
383ac1d8878SDaniel P. Berrange                             NULL);
384ac1d8878SDaniel P. Berrange }
385ac1d8878SDaniel P. Berrange 
386ac1d8878SDaniel P. Berrange 
387ac1d8878SDaniel P. Berrange static void
388ac1d8878SDaniel P. Berrange qcrypto_secret_finalize(Object *obj)
389ac1d8878SDaniel P. Berrange {
390ac1d8878SDaniel P. Berrange     QCryptoSecret *secret = QCRYPTO_SECRET(obj);
391ac1d8878SDaniel P. Berrange 
392ac1d8878SDaniel P. Berrange     g_free(secret->iv);
393ac1d8878SDaniel P. Berrange     g_free(secret->file);
394ac1d8878SDaniel P. Berrange     g_free(secret->keyid);
395ac1d8878SDaniel P. Berrange     g_free(secret->rawdata);
396ac1d8878SDaniel P. Berrange     g_free(secret->data);
397ac1d8878SDaniel P. Berrange }
398ac1d8878SDaniel P. Berrange 
399ac1d8878SDaniel P. Berrange static void
400ac1d8878SDaniel P. Berrange qcrypto_secret_class_init(ObjectClass *oc, void *data)
401ac1d8878SDaniel P. Berrange {
402ac1d8878SDaniel P. Berrange     UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
403ac1d8878SDaniel P. Berrange 
404ac1d8878SDaniel P. Berrange     ucc->complete = qcrypto_secret_complete;
405ac1d8878SDaniel P. Berrange }
406ac1d8878SDaniel P. Berrange 
407ac1d8878SDaniel P. Berrange 
408ac1d8878SDaniel P. Berrange int qcrypto_secret_lookup(const char *secretid,
409ac1d8878SDaniel P. Berrange                           uint8_t **data,
410ac1d8878SDaniel P. Berrange                           size_t *datalen,
411ac1d8878SDaniel P. Berrange                           Error **errp)
412ac1d8878SDaniel P. Berrange {
413ac1d8878SDaniel P. Berrange     Object *obj;
414ac1d8878SDaniel P. Berrange     QCryptoSecret *secret;
415ac1d8878SDaniel P. Berrange 
416ac1d8878SDaniel P. Berrange     obj = object_resolve_path_component(
417ac1d8878SDaniel P. Berrange         object_get_objects_root(), secretid);
418ac1d8878SDaniel P. Berrange     if (!obj) {
419ac1d8878SDaniel P. Berrange         error_setg(errp, "No secret with id '%s'", secretid);
420ac1d8878SDaniel P. Berrange         return -1;
421ac1d8878SDaniel P. Berrange     }
422ac1d8878SDaniel P. Berrange 
423ac1d8878SDaniel P. Berrange     secret = (QCryptoSecret *)
424ac1d8878SDaniel P. Berrange         object_dynamic_cast(obj,
425ac1d8878SDaniel P. Berrange                             TYPE_QCRYPTO_SECRET);
426ac1d8878SDaniel P. Berrange     if (!secret) {
427ac1d8878SDaniel P. Berrange         error_setg(errp, "Object with id '%s' is not a secret",
428ac1d8878SDaniel P. Berrange                    secretid);
429ac1d8878SDaniel P. Berrange         return -1;
430ac1d8878SDaniel P. Berrange     }
431ac1d8878SDaniel P. Berrange 
432ac1d8878SDaniel P. Berrange     if (!secret->rawdata) {
433ac1d8878SDaniel P. Berrange         error_setg(errp, "Secret with id '%s' has no data",
434ac1d8878SDaniel P. Berrange                    secretid);
435ac1d8878SDaniel P. Berrange         return -1;
436ac1d8878SDaniel P. Berrange     }
437ac1d8878SDaniel P. Berrange 
438d341d9f3SPeter Maydell     *data = g_new0(uint8_t, secret->rawlen + 1);
439ac1d8878SDaniel P. Berrange     memcpy(*data, secret->rawdata, secret->rawlen);
440ac1d8878SDaniel P. Berrange     (*data)[secret->rawlen] = '\0';
441ac1d8878SDaniel P. Berrange     *datalen = secret->rawlen;
442ac1d8878SDaniel P. Berrange 
443ac1d8878SDaniel P. Berrange     return 0;
444ac1d8878SDaniel P. Berrange }
445ac1d8878SDaniel P. Berrange 
446ac1d8878SDaniel P. Berrange 
447ac1d8878SDaniel P. Berrange char *qcrypto_secret_lookup_as_utf8(const char *secretid,
448ac1d8878SDaniel P. Berrange                                     Error **errp)
449ac1d8878SDaniel P. Berrange {
450ac1d8878SDaniel P. Berrange     uint8_t *data;
451ac1d8878SDaniel P. Berrange     size_t datalen;
452ac1d8878SDaniel P. Berrange 
453ac1d8878SDaniel P. Berrange     if (qcrypto_secret_lookup(secretid,
454ac1d8878SDaniel P. Berrange                               &data,
455ac1d8878SDaniel P. Berrange                               &datalen,
456ac1d8878SDaniel P. Berrange                               errp) < 0) {
457ac1d8878SDaniel P. Berrange         return NULL;
458ac1d8878SDaniel P. Berrange     }
459ac1d8878SDaniel P. Berrange 
460ac1d8878SDaniel P. Berrange     if (!g_utf8_validate((const gchar*)data, datalen, NULL)) {
461ac1d8878SDaniel P. Berrange         error_setg(errp,
462ac1d8878SDaniel P. Berrange                    "Data from secret %s is not valid UTF-8",
463ac1d8878SDaniel P. Berrange                    secretid);
464ac1d8878SDaniel P. Berrange         g_free(data);
465ac1d8878SDaniel P. Berrange         return NULL;
466ac1d8878SDaniel P. Berrange     }
467ac1d8878SDaniel P. Berrange 
468ac1d8878SDaniel P. Berrange     return (char *)data;
469ac1d8878SDaniel P. Berrange }
470ac1d8878SDaniel P. Berrange 
471ac1d8878SDaniel P. Berrange 
472ac1d8878SDaniel P. Berrange char *qcrypto_secret_lookup_as_base64(const char *secretid,
473ac1d8878SDaniel P. Berrange                                       Error **errp)
474ac1d8878SDaniel P. Berrange {
475ac1d8878SDaniel P. Berrange     uint8_t *data;
476ac1d8878SDaniel P. Berrange     size_t datalen;
477ac1d8878SDaniel P. Berrange     char *ret;
478ac1d8878SDaniel P. Berrange 
479ac1d8878SDaniel P. Berrange     if (qcrypto_secret_lookup(secretid,
480ac1d8878SDaniel P. Berrange                               &data,
481ac1d8878SDaniel P. Berrange                               &datalen,
482ac1d8878SDaniel P. Berrange                               errp) < 0) {
483ac1d8878SDaniel P. Berrange         return NULL;
484ac1d8878SDaniel P. Berrange     }
485ac1d8878SDaniel P. Berrange 
486ac1d8878SDaniel P. Berrange     ret = g_base64_encode(data, datalen);
487ac1d8878SDaniel P. Berrange     g_free(data);
488ac1d8878SDaniel P. Berrange     return ret;
489ac1d8878SDaniel P. Berrange }
490ac1d8878SDaniel P. Berrange 
491ac1d8878SDaniel P. Berrange 
492ac1d8878SDaniel P. Berrange static const TypeInfo qcrypto_secret_info = {
493ac1d8878SDaniel P. Berrange     .parent = TYPE_OBJECT,
494ac1d8878SDaniel P. Berrange     .name = TYPE_QCRYPTO_SECRET,
495ac1d8878SDaniel P. Berrange     .instance_size = sizeof(QCryptoSecret),
496ac1d8878SDaniel P. Berrange     .instance_init = qcrypto_secret_init,
497ac1d8878SDaniel P. Berrange     .instance_finalize = qcrypto_secret_finalize,
498ac1d8878SDaniel P. Berrange     .class_size = sizeof(QCryptoSecretClass),
499ac1d8878SDaniel P. Berrange     .class_init = qcrypto_secret_class_init,
500ac1d8878SDaniel P. Berrange     .interfaces = (InterfaceInfo[]) {
501ac1d8878SDaniel P. Berrange         { TYPE_USER_CREATABLE },
502ac1d8878SDaniel P. Berrange         { }
503ac1d8878SDaniel P. Berrange     }
504ac1d8878SDaniel P. Berrange };
505ac1d8878SDaniel P. Berrange 
506ac1d8878SDaniel P. Berrange 
507ac1d8878SDaniel P. Berrange static void
508ac1d8878SDaniel P. Berrange qcrypto_secret_register_types(void)
509ac1d8878SDaniel P. Berrange {
510ac1d8878SDaniel P. Berrange     type_register_static(&qcrypto_secret_info);
511ac1d8878SDaniel P. Berrange }
512ac1d8878SDaniel P. Berrange 
513ac1d8878SDaniel P. Berrange 
514ac1d8878SDaniel P. Berrange type_init(qcrypto_secret_register_types);
515