1da668aa1SThomas Huth /*
2da668aa1SThomas Huth * QEMU Crypto block encryption
3da668aa1SThomas Huth *
4da668aa1SThomas Huth * Copyright (c) 2016 Red Hat, Inc.
5da668aa1SThomas Huth *
6da668aa1SThomas Huth * This library is free software; you can redistribute it and/or
7da668aa1SThomas Huth * modify it under the terms of the GNU Lesser General Public
8da668aa1SThomas Huth * License as published by the Free Software Foundation; either
9da668aa1SThomas Huth * version 2.1 of the License, or (at your option) any later version.
10da668aa1SThomas Huth *
11da668aa1SThomas Huth * This library is distributed in the hope that it will be useful,
12da668aa1SThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of
13da668aa1SThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14da668aa1SThomas Huth * Lesser General Public License for more details.
15da668aa1SThomas Huth *
16da668aa1SThomas Huth * You should have received a copy of the GNU Lesser General Public
17da668aa1SThomas Huth * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18da668aa1SThomas Huth *
19da668aa1SThomas Huth */
20da668aa1SThomas Huth
21da668aa1SThomas Huth #include "qemu/osdep.h"
22da668aa1SThomas Huth #include "qapi/error.h"
23da668aa1SThomas Huth #include "crypto/init.h"
24da668aa1SThomas Huth #include "crypto/block.h"
25da0ab2c4SDaniel P. Berrangé #include "crypto/block-luks-priv.h"
26da668aa1SThomas Huth #include "qemu/buffer.h"
27da668aa1SThomas Huth #include "qemu/module.h"
28da668aa1SThomas Huth #include "crypto/secret.h"
29da668aa1SThomas Huth #ifndef _WIN32
30da668aa1SThomas Huth #include <sys/resource.h>
31da668aa1SThomas Huth #endif
32da668aa1SThomas Huth
33da668aa1SThomas Huth #if (defined(_WIN32) || defined RUSAGE_THREAD) && \
34741c314aSDaniel P. Berrangé (defined(CONFIG_NETTLE) || defined(CONFIG_GCRYPT) || \
35741c314aSDaniel P. Berrangé defined(CONFIG_GNUTLS_CRYPTO))
36da668aa1SThomas Huth #define TEST_LUKS
37da668aa1SThomas Huth #else
38da668aa1SThomas Huth #undef TEST_LUKS
39da668aa1SThomas Huth #endif
40da668aa1SThomas Huth
41da668aa1SThomas Huth static QCryptoBlockCreateOptions qcow_create_opts = {
42d23d2ef3SMarkus Armbruster .format = QCRYPTO_BLOCK_FORMAT_QCOW,
43da668aa1SThomas Huth .u.qcow = {
44da668aa1SThomas Huth .key_secret = (char *)"sec0",
45da668aa1SThomas Huth },
46da668aa1SThomas Huth };
47da668aa1SThomas Huth
48da668aa1SThomas Huth static QCryptoBlockOpenOptions qcow_open_opts = {
49d23d2ef3SMarkus Armbruster .format = QCRYPTO_BLOCK_FORMAT_QCOW,
50da668aa1SThomas Huth .u.qcow = {
51da668aa1SThomas Huth .key_secret = (char *)"sec0",
52da668aa1SThomas Huth },
53da668aa1SThomas Huth };
54da668aa1SThomas Huth
55da668aa1SThomas Huth
56da668aa1SThomas Huth #ifdef TEST_LUKS
57da668aa1SThomas Huth static QCryptoBlockOpenOptions luks_open_opts = {
58d23d2ef3SMarkus Armbruster .format = QCRYPTO_BLOCK_FORMAT_LUKS,
59da668aa1SThomas Huth .u.luks = {
60da668aa1SThomas Huth .key_secret = (char *)"sec0",
61da668aa1SThomas Huth },
62da668aa1SThomas Huth };
63da668aa1SThomas Huth
64da668aa1SThomas Huth
65da668aa1SThomas Huth /* Creation with all default values */
66da668aa1SThomas Huth static QCryptoBlockCreateOptions luks_create_opts_default = {
67d23d2ef3SMarkus Armbruster .format = QCRYPTO_BLOCK_FORMAT_LUKS,
68da668aa1SThomas Huth .u.luks = {
69da668aa1SThomas Huth .key_secret = (char *)"sec0",
70da668aa1SThomas Huth },
71da668aa1SThomas Huth };
72da668aa1SThomas Huth
73da668aa1SThomas Huth
74da668aa1SThomas Huth /* ...and with explicit values */
75da668aa1SThomas Huth static QCryptoBlockCreateOptions luks_create_opts_aes256_cbc_plain64 = {
76d23d2ef3SMarkus Armbruster .format = QCRYPTO_BLOCK_FORMAT_LUKS,
77da668aa1SThomas Huth .u.luks = {
78da668aa1SThomas Huth .key_secret = (char *)"sec0",
79da668aa1SThomas Huth .has_cipher_alg = true,
80a092c513SMarkus Armbruster .cipher_alg = QCRYPTO_CIPHER_ALGO_AES_256,
81da668aa1SThomas Huth .has_cipher_mode = true,
82da668aa1SThomas Huth .cipher_mode = QCRYPTO_CIPHER_MODE_CBC,
83da668aa1SThomas Huth .has_ivgen_alg = true,
84*5e0e5102SMarkus Armbruster .ivgen_alg = QCRYPTO_IV_GEN_ALGO_PLAIN64,
85da668aa1SThomas Huth },
86da668aa1SThomas Huth };
87da668aa1SThomas Huth
88da668aa1SThomas Huth
89da668aa1SThomas Huth static QCryptoBlockCreateOptions luks_create_opts_aes256_cbc_essiv = {
90d23d2ef3SMarkus Armbruster .format = QCRYPTO_BLOCK_FORMAT_LUKS,
91da668aa1SThomas Huth .u.luks = {
92da668aa1SThomas Huth .key_secret = (char *)"sec0",
93da668aa1SThomas Huth .has_cipher_alg = true,
94a092c513SMarkus Armbruster .cipher_alg = QCRYPTO_CIPHER_ALGO_AES_256,
95da668aa1SThomas Huth .has_cipher_mode = true,
96da668aa1SThomas Huth .cipher_mode = QCRYPTO_CIPHER_MODE_CBC,
97da668aa1SThomas Huth .has_ivgen_alg = true,
98*5e0e5102SMarkus Armbruster .ivgen_alg = QCRYPTO_IV_GEN_ALGO_ESSIV,
99da668aa1SThomas Huth .has_ivgen_hash_alg = true,
100ef834aa2SMarkus Armbruster .ivgen_hash_alg = QCRYPTO_HASH_ALGO_SHA256,
101da668aa1SThomas Huth .has_hash_alg = true,
102ef834aa2SMarkus Armbruster .hash_alg = QCRYPTO_HASH_ALGO_SHA1,
103da668aa1SThomas Huth },
104da668aa1SThomas Huth };
105da668aa1SThomas Huth #endif /* TEST_LUKS */
106da668aa1SThomas Huth
107da668aa1SThomas Huth
108da668aa1SThomas Huth static struct QCryptoBlockTestData {
109da668aa1SThomas Huth const char *path;
110da668aa1SThomas Huth QCryptoBlockCreateOptions *create_opts;
111da668aa1SThomas Huth QCryptoBlockOpenOptions *open_opts;
112da668aa1SThomas Huth
113da668aa1SThomas Huth bool expect_header;
114da668aa1SThomas Huth
115a092c513SMarkus Armbruster QCryptoCipherAlgo cipher_alg;
116da668aa1SThomas Huth QCryptoCipherMode cipher_mode;
117ef834aa2SMarkus Armbruster QCryptoHashAlgo hash_alg;
118da668aa1SThomas Huth
119*5e0e5102SMarkus Armbruster QCryptoIVGenAlgo ivgen_alg;
120ef834aa2SMarkus Armbruster QCryptoHashAlgo ivgen_hash;
121da668aa1SThomas Huth
122da668aa1SThomas Huth bool slow;
123da668aa1SThomas Huth } test_data[] = {
124da668aa1SThomas Huth {
125da668aa1SThomas Huth .path = "/crypto/block/qcow",
126da668aa1SThomas Huth .create_opts = &qcow_create_opts,
127da668aa1SThomas Huth .open_opts = &qcow_open_opts,
128da668aa1SThomas Huth
129da668aa1SThomas Huth .expect_header = false,
130da668aa1SThomas Huth
131a092c513SMarkus Armbruster .cipher_alg = QCRYPTO_CIPHER_ALGO_AES_128,
132da668aa1SThomas Huth .cipher_mode = QCRYPTO_CIPHER_MODE_CBC,
133da668aa1SThomas Huth
134*5e0e5102SMarkus Armbruster .ivgen_alg = QCRYPTO_IV_GEN_ALGO_PLAIN64,
135da668aa1SThomas Huth },
136da668aa1SThomas Huth #ifdef TEST_LUKS
137da668aa1SThomas Huth {
138da668aa1SThomas Huth .path = "/crypto/block/luks/default",
139da668aa1SThomas Huth .create_opts = &luks_create_opts_default,
140da668aa1SThomas Huth .open_opts = &luks_open_opts,
141da668aa1SThomas Huth
142da668aa1SThomas Huth .expect_header = true,
143da668aa1SThomas Huth
144a092c513SMarkus Armbruster .cipher_alg = QCRYPTO_CIPHER_ALGO_AES_256,
145da668aa1SThomas Huth .cipher_mode = QCRYPTO_CIPHER_MODE_XTS,
146ef834aa2SMarkus Armbruster .hash_alg = QCRYPTO_HASH_ALGO_SHA256,
147da668aa1SThomas Huth
148*5e0e5102SMarkus Armbruster .ivgen_alg = QCRYPTO_IV_GEN_ALGO_PLAIN64,
149da668aa1SThomas Huth
150da668aa1SThomas Huth .slow = true,
151da668aa1SThomas Huth },
152da668aa1SThomas Huth {
153da668aa1SThomas Huth .path = "/crypto/block/luks/aes-256-cbc-plain64",
154da668aa1SThomas Huth .create_opts = &luks_create_opts_aes256_cbc_plain64,
155da668aa1SThomas Huth .open_opts = &luks_open_opts,
156da668aa1SThomas Huth
157da668aa1SThomas Huth .expect_header = true,
158da668aa1SThomas Huth
159a092c513SMarkus Armbruster .cipher_alg = QCRYPTO_CIPHER_ALGO_AES_256,
160da668aa1SThomas Huth .cipher_mode = QCRYPTO_CIPHER_MODE_CBC,
161ef834aa2SMarkus Armbruster .hash_alg = QCRYPTO_HASH_ALGO_SHA256,
162da668aa1SThomas Huth
163*5e0e5102SMarkus Armbruster .ivgen_alg = QCRYPTO_IV_GEN_ALGO_PLAIN64,
164da668aa1SThomas Huth
165da668aa1SThomas Huth .slow = true,
166da668aa1SThomas Huth },
167da668aa1SThomas Huth {
168da668aa1SThomas Huth .path = "/crypto/block/luks/aes-256-cbc-essiv",
169da668aa1SThomas Huth .create_opts = &luks_create_opts_aes256_cbc_essiv,
170da668aa1SThomas Huth .open_opts = &luks_open_opts,
171da668aa1SThomas Huth
172da668aa1SThomas Huth .expect_header = true,
173da668aa1SThomas Huth
174a092c513SMarkus Armbruster .cipher_alg = QCRYPTO_CIPHER_ALGO_AES_256,
175da668aa1SThomas Huth .cipher_mode = QCRYPTO_CIPHER_MODE_CBC,
176ef834aa2SMarkus Armbruster .hash_alg = QCRYPTO_HASH_ALGO_SHA1,
177da668aa1SThomas Huth
178*5e0e5102SMarkus Armbruster .ivgen_alg = QCRYPTO_IV_GEN_ALGO_ESSIV,
179ef834aa2SMarkus Armbruster .ivgen_hash = QCRYPTO_HASH_ALGO_SHA256,
180da668aa1SThomas Huth
181da668aa1SThomas Huth .slow = true,
182da668aa1SThomas Huth },
183da668aa1SThomas Huth #endif
184da668aa1SThomas Huth };
185da668aa1SThomas Huth
186da668aa1SThomas Huth
test_block_read_func(QCryptoBlock * block,size_t offset,uint8_t * buf,size_t buflen,void * opaque,Error ** errp)187757dda54SAlberto Faria static int test_block_read_func(QCryptoBlock *block,
188da668aa1SThomas Huth size_t offset,
189da668aa1SThomas Huth uint8_t *buf,
190da668aa1SThomas Huth size_t buflen,
191da668aa1SThomas Huth void *opaque,
192da668aa1SThomas Huth Error **errp)
193da668aa1SThomas Huth {
194da668aa1SThomas Huth Buffer *header = opaque;
195da668aa1SThomas Huth
196da668aa1SThomas Huth g_assert_cmpint(offset + buflen, <=, header->capacity);
197da668aa1SThomas Huth
198da668aa1SThomas Huth memcpy(buf, header->buffer + offset, buflen);
199da668aa1SThomas Huth
200757dda54SAlberto Faria return 0;
201da668aa1SThomas Huth }
202da668aa1SThomas Huth
203da668aa1SThomas Huth
test_block_init_func(QCryptoBlock * block,size_t headerlen,void * opaque,Error ** errp)204757dda54SAlberto Faria static int test_block_init_func(QCryptoBlock *block,
205da668aa1SThomas Huth size_t headerlen,
206da668aa1SThomas Huth void *opaque,
207da668aa1SThomas Huth Error **errp)
208da668aa1SThomas Huth {
209da668aa1SThomas Huth Buffer *header = opaque;
210da668aa1SThomas Huth
211da668aa1SThomas Huth g_assert_cmpint(header->capacity, ==, 0);
212da668aa1SThomas Huth
213da668aa1SThomas Huth buffer_reserve(header, headerlen);
214da668aa1SThomas Huth
215757dda54SAlberto Faria return 0;
216da668aa1SThomas Huth }
217da668aa1SThomas Huth
218da668aa1SThomas Huth
test_block_write_func(QCryptoBlock * block,size_t offset,const uint8_t * buf,size_t buflen,void * opaque,Error ** errp)219757dda54SAlberto Faria static int test_block_write_func(QCryptoBlock *block,
220da668aa1SThomas Huth size_t offset,
221da668aa1SThomas Huth const uint8_t *buf,
222da668aa1SThomas Huth size_t buflen,
223da668aa1SThomas Huth void *opaque,
224da668aa1SThomas Huth Error **errp)
225da668aa1SThomas Huth {
226da668aa1SThomas Huth Buffer *header = opaque;
227da668aa1SThomas Huth
228da668aa1SThomas Huth g_assert_cmpint(buflen + offset, <=, header->capacity);
229da668aa1SThomas Huth
230da668aa1SThomas Huth memcpy(header->buffer + offset, buf, buflen);
231da668aa1SThomas Huth header->offset = offset + buflen;
232da668aa1SThomas Huth
233757dda54SAlberto Faria return 0;
234da668aa1SThomas Huth }
235da668aa1SThomas Huth
236da668aa1SThomas Huth
test_block_secret(void)237da668aa1SThomas Huth static Object *test_block_secret(void)
238da668aa1SThomas Huth {
239da668aa1SThomas Huth return object_new_with_props(
240da668aa1SThomas Huth TYPE_QCRYPTO_SECRET,
241da668aa1SThomas Huth object_get_objects_root(),
242da668aa1SThomas Huth "sec0",
243da668aa1SThomas Huth &error_abort,
244da668aa1SThomas Huth "data", "123456",
245da668aa1SThomas Huth NULL);
246da668aa1SThomas Huth }
247da668aa1SThomas Huth
test_block_assert_setup(const struct QCryptoBlockTestData * data,QCryptoBlock * blk)248da668aa1SThomas Huth static void test_block_assert_setup(const struct QCryptoBlockTestData *data,
249da668aa1SThomas Huth QCryptoBlock *blk)
250da668aa1SThomas Huth {
251da668aa1SThomas Huth QCryptoIVGen *ivgen;
252da668aa1SThomas Huth QCryptoCipher *cipher;
253da668aa1SThomas Huth
254da668aa1SThomas Huth ivgen = qcrypto_block_get_ivgen(blk);
255da668aa1SThomas Huth cipher = qcrypto_block_get_cipher(blk);
256da668aa1SThomas Huth
257da668aa1SThomas Huth g_assert(ivgen);
258da668aa1SThomas Huth g_assert(cipher);
259da668aa1SThomas Huth
260da668aa1SThomas Huth g_assert_cmpint(data->cipher_alg, ==, cipher->alg);
261da668aa1SThomas Huth g_assert_cmpint(data->cipher_mode, ==, cipher->mode);
262da668aa1SThomas Huth g_assert_cmpint(data->hash_alg, ==,
263da668aa1SThomas Huth qcrypto_block_get_kdf_hash(blk));
264da668aa1SThomas Huth
265da668aa1SThomas Huth g_assert_cmpint(data->ivgen_alg, ==,
266da668aa1SThomas Huth qcrypto_ivgen_get_algorithm(ivgen));
267da668aa1SThomas Huth g_assert_cmpint(data->ivgen_hash, ==,
268da668aa1SThomas Huth qcrypto_ivgen_get_hash(ivgen));
269da668aa1SThomas Huth }
270da668aa1SThomas Huth
271da668aa1SThomas Huth
test_block(gconstpointer opaque)272da668aa1SThomas Huth static void test_block(gconstpointer opaque)
273da668aa1SThomas Huth {
274da668aa1SThomas Huth const struct QCryptoBlockTestData *data = opaque;
275da668aa1SThomas Huth QCryptoBlock *blk;
276da668aa1SThomas Huth Buffer header;
277da668aa1SThomas Huth Object *sec = test_block_secret();
278da668aa1SThomas Huth
279da668aa1SThomas Huth memset(&header, 0, sizeof(header));
280da668aa1SThomas Huth buffer_init(&header, "header");
281da668aa1SThomas Huth
282da668aa1SThomas Huth blk = qcrypto_block_create(data->create_opts, NULL,
283da668aa1SThomas Huth test_block_init_func,
284da668aa1SThomas Huth test_block_write_func,
285da668aa1SThomas Huth &header,
286d74523a3SHyman Huang 0,
287da668aa1SThomas Huth &error_abort);
288da668aa1SThomas Huth g_assert(blk);
289da668aa1SThomas Huth
290da668aa1SThomas Huth if (data->expect_header) {
291da668aa1SThomas Huth g_assert_cmpint(header.capacity, >, 0);
292da668aa1SThomas Huth } else {
293da668aa1SThomas Huth g_assert_cmpint(header.capacity, ==, 0);
294da668aa1SThomas Huth }
295da668aa1SThomas Huth
296da668aa1SThomas Huth test_block_assert_setup(data, blk);
297da668aa1SThomas Huth
298da668aa1SThomas Huth qcrypto_block_free(blk);
299da668aa1SThomas Huth object_unparent(sec);
300da668aa1SThomas Huth
301da668aa1SThomas Huth /* Ensure we can't open without the secret */
302da668aa1SThomas Huth blk = qcrypto_block_open(data->open_opts, NULL,
303da668aa1SThomas Huth test_block_read_func,
304da668aa1SThomas Huth &header,
305da668aa1SThomas Huth 0,
306da668aa1SThomas Huth NULL);
307da668aa1SThomas Huth g_assert(blk == NULL);
308da668aa1SThomas Huth
309da668aa1SThomas Huth /* Ensure we can't open without the secret, unless NO_IO */
310da668aa1SThomas Huth blk = qcrypto_block_open(data->open_opts, NULL,
311da668aa1SThomas Huth test_block_read_func,
312da668aa1SThomas Huth &header,
313da668aa1SThomas Huth QCRYPTO_BLOCK_OPEN_NO_IO,
314da668aa1SThomas Huth &error_abort);
315da668aa1SThomas Huth
316da668aa1SThomas Huth g_assert(qcrypto_block_get_cipher(blk) == NULL);
317da668aa1SThomas Huth g_assert(qcrypto_block_get_ivgen(blk) == NULL);
318da668aa1SThomas Huth
319da668aa1SThomas Huth qcrypto_block_free(blk);
320da668aa1SThomas Huth
321da668aa1SThomas Huth
322da668aa1SThomas Huth /* Now open for real with secret */
323da668aa1SThomas Huth sec = test_block_secret();
324da668aa1SThomas Huth blk = qcrypto_block_open(data->open_opts, NULL,
325da668aa1SThomas Huth test_block_read_func,
326da668aa1SThomas Huth &header,
327da668aa1SThomas Huth 0,
328da668aa1SThomas Huth &error_abort);
329da668aa1SThomas Huth g_assert(blk);
330da668aa1SThomas Huth
331da668aa1SThomas Huth test_block_assert_setup(data, blk);
332da668aa1SThomas Huth
333da668aa1SThomas Huth qcrypto_block_free(blk);
334da668aa1SThomas Huth
335da668aa1SThomas Huth object_unparent(sec);
336da668aa1SThomas Huth
337da668aa1SThomas Huth buffer_free(&header);
338da668aa1SThomas Huth }
339da668aa1SThomas Huth
340da668aa1SThomas Huth
341da0ab2c4SDaniel P. Berrangé #ifdef TEST_LUKS
342da0ab2c4SDaniel P. Berrangé typedef const char *(*LuksHeaderDoBadStuff)(QCryptoBlockLUKSHeader *hdr);
343da0ab2c4SDaniel P. Berrangé
344da0ab2c4SDaniel P. Berrangé static void
test_luks_bad_header(gconstpointer data)345da0ab2c4SDaniel P. Berrangé test_luks_bad_header(gconstpointer data)
346da0ab2c4SDaniel P. Berrangé {
347da0ab2c4SDaniel P. Berrangé LuksHeaderDoBadStuff badstuff = data;
348da0ab2c4SDaniel P. Berrangé QCryptoBlock *blk;
349da0ab2c4SDaniel P. Berrangé Buffer buf;
350da0ab2c4SDaniel P. Berrangé Object *sec = test_block_secret();
351da0ab2c4SDaniel P. Berrangé QCryptoBlockLUKSHeader hdr;
352da0ab2c4SDaniel P. Berrangé Error *err = NULL;
353da0ab2c4SDaniel P. Berrangé const char *msg;
354da0ab2c4SDaniel P. Berrangé
355da0ab2c4SDaniel P. Berrangé memset(&buf, 0, sizeof(buf));
356da0ab2c4SDaniel P. Berrangé buffer_init(&buf, "header");
357da0ab2c4SDaniel P. Berrangé
358da0ab2c4SDaniel P. Berrangé /* Correctly create the volume initially */
359da0ab2c4SDaniel P. Berrangé blk = qcrypto_block_create(&luks_create_opts_default, NULL,
360da0ab2c4SDaniel P. Berrangé test_block_init_func,
361da0ab2c4SDaniel P. Berrangé test_block_write_func,
362da0ab2c4SDaniel P. Berrangé &buf,
363d74523a3SHyman Huang 0,
364da0ab2c4SDaniel P. Berrangé &error_abort);
365da0ab2c4SDaniel P. Berrangé g_assert(blk);
366da0ab2c4SDaniel P. Berrangé
367da0ab2c4SDaniel P. Berrangé qcrypto_block_free(blk);
368da0ab2c4SDaniel P. Berrangé
369da0ab2c4SDaniel P. Berrangé /* Mangle it in some unpleasant way */
370da0ab2c4SDaniel P. Berrangé g_assert(buf.offset >= sizeof(hdr));
371da0ab2c4SDaniel P. Berrangé memcpy(&hdr, buf.buffer, sizeof(hdr));
372da0ab2c4SDaniel P. Berrangé qcrypto_block_luks_to_disk_endian(&hdr);
373da0ab2c4SDaniel P. Berrangé
374da0ab2c4SDaniel P. Berrangé msg = badstuff(&hdr);
375da0ab2c4SDaniel P. Berrangé
376da0ab2c4SDaniel P. Berrangé qcrypto_block_luks_from_disk_endian(&hdr);
377da0ab2c4SDaniel P. Berrangé memcpy(buf.buffer, &hdr, sizeof(hdr));
378da0ab2c4SDaniel P. Berrangé
379da0ab2c4SDaniel P. Berrangé /* Check that we fail to open it again */
380da0ab2c4SDaniel P. Berrangé blk = qcrypto_block_open(&luks_open_opts, NULL,
381da0ab2c4SDaniel P. Berrangé test_block_read_func,
382da0ab2c4SDaniel P. Berrangé &buf,
383da0ab2c4SDaniel P. Berrangé 0,
384da0ab2c4SDaniel P. Berrangé &err);
385da0ab2c4SDaniel P. Berrangé g_assert(!blk);
386da0ab2c4SDaniel P. Berrangé g_assert(err);
387da0ab2c4SDaniel P. Berrangé
388da0ab2c4SDaniel P. Berrangé g_assert_cmpstr(error_get_pretty(err), ==, msg);
389da0ab2c4SDaniel P. Berrangé error_free(err);
390da0ab2c4SDaniel P. Berrangé
391da0ab2c4SDaniel P. Berrangé object_unparent(sec);
392da0ab2c4SDaniel P. Berrangé
393da0ab2c4SDaniel P. Berrangé buffer_free(&buf);
394da0ab2c4SDaniel P. Berrangé }
395da0ab2c4SDaniel P. Berrangé
luks_bad_null_term_cipher_name(QCryptoBlockLUKSHeader * hdr)396da0ab2c4SDaniel P. Berrangé static const char *luks_bad_null_term_cipher_name(QCryptoBlockLUKSHeader *hdr)
397da0ab2c4SDaniel P. Berrangé {
398da0ab2c4SDaniel P. Berrangé /* Replace NUL termination with spaces */
399da0ab2c4SDaniel P. Berrangé char *offset = hdr->cipher_name + strlen(hdr->cipher_name);
400da0ab2c4SDaniel P. Berrangé memset(offset, ' ', sizeof(hdr->cipher_name) - (offset - hdr->cipher_name));
401da0ab2c4SDaniel P. Berrangé
402da0ab2c4SDaniel P. Berrangé return "LUKS header cipher name is not NUL terminated";
403da0ab2c4SDaniel P. Berrangé }
404da0ab2c4SDaniel P. Berrangé
luks_bad_null_term_cipher_mode(QCryptoBlockLUKSHeader * hdr)405da0ab2c4SDaniel P. Berrangé static const char *luks_bad_null_term_cipher_mode(QCryptoBlockLUKSHeader *hdr)
406da0ab2c4SDaniel P. Berrangé {
407da0ab2c4SDaniel P. Berrangé /* Replace NUL termination with spaces */
408da0ab2c4SDaniel P. Berrangé char *offset = hdr->cipher_mode + strlen(hdr->cipher_mode);
409da0ab2c4SDaniel P. Berrangé memset(offset, ' ', sizeof(hdr->cipher_mode) - (offset - hdr->cipher_mode));
410da0ab2c4SDaniel P. Berrangé
411da0ab2c4SDaniel P. Berrangé return "LUKS header cipher mode is not NUL terminated";
412da0ab2c4SDaniel P. Berrangé }
413da0ab2c4SDaniel P. Berrangé
luks_bad_null_term_hash_spec(QCryptoBlockLUKSHeader * hdr)414da0ab2c4SDaniel P. Berrangé static const char *luks_bad_null_term_hash_spec(QCryptoBlockLUKSHeader *hdr)
415da0ab2c4SDaniel P. Berrangé {
416da0ab2c4SDaniel P. Berrangé /* Replace NUL termination with spaces */
417da0ab2c4SDaniel P. Berrangé char *offset = hdr->hash_spec + strlen(hdr->hash_spec);
418da0ab2c4SDaniel P. Berrangé memset(offset, ' ', sizeof(hdr->hash_spec) - (offset - hdr->hash_spec));
419da0ab2c4SDaniel P. Berrangé
420da0ab2c4SDaniel P. Berrangé return "LUKS header hash spec is not NUL terminated";
421da0ab2c4SDaniel P. Berrangé }
422da0ab2c4SDaniel P. Berrangé
luks_bad_cipher_name_empty(QCryptoBlockLUKSHeader * hdr)423da0ab2c4SDaniel P. Berrangé static const char *luks_bad_cipher_name_empty(QCryptoBlockLUKSHeader *hdr)
424da0ab2c4SDaniel P. Berrangé {
425da0ab2c4SDaniel P. Berrangé memcpy(hdr->cipher_name, "", 1);
426da0ab2c4SDaniel P. Berrangé
427da0ab2c4SDaniel P. Berrangé return "Algorithm '' with key size 32 bytes not supported";
428da0ab2c4SDaniel P. Berrangé }
429da0ab2c4SDaniel P. Berrangé
luks_bad_cipher_name_unknown(QCryptoBlockLUKSHeader * hdr)430da0ab2c4SDaniel P. Berrangé static const char *luks_bad_cipher_name_unknown(QCryptoBlockLUKSHeader *hdr)
431da0ab2c4SDaniel P. Berrangé {
432da0ab2c4SDaniel P. Berrangé memcpy(hdr->cipher_name, "aess", 5);
433da0ab2c4SDaniel P. Berrangé
434da0ab2c4SDaniel P. Berrangé return "Algorithm 'aess' with key size 32 bytes not supported";
435da0ab2c4SDaniel P. Berrangé }
436da0ab2c4SDaniel P. Berrangé
luks_bad_cipher_xts_size(QCryptoBlockLUKSHeader * hdr)437da0ab2c4SDaniel P. Berrangé static const char *luks_bad_cipher_xts_size(QCryptoBlockLUKSHeader *hdr)
438da0ab2c4SDaniel P. Berrangé {
439da0ab2c4SDaniel P. Berrangé hdr->master_key_len = 33;
440da0ab2c4SDaniel P. Berrangé
441da0ab2c4SDaniel P. Berrangé return "XTS cipher key length should be a multiple of 2";
442da0ab2c4SDaniel P. Berrangé }
443da0ab2c4SDaniel P. Berrangé
luks_bad_cipher_cbc_size(QCryptoBlockLUKSHeader * hdr)444da0ab2c4SDaniel P. Berrangé static const char *luks_bad_cipher_cbc_size(QCryptoBlockLUKSHeader *hdr)
445da0ab2c4SDaniel P. Berrangé {
446da0ab2c4SDaniel P. Berrangé hdr->master_key_len = 33;
447da0ab2c4SDaniel P. Berrangé memcpy(hdr->cipher_mode, "cbc-essiv", 10);
448da0ab2c4SDaniel P. Berrangé
449da0ab2c4SDaniel P. Berrangé return "Algorithm 'aes' with key size 33 bytes not supported";
450da0ab2c4SDaniel P. Berrangé }
451da0ab2c4SDaniel P. Berrangé
luks_bad_cipher_mode_empty(QCryptoBlockLUKSHeader * hdr)452da0ab2c4SDaniel P. Berrangé static const char *luks_bad_cipher_mode_empty(QCryptoBlockLUKSHeader *hdr)
453da0ab2c4SDaniel P. Berrangé {
454da0ab2c4SDaniel P. Berrangé memcpy(hdr->cipher_mode, "", 1);
455da0ab2c4SDaniel P. Berrangé
456da0ab2c4SDaniel P. Berrangé return "Unexpected cipher mode string format ''";
457da0ab2c4SDaniel P. Berrangé }
458da0ab2c4SDaniel P. Berrangé
luks_bad_cipher_mode_unknown(QCryptoBlockLUKSHeader * hdr)459da0ab2c4SDaniel P. Berrangé static const char *luks_bad_cipher_mode_unknown(QCryptoBlockLUKSHeader *hdr)
460da0ab2c4SDaniel P. Berrangé {
461da0ab2c4SDaniel P. Berrangé memcpy(hdr->cipher_mode, "xfs", 4);
462da0ab2c4SDaniel P. Berrangé
463da0ab2c4SDaniel P. Berrangé return "Unexpected cipher mode string format 'xfs'";
464da0ab2c4SDaniel P. Berrangé }
465da0ab2c4SDaniel P. Berrangé
luks_bad_ivgen_separator(QCryptoBlockLUKSHeader * hdr)466da0ab2c4SDaniel P. Berrangé static const char *luks_bad_ivgen_separator(QCryptoBlockLUKSHeader *hdr)
467da0ab2c4SDaniel P. Berrangé {
468da0ab2c4SDaniel P. Berrangé memcpy(hdr->cipher_mode, "xts:plain64", 12);
469da0ab2c4SDaniel P. Berrangé
470da0ab2c4SDaniel P. Berrangé return "Unexpected cipher mode string format 'xts:plain64'";
471da0ab2c4SDaniel P. Berrangé }
472da0ab2c4SDaniel P. Berrangé
luks_bad_ivgen_name_empty(QCryptoBlockLUKSHeader * hdr)473da0ab2c4SDaniel P. Berrangé static const char *luks_bad_ivgen_name_empty(QCryptoBlockLUKSHeader *hdr)
474da0ab2c4SDaniel P. Berrangé {
475da0ab2c4SDaniel P. Berrangé memcpy(hdr->cipher_mode, "xts-", 5);
476da0ab2c4SDaniel P. Berrangé
477da0ab2c4SDaniel P. Berrangé return "IV generator '' not supported";
478da0ab2c4SDaniel P. Berrangé }
479da0ab2c4SDaniel P. Berrangé
luks_bad_ivgen_name_unknown(QCryptoBlockLUKSHeader * hdr)480da0ab2c4SDaniel P. Berrangé static const char *luks_bad_ivgen_name_unknown(QCryptoBlockLUKSHeader *hdr)
481da0ab2c4SDaniel P. Berrangé {
482da0ab2c4SDaniel P. Berrangé memcpy(hdr->cipher_mode, "xts-plain65", 12);
483da0ab2c4SDaniel P. Berrangé
484da0ab2c4SDaniel P. Berrangé return "IV generator 'plain65' not supported";
485da0ab2c4SDaniel P. Berrangé }
486da0ab2c4SDaniel P. Berrangé
luks_bad_ivgen_hash_empty(QCryptoBlockLUKSHeader * hdr)487da0ab2c4SDaniel P. Berrangé static const char *luks_bad_ivgen_hash_empty(QCryptoBlockLUKSHeader *hdr)
488da0ab2c4SDaniel P. Berrangé {
489da0ab2c4SDaniel P. Berrangé memcpy(hdr->cipher_mode, "xts-plain65:", 13);
490da0ab2c4SDaniel P. Berrangé
491da0ab2c4SDaniel P. Berrangé return "Hash algorithm '' not supported";
492da0ab2c4SDaniel P. Berrangé }
493da0ab2c4SDaniel P. Berrangé
luks_bad_ivgen_hash_unknown(QCryptoBlockLUKSHeader * hdr)494da0ab2c4SDaniel P. Berrangé static const char *luks_bad_ivgen_hash_unknown(QCryptoBlockLUKSHeader *hdr)
495da0ab2c4SDaniel P. Berrangé {
496da0ab2c4SDaniel P. Berrangé memcpy(hdr->cipher_mode, "xts-plain65:sha257", 19);
497da0ab2c4SDaniel P. Berrangé
498da0ab2c4SDaniel P. Berrangé return "Hash algorithm 'sha257' not supported";
499da0ab2c4SDaniel P. Berrangé }
500da0ab2c4SDaniel P. Berrangé
luks_bad_hash_spec_empty(QCryptoBlockLUKSHeader * hdr)501da0ab2c4SDaniel P. Berrangé static const char *luks_bad_hash_spec_empty(QCryptoBlockLUKSHeader *hdr)
502da0ab2c4SDaniel P. Berrangé {
503da0ab2c4SDaniel P. Berrangé memcpy(hdr->hash_spec, "", 1);
504da0ab2c4SDaniel P. Berrangé
505da0ab2c4SDaniel P. Berrangé return "Hash algorithm '' not supported";
506da0ab2c4SDaniel P. Berrangé }
507da0ab2c4SDaniel P. Berrangé
luks_bad_hash_spec_unknown(QCryptoBlockLUKSHeader * hdr)508da0ab2c4SDaniel P. Berrangé static const char *luks_bad_hash_spec_unknown(QCryptoBlockLUKSHeader *hdr)
509da0ab2c4SDaniel P. Berrangé {
510da0ab2c4SDaniel P. Berrangé memcpy(hdr->hash_spec, "sha2566", 8);
511da0ab2c4SDaniel P. Berrangé
512da0ab2c4SDaniel P. Berrangé return "Hash algorithm 'sha2566' not supported";
513da0ab2c4SDaniel P. Berrangé }
514da0ab2c4SDaniel P. Berrangé
luks_bad_stripes(QCryptoBlockLUKSHeader * hdr)515da0ab2c4SDaniel P. Berrangé static const char *luks_bad_stripes(QCryptoBlockLUKSHeader *hdr)
516da0ab2c4SDaniel P. Berrangé {
517da0ab2c4SDaniel P. Berrangé hdr->key_slots[0].stripes = 3999;
518da0ab2c4SDaniel P. Berrangé
519da0ab2c4SDaniel P. Berrangé return "Keyslot 0 is corrupted (stripes 3999 != 4000)";
520da0ab2c4SDaniel P. Berrangé }
521da0ab2c4SDaniel P. Berrangé
luks_bad_key_overlap_header(QCryptoBlockLUKSHeader * hdr)522da0ab2c4SDaniel P. Berrangé static const char *luks_bad_key_overlap_header(QCryptoBlockLUKSHeader *hdr)
523da0ab2c4SDaniel P. Berrangé {
524da0ab2c4SDaniel P. Berrangé hdr->key_slots[0].key_offset_sector = 2;
525da0ab2c4SDaniel P. Berrangé
526da0ab2c4SDaniel P. Berrangé return "Keyslot 0 is overlapping with the LUKS header";
527da0ab2c4SDaniel P. Berrangé }
528da0ab2c4SDaniel P. Berrangé
luks_bad_key_overlap_key(QCryptoBlockLUKSHeader * hdr)529da0ab2c4SDaniel P. Berrangé static const char *luks_bad_key_overlap_key(QCryptoBlockLUKSHeader *hdr)
530da0ab2c4SDaniel P. Berrangé {
531da0ab2c4SDaniel P. Berrangé hdr->key_slots[0].key_offset_sector = hdr->key_slots[1].key_offset_sector;
532da0ab2c4SDaniel P. Berrangé
533da0ab2c4SDaniel P. Berrangé return "Keyslots 0 and 1 are overlapping in the header";
534da0ab2c4SDaniel P. Berrangé }
535da0ab2c4SDaniel P. Berrangé
luks_bad_key_overlap_payload(QCryptoBlockLUKSHeader * hdr)536da0ab2c4SDaniel P. Berrangé static const char *luks_bad_key_overlap_payload(QCryptoBlockLUKSHeader *hdr)
537da0ab2c4SDaniel P. Berrangé {
538da0ab2c4SDaniel P. Berrangé hdr->key_slots[0].key_offset_sector = hdr->payload_offset_sector + 42;
539da0ab2c4SDaniel P. Berrangé
540da0ab2c4SDaniel P. Berrangé return "Keyslot 0 is overlapping with the encrypted payload";
541da0ab2c4SDaniel P. Berrangé }
542da0ab2c4SDaniel P. Berrangé
luks_bad_payload_overlap_header(QCryptoBlockLUKSHeader * hdr)543da0ab2c4SDaniel P. Berrangé static const char *luks_bad_payload_overlap_header(QCryptoBlockLUKSHeader *hdr)
544da0ab2c4SDaniel P. Berrangé {
545da0ab2c4SDaniel P. Berrangé hdr->payload_offset_sector = 2;
546da0ab2c4SDaniel P. Berrangé
547da0ab2c4SDaniel P. Berrangé return "LUKS payload is overlapping with the header";
548da0ab2c4SDaniel P. Berrangé }
549da0ab2c4SDaniel P. Berrangé
luks_bad_key_iterations(QCryptoBlockLUKSHeader * hdr)550da0ab2c4SDaniel P. Berrangé static const char *luks_bad_key_iterations(QCryptoBlockLUKSHeader *hdr)
551da0ab2c4SDaniel P. Berrangé {
552da0ab2c4SDaniel P. Berrangé hdr->key_slots[0].iterations = 0;
553da0ab2c4SDaniel P. Berrangé
554da0ab2c4SDaniel P. Berrangé return "Keyslot 0 iteration count is zero";
555da0ab2c4SDaniel P. Berrangé }
556da0ab2c4SDaniel P. Berrangé
luks_bad_iterations(QCryptoBlockLUKSHeader * hdr)557da0ab2c4SDaniel P. Berrangé static const char *luks_bad_iterations(QCryptoBlockLUKSHeader *hdr)
558da0ab2c4SDaniel P. Berrangé {
559da0ab2c4SDaniel P. Berrangé hdr->master_key_iterations = 0;
560da0ab2c4SDaniel P. Berrangé
561da0ab2c4SDaniel P. Berrangé return "LUKS key iteration count is zero";
562da0ab2c4SDaniel P. Berrangé }
563da0ab2c4SDaniel P. Berrangé #endif
564da0ab2c4SDaniel P. Berrangé
main(int argc,char ** argv)565da668aa1SThomas Huth int main(int argc, char **argv)
566da668aa1SThomas Huth {
567da668aa1SThomas Huth gsize i;
568da668aa1SThomas Huth
569da668aa1SThomas Huth module_call_init(MODULE_INIT_QOM);
570da668aa1SThomas Huth g_test_init(&argc, &argv, NULL);
571da668aa1SThomas Huth
572da668aa1SThomas Huth g_assert(qcrypto_init(NULL) == 0);
573da668aa1SThomas Huth
574da668aa1SThomas Huth for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
575d23d2ef3SMarkus Armbruster if (test_data[i].open_opts->format == QCRYPTO_BLOCK_FORMAT_LUKS &&
576da668aa1SThomas Huth !qcrypto_hash_supports(test_data[i].hash_alg)) {
577da668aa1SThomas Huth continue;
578da668aa1SThomas Huth }
579da668aa1SThomas Huth if (!test_data[i].slow ||
580da668aa1SThomas Huth g_test_slow()) {
581da668aa1SThomas Huth g_test_add_data_func(test_data[i].path, &test_data[i], test_block);
582da668aa1SThomas Huth }
583da668aa1SThomas Huth }
584da668aa1SThomas Huth
585da0ab2c4SDaniel P. Berrangé #ifdef TEST_LUKS
586da0ab2c4SDaniel P. Berrangé if (g_test_slow()) {
587da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/cipher-name-nul-term",
588da0ab2c4SDaniel P. Berrangé luks_bad_null_term_cipher_name,
589da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
590da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/cipher-mode-nul-term",
591da0ab2c4SDaniel P. Berrangé luks_bad_null_term_cipher_mode,
592da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
593da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/hash-spec-nul-term",
594da0ab2c4SDaniel P. Berrangé luks_bad_null_term_hash_spec,
595da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
596da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/cipher-name-empty",
597da0ab2c4SDaniel P. Berrangé luks_bad_cipher_name_empty,
598da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
599da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/cipher-name-unknown",
600da0ab2c4SDaniel P. Berrangé luks_bad_cipher_name_unknown,
601da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
602da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/cipher-xts-size",
603da0ab2c4SDaniel P. Berrangé luks_bad_cipher_xts_size,
604da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
605da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/cipher-cbc-size",
606da0ab2c4SDaniel P. Berrangé luks_bad_cipher_cbc_size,
607da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
608da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/cipher-mode-empty",
609da0ab2c4SDaniel P. Berrangé luks_bad_cipher_mode_empty,
610da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
611da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/cipher-mode-unknown",
612da0ab2c4SDaniel P. Berrangé luks_bad_cipher_mode_unknown,
613da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
614da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/ivgen-separator",
615da0ab2c4SDaniel P. Berrangé luks_bad_ivgen_separator,
616da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
617da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/ivgen-name-empty",
618da0ab2c4SDaniel P. Berrangé luks_bad_ivgen_name_empty,
619da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
620da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/ivgen-name-unknown",
621da0ab2c4SDaniel P. Berrangé luks_bad_ivgen_name_unknown,
622da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
623da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/ivgen-hash-empty",
624da0ab2c4SDaniel P. Berrangé luks_bad_ivgen_hash_empty,
625da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
626da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/ivgen-hash-unknown",
627da0ab2c4SDaniel P. Berrangé luks_bad_ivgen_hash_unknown,
628da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
629da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/hash-spec-empty",
630da0ab2c4SDaniel P. Berrangé luks_bad_hash_spec_empty,
631da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
632da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/hash-spec-unknown",
633da0ab2c4SDaniel P. Berrangé luks_bad_hash_spec_unknown,
634da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
635da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/stripes",
636da0ab2c4SDaniel P. Berrangé luks_bad_stripes,
637da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
638da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/key-overlap-header",
639da0ab2c4SDaniel P. Berrangé luks_bad_key_overlap_header,
640da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
641da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/key-overlap-key",
642da0ab2c4SDaniel P. Berrangé luks_bad_key_overlap_key,
643da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
644da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/key-overlap-payload",
645da0ab2c4SDaniel P. Berrangé luks_bad_key_overlap_payload,
646da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
647da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/payload-overlap-header",
648da0ab2c4SDaniel P. Berrangé luks_bad_payload_overlap_header,
649da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
650da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/iterations",
651da0ab2c4SDaniel P. Berrangé luks_bad_iterations,
652da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
653da0ab2c4SDaniel P. Berrangé g_test_add_data_func("/crypto/block/luks/bad/key-iterations",
654da0ab2c4SDaniel P. Berrangé luks_bad_key_iterations,
655da0ab2c4SDaniel P. Berrangé test_luks_bad_header);
656da0ab2c4SDaniel P. Berrangé }
657da0ab2c4SDaniel P. Berrangé #endif
658da0ab2c4SDaniel P. Berrangé
659da668aa1SThomas Huth return g_test_run();
660da668aa1SThomas Huth }
661