2 * QEMU Crypto secret handling
4 * Copyright (c) 2015 Red Hat, Inc.
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
9 * version 2.1 of the License, or (at your option) any later version.
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.
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/>.
21 #include "qemu/osdep.h"
23 #include "crypto/init.h"
24 #include "crypto/secret.h"
25 #include "qapi/error.h"
26 #include "qemu/module.h"
27 #ifdef CONFIG_KEYUTILS
28 #include "crypto/secret_keyring.h"
32 static void test_secret_direct(void)
34 Object
*sec
= object_new_with_props(
36 object_get_objects_root(),
42 char *pw
= qcrypto_secret_lookup_as_utf8("sec0",
45 g_assert_cmpstr(pw
, ==, "123456");
52 static void test_secret_indirect_good(void)
56 int fd
= g_file_open_tmp("qemu-test-crypto-secret-XXXXXX",
61 g_assert_nonnull(fname
);
63 g_assert(write(fd
, "123456", 6) == 6);
65 sec
= object_new_with_props(
67 object_get_objects_root(),
73 char *pw
= qcrypto_secret_lookup_as_utf8("sec0",
76 g_assert_cmpstr(pw
, ==, "123456");
86 static void test_secret_indirect_badfile(void)
88 Object
*sec
= object_new_with_props(
90 object_get_objects_root(),
93 "file", "does-not-exist",
96 g_assert(sec
== NULL
);
100 static void test_secret_indirect_emptyfile(void)
104 int fd
= g_file_open_tmp("qemu-test-crypto-secretXXXXXX",
109 g_assert_nonnull(fname
);
111 sec
= object_new_with_props(
113 object_get_objects_root(),
119 char *pw
= qcrypto_secret_lookup_as_utf8("sec0",
122 g_assert_cmpstr(pw
, ==, "");
124 object_unparent(sec
);
131 #ifdef CONFIG_KEYUTILS
133 #define DESCRIPTION "qemu_test_secret"
134 #define PAYLOAD "Test Payload"
137 static void test_secret_keyring_good(void)
141 int32_t key
= add_key("user", DESCRIPTION
, PAYLOAD
,
142 strlen(PAYLOAD
), KEY_SPEC_PROCESS_KEYRING
);
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(),
155 assert(0 <= keyctl_unlink(key
, KEY_SPEC_PROCESS_KEYRING
));
156 char *pw
= qcrypto_secret_lookup_as_utf8("sec0",
158 g_assert_cmpstr(pw
, ==, PAYLOAD
);
160 object_unparent(sec
);
165 static void test_secret_keyring_revoked_key(void)
169 int32_t key
= add_key("user", DESCRIPTION
, PAYLOAD
,
170 strlen(PAYLOAD
), KEY_SPEC_PROCESS_KEYRING
);
172 g_assert_false(keyctl_revoke(key
));
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(),
183 g_assert(errno
== EKEYREVOKED
);
184 g_assert(sec
== NULL
);
186 keyctl_unlink(key
, KEY_SPEC_PROCESS_KEYRING
);
190 static void test_secret_keyring_expired_key(void)
194 int32_t key
= add_key("user", DESCRIPTION
, PAYLOAD
,
195 strlen(PAYLOAD
), KEY_SPEC_PROCESS_KEYRING
);
197 g_assert_false(keyctl_set_timeout(key
, 1));
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(),
209 g_assert(errno
== EKEYEXPIRED
);
210 g_assert(sec
== NULL
);
212 keyctl_unlink(key
, KEY_SPEC_PROCESS_KEYRING
);
216 static void test_secret_keyring_bad_serial_key(void)
220 sec
= object_new_with_props(
221 TYPE_QCRYPTO_SECRET_KEYRING
,
222 object_get_objects_root(),
228 g_assert(errno
== ENOKEY
);
229 g_assert(sec
== NULL
);
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'
242 static void test_secret_keyring_bad_key_access_right(void)
247 g_test_skip("TODO: Need responce from Linux kernel maintainers");
250 int32_t key
= add_key("user", DESCRIPTION
, PAYLOAD
,
251 strlen(PAYLOAD
), KEY_SPEC_PROCESS_KEYRING
);
253 g_assert_false(keyctl_setperm(key
, KEY_POS_ALL
& (~KEY_POS_READ
)));
255 snprintf(key_str
, sizeof(key_str
), "0x%08x", key
);
257 sec
= object_new_with_props(
258 TYPE_QCRYPTO_SECRET_KEYRING
,
259 object_get_objects_root(),
265 g_assert(errno
== EACCES
);
266 g_assert(sec
== NULL
);
268 keyctl_unlink(key
, KEY_SPEC_PROCESS_KEYRING
);
271 #endif /* CONFIG_KEYUTILS */
273 static void test_secret_noconv_base64_good(void)
275 Object
*sec
= object_new_with_props(
277 object_get_objects_root(),
284 char *pw
= qcrypto_secret_lookup_as_base64("sec0",
287 g_assert_cmpstr(pw
, ==, "MTIzNDU2");
289 object_unparent(sec
);
294 static void test_secret_noconv_base64_bad(void)
296 Object
*sec
= object_new_with_props(
298 object_get_objects_root(),
305 g_assert(sec
== NULL
);
309 static void test_secret_noconv_utf8(void)
311 Object
*sec
= object_new_with_props(
313 object_get_objects_root(),
320 char *pw
= qcrypto_secret_lookup_as_utf8("sec0",
323 g_assert_cmpstr(pw
, ==, "123456");
325 object_unparent(sec
);
330 static void test_secret_conv_base64_utf8valid(void)
332 Object
*sec
= object_new_with_props(
334 object_get_objects_root(),
341 char *pw
= qcrypto_secret_lookup_as_utf8("sec0",
344 g_assert_cmpstr(pw
, ==, "123456");
346 object_unparent(sec
);
351 static void test_secret_conv_base64_utf8invalid(void)
353 Object
*sec
= object_new_with_props(
355 object_get_objects_root(),
358 "data", "f0VMRgIBAQAAAA==",
362 char *pw
= qcrypto_secret_lookup_as_utf8("sec0",
364 g_assert(pw
== NULL
);
366 object_unparent(sec
);
370 static void test_secret_conv_utf8_base64(void)
372 Object
*sec
= object_new_with_props(
374 object_get_objects_root(),
380 char *pw
= qcrypto_secret_lookup_as_base64("sec0",
383 g_assert_cmpstr(pw
, ==, "MTIzNDU2");
385 object_unparent(sec
);
390 static void test_secret_crypt_raw(void)
392 Object
*master
= object_new_with_props(
394 object_get_objects_root(),
397 "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
400 Object
*sec
= object_new_with_props(
402 object_get_objects_root(),
406 "\xCC\xBF\xF7\x09\x46\x19\x0B\x52\x2A\x3A\xB4\x6B\xCD\x7A\xB0\xB0",
409 "iv", "0I7Gw/TKuA+Old2W2apQ3g==",
412 char *pw
= qcrypto_secret_lookup_as_utf8("sec0",
415 g_assert_cmpstr(pw
, ==, "123456");
417 object_unparent(sec
);
418 object_unparent(master
);
423 static void test_secret_crypt_base64(void)
425 Object
*master
= object_new_with_props(
427 object_get_objects_root(),
430 "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
433 Object
*sec
= object_new_with_props(
435 object_get_objects_root(),
438 "data", "zL/3CUYZC1IqOrRrzXqwsA==",
441 "iv", "0I7Gw/TKuA+Old2W2apQ3g==",
444 char *pw
= qcrypto_secret_lookup_as_utf8("sec0",
447 g_assert_cmpstr(pw
, ==, "123456");
449 object_unparent(sec
);
450 object_unparent(master
);
455 static void test_secret_crypt_short_key(void)
457 Object
*master
= object_new_with_props(
459 object_get_objects_root(),
462 "data", "9miloPQCzGy+TL6aonfzVc",
465 Object
*sec
= object_new_with_props(
467 object_get_objects_root(),
470 "data", "zL/3CUYZC1IqOrRrzXqwsA==",
473 "iv", "0I7Gw/TKuA+Old2W2apQ3g==",
476 g_assert(sec
== NULL
);
477 object_unparent(master
);
481 static void test_secret_crypt_short_iv(void)
483 Object
*master
= object_new_with_props(
485 object_get_objects_root(),
488 "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
491 Object
*sec
= object_new_with_props(
493 object_get_objects_root(),
496 "data", "zL/3CUYZC1IqOrRrzXqwsA==",
499 "iv", "0I7Gw/TKuA+Old2W2a",
502 g_assert(sec
== NULL
);
503 object_unparent(master
);
507 static void test_secret_crypt_missing_iv(void)
509 Object
*master
= object_new_with_props(
511 object_get_objects_root(),
514 "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
517 Object
*sec
= object_new_with_props(
519 object_get_objects_root(),
522 "data", "zL/3CUYZC1IqOrRrzXqwsA==",
527 g_assert(sec
== NULL
);
528 object_unparent(master
);
532 static void test_secret_crypt_bad_iv(void)
534 Object
*master
= object_new_with_props(
536 object_get_objects_root(),
539 "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
542 Object
*sec
= object_new_with_props(
544 object_get_objects_root(),
547 "data", "zL/3CUYZC1IqOrRrzXqwsA==",
550 "iv", "0I7Gw/TK$$uA+Old2W2a",
553 g_assert(sec
== NULL
);
554 object_unparent(master
);
558 int main(int argc
, char **argv
)
560 module_call_init(MODULE_INIT_QOM
);
561 g_test_init(&argc
, &argv
, NULL
);
563 g_assert(qcrypto_init(NULL
) == 0);
565 g_test_add_func("/crypto/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
);
574 #ifdef CONFIG_KEYUTILS
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
);
585 #endif /* CONFIG_KEYUTILS */
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
);
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
);