]> git.proxmox.com Git - mirror_qemu.git/blame - tests/test-crypto-secret.c
qemu-option: restrict qemu_opts_set to merge-lists QemuOpts
[mirror_qemu.git] / tests / test-crypto-secret.c
CommitLineData
ac1d8878
DB
1/*
2 * QEMU Crypto secret handling
3 *
4 * Copyright (c) 2015 Red Hat, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
422c16e7 9 * version 2.1 of the License, or (at your option) any later version.
ac1d8878
DB
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
681c28a3 21#include "qemu/osdep.h"
ac1d8878
DB
22
23#include "crypto/init.h"
24#include "crypto/secret.h"
da34e65c 25#include "qapi/error.h"
7136fc1d 26#include "qemu/module.h"
9866a33c 27#ifdef CONFIG_KEYUTILS
92500362
AK
28#include "crypto/secret_keyring.h"
29#include <keyutils.h>
30#endif
ac1d8878
DB
31
32static void test_secret_direct(void)
33{
34 Object *sec = object_new_with_props(
35 TYPE_QCRYPTO_SECRET,
36 object_get_objects_root(),
37 "sec0",
38 &error_abort,
39 "data", "123456",
40 NULL);
41
42 char *pw = qcrypto_secret_lookup_as_utf8("sec0",
43 &error_abort);
44
45 g_assert_cmpstr(pw, ==, "123456");
46
47 object_unparent(sec);
48 g_free(pw);
49}
50
51
52static void test_secret_indirect_good(void)
53{
54 Object *sec;
55 char *fname = NULL;
e7ed11f0 56 int fd = g_file_open_tmp("qemu-test-crypto-secret-XXXXXX",
ac1d8878
DB
57 &fname,
58 NULL);
59
60 g_assert(fd >= 0);
61 g_assert_nonnull(fname);
62
63 g_assert(write(fd, "123456", 6) == 6);
64
65 sec = object_new_with_props(
66 TYPE_QCRYPTO_SECRET,
67 object_get_objects_root(),
68 "sec0",
69 &error_abort,
70 "file", fname,
71 NULL);
72
73 char *pw = qcrypto_secret_lookup_as_utf8("sec0",
74 &error_abort);
75
76 g_assert_cmpstr(pw, ==, "123456");
77
78 object_unparent(sec);
79 g_free(pw);
80 close(fd);
e7ed11f0 81 unlink(fname);
ac1d8878
DB
82 g_free(fname);
83}
84
85
86static void test_secret_indirect_badfile(void)
87{
88 Object *sec = object_new_with_props(
89 TYPE_QCRYPTO_SECRET,
90 object_get_objects_root(),
91 "sec0",
92 NULL,
93 "file", "does-not-exist",
94 NULL);
95
96 g_assert(sec == NULL);
97}
98
99
100static void test_secret_indirect_emptyfile(void)
101{
102 Object *sec;
103 char *fname = NULL;
e7ed11f0 104 int fd = g_file_open_tmp("qemu-test-crypto-secretXXXXXX",
ac1d8878
DB
105 &fname,
106 NULL);
107
108 g_assert(fd >= 0);
109 g_assert_nonnull(fname);
110
111 sec = object_new_with_props(
112 TYPE_QCRYPTO_SECRET,
113 object_get_objects_root(),
114 "sec0",
115 &error_abort,
116 "file", fname,
117 NULL);
118
119 char *pw = qcrypto_secret_lookup_as_utf8("sec0",
120 &error_abort);
121
122 g_assert_cmpstr(pw, ==, "");
123
124 object_unparent(sec);
125 g_free(pw);
126 close(fd);
e7ed11f0 127 unlink(fname);
ac1d8878
DB
128 g_free(fname);
129}
130
9866a33c 131#ifdef CONFIG_KEYUTILS
92500362
AK
132
133#define DESCRIPTION "qemu_test_secret"
134#define PAYLOAD "Test Payload"
135
136
137static void test_secret_keyring_good(void)
138{
139 char key_str[16];
140 Object *sec;
141 int32_t key = add_key("user", DESCRIPTION, PAYLOAD,
142 strlen(PAYLOAD), KEY_SPEC_PROCESS_KEYRING);
143
144 g_assert(key >= 0);
145
146 snprintf(key_str, sizeof(key_str), "0x%08x", key);
147 sec = object_new_with_props(
148 TYPE_QCRYPTO_SECRET_KEYRING,
149 object_get_objects_root(),
150 "sec0",
151 &error_abort,
152 "serial", key_str,
153 NULL);
154
155 assert(0 <= keyctl_unlink(key, KEY_SPEC_PROCESS_KEYRING));
156 char *pw = qcrypto_secret_lookup_as_utf8("sec0",
157 &error_abort);
158 g_assert_cmpstr(pw, ==, PAYLOAD);
159
160 object_unparent(sec);
161 g_free(pw);
162}
163
164
165static void test_secret_keyring_revoked_key(void)
166{
167 char key_str[16];
168 Object *sec;
169 int32_t key = add_key("user", DESCRIPTION, PAYLOAD,
170 strlen(PAYLOAD), KEY_SPEC_PROCESS_KEYRING);
171 g_assert(key >= 0);
172 g_assert_false(keyctl_revoke(key));
173
174 snprintf(key_str, sizeof(key_str), "0x%08x", key);
175 sec = object_new_with_props(
176 TYPE_QCRYPTO_SECRET_KEYRING,
177 object_get_objects_root(),
178 "sec0",
179 NULL,
180 "serial", key_str,
181 NULL);
182
183 g_assert(errno == EKEYREVOKED);
184 g_assert(sec == NULL);
185
186 keyctl_unlink(key, KEY_SPEC_PROCESS_KEYRING);
187}
188
189
190static void test_secret_keyring_expired_key(void)
191{
192 char key_str[16];
193 Object *sec;
194 int32_t key = add_key("user", DESCRIPTION, PAYLOAD,
195 strlen(PAYLOAD), KEY_SPEC_PROCESS_KEYRING);
196 g_assert(key >= 0);
197 g_assert_false(keyctl_set_timeout(key, 1));
198 sleep(1);
199
200 snprintf(key_str, sizeof(key_str), "0x%08x", key);
201 sec = object_new_with_props(
202 TYPE_QCRYPTO_SECRET_KEYRING,
203 object_get_objects_root(),
204 "sec0",
205 NULL,
206 "serial", key_str,
207 NULL);
208
209 g_assert(errno == EKEYEXPIRED);
210 g_assert(sec == NULL);
211
212 keyctl_unlink(key, KEY_SPEC_PROCESS_KEYRING);
213}
214
215
216static void test_secret_keyring_bad_serial_key(void)
217{
218 Object *sec;
219
220 sec = object_new_with_props(
221 TYPE_QCRYPTO_SECRET_KEYRING,
222 object_get_objects_root(),
223 "sec0",
224 NULL,
225 "serial", "1",
226 NULL);
227
228 g_assert(errno == ENOKEY);
229 g_assert(sec == NULL);
230}
231
232/*
233 * TODO
234 * test_secret_keyring_bad_key_access_right() is not working yet.
235 * We don't know yet if this due a bug in the Linux kernel or
236 * whether it's normal syscall behavior.
237 * We've requested information from kernel maintainers.
238 * See: <https://www.spinics.net/lists/keyrings/index.html>
239 * Thread: 'security/keys: remove possessor verify after key permission check'
240 */
241
242static void test_secret_keyring_bad_key_access_right(void)
243{
244 char key_str[16];
245 Object *sec;
246
247 g_test_skip("TODO: Need responce from Linux kernel maintainers");
248 return;
249
250 int32_t key = add_key("user", DESCRIPTION, PAYLOAD,
251 strlen(PAYLOAD), KEY_SPEC_PROCESS_KEYRING);
252 g_assert(key >= 0);
253 g_assert_false(keyctl_setperm(key, KEY_POS_ALL & (~KEY_POS_READ)));
254
255 snprintf(key_str, sizeof(key_str), "0x%08x", key);
256
257 sec = object_new_with_props(
258 TYPE_QCRYPTO_SECRET_KEYRING,
259 object_get_objects_root(),
260 "sec0",
261 NULL,
262 "serial", key_str,
263 NULL);
264
265 g_assert(errno == EACCES);
266 g_assert(sec == NULL);
267
268 keyctl_unlink(key, KEY_SPEC_PROCESS_KEYRING);
269}
270
9866a33c 271#endif /* CONFIG_KEYUTILS */
ac1d8878
DB
272
273static void test_secret_noconv_base64_good(void)
274{
275 Object *sec = object_new_with_props(
276 TYPE_QCRYPTO_SECRET,
277 object_get_objects_root(),
278 "sec0",
279 &error_abort,
280 "data", "MTIzNDU2",
281 "format", "base64",
282 NULL);
283
284 char *pw = qcrypto_secret_lookup_as_base64("sec0",
285 &error_abort);
286
287 g_assert_cmpstr(pw, ==, "MTIzNDU2");
288
289 object_unparent(sec);
290 g_free(pw);
291}
292
293
294static void test_secret_noconv_base64_bad(void)
295{
296 Object *sec = object_new_with_props(
297 TYPE_QCRYPTO_SECRET,
298 object_get_objects_root(),
299 "sec0",
300 NULL,
301 "data", "MTI$NDU2",
302 "format", "base64",
303 NULL);
304
305 g_assert(sec == NULL);
306}
307
308
309static void test_secret_noconv_utf8(void)
310{
311 Object *sec = object_new_with_props(
312 TYPE_QCRYPTO_SECRET,
313 object_get_objects_root(),
314 "sec0",
315 &error_abort,
316 "data", "123456",
317 "format", "raw",
318 NULL);
319
320 char *pw = qcrypto_secret_lookup_as_utf8("sec0",
321 &error_abort);
322
323 g_assert_cmpstr(pw, ==, "123456");
324
325 object_unparent(sec);
326 g_free(pw);
327}
328
329
330static void test_secret_conv_base64_utf8valid(void)
331{
332 Object *sec = object_new_with_props(
333 TYPE_QCRYPTO_SECRET,
334 object_get_objects_root(),
335 "sec0",
336 &error_abort,
337 "data", "MTIzNDU2",
338 "format", "base64",
339 NULL);
340
341 char *pw = qcrypto_secret_lookup_as_utf8("sec0",
342 &error_abort);
343
344 g_assert_cmpstr(pw, ==, "123456");
345
346 object_unparent(sec);
347 g_free(pw);
348}
349
350
351static void test_secret_conv_base64_utf8invalid(void)
352{
353 Object *sec = object_new_with_props(
354 TYPE_QCRYPTO_SECRET,
355 object_get_objects_root(),
356 "sec0",
357 &error_abort,
358 "data", "f0VMRgIBAQAAAA==",
359 "format", "base64",
360 NULL);
361
362 char *pw = qcrypto_secret_lookup_as_utf8("sec0",
363 NULL);
364 g_assert(pw == NULL);
365
366 object_unparent(sec);
367}
368
369
370static void test_secret_conv_utf8_base64(void)
371{
372 Object *sec = object_new_with_props(
373 TYPE_QCRYPTO_SECRET,
374 object_get_objects_root(),
375 "sec0",
376 &error_abort,
377 "data", "123456",
378 NULL);
379
380 char *pw = qcrypto_secret_lookup_as_base64("sec0",
381 &error_abort);
382
383 g_assert_cmpstr(pw, ==, "MTIzNDU2");
384
385 object_unparent(sec);
386 g_free(pw);
387}
388
389
390static void test_secret_crypt_raw(void)
391{
392 Object *master = object_new_with_props(
393 TYPE_QCRYPTO_SECRET,
394 object_get_objects_root(),
395 "master",
396 &error_abort,
397 "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
398 "format", "base64",
399 NULL);
400 Object *sec = object_new_with_props(
401 TYPE_QCRYPTO_SECRET,
402 object_get_objects_root(),
403 "sec0",
404 &error_abort,
405 "data",
406 "\xCC\xBF\xF7\x09\x46\x19\x0B\x52\x2A\x3A\xB4\x6B\xCD\x7A\xB0\xB0",
407 "format", "raw",
408 "keyid", "master",
409 "iv", "0I7Gw/TKuA+Old2W2apQ3g==",
410 NULL);
411
412 char *pw = qcrypto_secret_lookup_as_utf8("sec0",
413 &error_abort);
414
415 g_assert_cmpstr(pw, ==, "123456");
416
417 object_unparent(sec);
418 object_unparent(master);
419 g_free(pw);
420}
421
422
423static void test_secret_crypt_base64(void)
424{
425 Object *master = object_new_with_props(
426 TYPE_QCRYPTO_SECRET,
427 object_get_objects_root(),
428 "master",
429 &error_abort,
430 "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
431 "format", "base64",
432 NULL);
433 Object *sec = object_new_with_props(
434 TYPE_QCRYPTO_SECRET,
435 object_get_objects_root(),
436 "sec0",
437 &error_abort,
438 "data", "zL/3CUYZC1IqOrRrzXqwsA==",
439 "format", "base64",
440 "keyid", "master",
441 "iv", "0I7Gw/TKuA+Old2W2apQ3g==",
442 NULL);
443
444 char *pw = qcrypto_secret_lookup_as_utf8("sec0",
445 &error_abort);
446
447 g_assert_cmpstr(pw, ==, "123456");
448
449 object_unparent(sec);
450 object_unparent(master);
451 g_free(pw);
452}
453
454
455static void test_secret_crypt_short_key(void)
456{
457 Object *master = object_new_with_props(
458 TYPE_QCRYPTO_SECRET,
459 object_get_objects_root(),
460 "master",
461 &error_abort,
462 "data", "9miloPQCzGy+TL6aonfzVc",
463 "format", "base64",
464 NULL);
465 Object *sec = object_new_with_props(
466 TYPE_QCRYPTO_SECRET,
467 object_get_objects_root(),
468 "sec0",
469 NULL,
470 "data", "zL/3CUYZC1IqOrRrzXqwsA==",
471 "format", "raw",
472 "keyid", "master",
473 "iv", "0I7Gw/TKuA+Old2W2apQ3g==",
474 NULL);
475
476 g_assert(sec == NULL);
477 object_unparent(master);
478}
479
480
481static void test_secret_crypt_short_iv(void)
482{
483 Object *master = object_new_with_props(
484 TYPE_QCRYPTO_SECRET,
485 object_get_objects_root(),
486 "master",
487 &error_abort,
488 "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
489 "format", "base64",
490 NULL);
491 Object *sec = object_new_with_props(
492 TYPE_QCRYPTO_SECRET,
493 object_get_objects_root(),
494 "sec0",
495 NULL,
496 "data", "zL/3CUYZC1IqOrRrzXqwsA==",
497 "format", "raw",
498 "keyid", "master",
499 "iv", "0I7Gw/TKuA+Old2W2a",
500 NULL);
501
502 g_assert(sec == NULL);
503 object_unparent(master);
504}
505
506
507static void test_secret_crypt_missing_iv(void)
508{
509 Object *master = object_new_with_props(
510 TYPE_QCRYPTO_SECRET,
511 object_get_objects_root(),
512 "master",
513 &error_abort,
514 "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
515 "format", "base64",
516 NULL);
517 Object *sec = object_new_with_props(
518 TYPE_QCRYPTO_SECRET,
519 object_get_objects_root(),
520 "sec0",
521 NULL,
522 "data", "zL/3CUYZC1IqOrRrzXqwsA==",
523 "format", "raw",
524 "keyid", "master",
525 NULL);
526
527 g_assert(sec == NULL);
528 object_unparent(master);
529}
530
531
532static void test_secret_crypt_bad_iv(void)
533{
534 Object *master = object_new_with_props(
535 TYPE_QCRYPTO_SECRET,
536 object_get_objects_root(),
537 "master",
538 &error_abort,
539 "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
540 "format", "base64",
541 NULL);
542 Object *sec = object_new_with_props(
543 TYPE_QCRYPTO_SECRET,
544 object_get_objects_root(),
545 "sec0",
546 NULL,
547 "data", "zL/3CUYZC1IqOrRrzXqwsA==",
548 "format", "raw",
549 "keyid", "master",
550 "iv", "0I7Gw/TK$$uA+Old2W2a",
551 NULL);
552
553 g_assert(sec == NULL);
554 object_unparent(master);
555}
556
557
558int main(int argc, char **argv)
559{
560 module_call_init(MODULE_INIT_QOM);
561 g_test_init(&argc, &argv, NULL);
562
563 g_assert(qcrypto_init(NULL) == 0);
564
565 g_test_add_func("/crypto/secret/direct",
566 test_secret_direct);
567 g_test_add_func("/crypto/secret/indirect/good",
568 test_secret_indirect_good);
569 g_test_add_func("/crypto/secret/indirect/badfile",
570 test_secret_indirect_badfile);
571 g_test_add_func("/crypto/secret/indirect/emptyfile",
572 test_secret_indirect_emptyfile);
573
9866a33c 574#ifdef CONFIG_KEYUTILS
92500362
AK
575 g_test_add_func("/crypto/secret/keyring/good",
576 test_secret_keyring_good);
577 g_test_add_func("/crypto/secret/keyring/revoked_key",
578 test_secret_keyring_revoked_key);
579 g_test_add_func("/crypto/secret/keyring/expired_key",
580 test_secret_keyring_expired_key);
581 g_test_add_func("/crypto/secret/keyring/bad_serial_key",
582 test_secret_keyring_bad_serial_key);
583 g_test_add_func("/crypto/secret/keyring/bad_key_access_right",
584 test_secret_keyring_bad_key_access_right);
9866a33c 585#endif /* CONFIG_KEYUTILS */
92500362 586
ac1d8878
DB
587 g_test_add_func("/crypto/secret/noconv/base64/good",
588 test_secret_noconv_base64_good);
589 g_test_add_func("/crypto/secret/noconv/base64/bad",
590 test_secret_noconv_base64_bad);
591 g_test_add_func("/crypto/secret/noconv/utf8",
592 test_secret_noconv_utf8);
593 g_test_add_func("/crypto/secret/conv/base64/utf8valid",
594 test_secret_conv_base64_utf8valid);
595 g_test_add_func("/crypto/secret/conv/base64/utf8invalid",
596 test_secret_conv_base64_utf8invalid);
597 g_test_add_func("/crypto/secret/conv/utf8/base64",
598 test_secret_conv_utf8_base64);
599
600 g_test_add_func("/crypto/secret/crypt/raw",
601 test_secret_crypt_raw);
602 g_test_add_func("/crypto/secret/crypt/base64",
603 test_secret_crypt_base64);
604 g_test_add_func("/crypto/secret/crypt/shortkey",
605 test_secret_crypt_short_key);
606 g_test_add_func("/crypto/secret/crypt/shortiv",
607 test_secret_crypt_short_iv);
608 g_test_add_func("/crypto/secret/crypt/missingiv",
609 test_secret_crypt_missing_iv);
610 g_test_add_func("/crypto/secret/crypt/badiv",
611 test_secret_crypt_bad_iv);
612
613 return g_test_run();
614}