cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

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
     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;
     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
     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;
    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
    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
    271#endif /* CONFIG_KEYUTILS */
    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
    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}