qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

test-crypto-secret.c (15950B)


      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
      9  * version 2.1 of the License, or (at your option) any later version.
     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 
     21 #include "qemu/osdep.h"
     22 
     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"
     29 #include <keyutils.h>
     30 #endif
     31 
     32 static 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 
     52 static void test_secret_indirect_good(void)
     53 {
     54     Object *sec;
     55     char *fname = NULL;
     56     int fd = g_file_open_tmp("qemu-test-crypto-secret-XXXXXX",
     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);
     81     unlink(fname);
     82     g_free(fname);
     83 }
     84 
     85 
     86 static 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 
    100 static void test_secret_indirect_emptyfile(void)
    101 {
    102     Object *sec;
    103     char *fname = NULL;
    104     int fd = g_file_open_tmp("qemu-test-crypto-secretXXXXXX",
    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);
    127     unlink(fname);
    128     g_free(fname);
    129 }
    130 
    131 #ifdef CONFIG_KEYUTILS
    132 
    133 #define DESCRIPTION "qemu_test_secret"
    134 #define PAYLOAD "Test Payload"
    135 
    136 
    137 static 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 
    165 static 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 
    190 static 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 
    216 static 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 
    242 static 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 
    271 #endif /* CONFIG_KEYUTILS */
    272 
    273 static 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 
    294 static 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 
    309 static 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 
    330 static 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 
    351 static 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 
    370 static 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 
    390 static 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 
    423 static 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 
    455 static 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 
    481 static 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 
    507 static 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 
    532 static 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 
    558 int 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 
    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 */
    586 
    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 }