aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-12-18 17:04:15 +0000
committerPeter Maydell <peter.maydell@linaro.org>2015-12-18 17:04:15 +0000
commitc688084506cf2cf2eba4ba9df4e91abb6e3dab83 (patch)
tree6737ec5f5e2709cffae7cdd094ee09e671cf23b2 /tests
parentde532ff1df75cc80f0fb30885524e54b014d4983 (diff)
parent1d7b5b4afdcd76e24ec3678d5418b29d4ff06ad9 (diff)
Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-secrets-base-2015-12-18-1' into staging
Merge QCryptoSecret object support # gpg: Signature made Fri 18 Dec 2015 16:51:21 GMT using RSA key ID 15104FDF # gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>" # gpg: aka "Daniel P. Berrange <berrange@redhat.com>" * remotes/berrange/tags/pull-qcrypto-secrets-base-2015-12-18-1: crypto: add support for loading encrypted x509 keys crypto: add QCryptoSecret object class for password/key handling qga: convert to use error checked base64 decode qemu-char: convert to use error checked base64 decode util: add base64 decoding function Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/.gitignore2
-rw-r--r--tests/Makefile5
-rw-r--r--tests/test-base64.c109
-rw-r--r--tests/test-crypto-secret.c452
4 files changed, 568 insertions, 0 deletions
diff --git a/tests/.gitignore b/tests/.gitignore
index 77aaba6c2f..787c95c73d 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -8,11 +8,13 @@ check-qom-interface
check-qom-proplist
rcutorture
test-aio
+test-base64
test-bitops
test-blockjob-txn
test-coroutine
test-crypto-cipher
test-crypto-hash
+test-crypto-secret
test-crypto-tlscredsx509
test-crypto-tlscredsx509-work/
test-crypto-tlscredsx509-certs/
diff --git a/tests/Makefile b/tests/Makefile
index 6ff4627d0c..7d2a0d36ee 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -80,6 +80,7 @@ check-unit-y += tests/test-write-threshold$(EXESUF)
gcov-files-test-write-threshold-y = block/write-threshold.c
check-unit-$(CONFIG_GNUTLS_HASH) += tests/test-crypto-hash$(EXESUF)
check-unit-y += tests/test-crypto-cipher$(EXESUF)
+check-unit-y += tests/test-crypto-secret$(EXESUF)
check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlscredsx509$(EXESUF)
check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlssession$(EXESUF)
check-unit-$(CONFIG_LINUX) += tests/test-qga$(EXESUF)
@@ -90,6 +91,7 @@ check-unit-y += tests/test-io-channel-file$(EXESUF)
check-unit-$(CONFIG_GNUTLS) += tests/test-io-channel-tls$(EXESUF)
check-unit-y += tests/test-io-channel-command$(EXESUF)
check-unit-y += tests/test-io-channel-buffer$(EXESUF)
+check-unit-y += tests/test-base64$(EXESUF)
check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
@@ -423,6 +425,8 @@ tests/test-vmstate$(EXESUF): tests/test-vmstate.o \
$(test-qom-obj-y)
tests/test-timed-average$(EXESUF): tests/test-timed-average.o qemu-timer.o \
$(test-util-obj-y)
+tests/test-base64$(EXESUF): tests/test-base64.o \
+ libqemuutil.a libqemustub.a
tests/test-qapi-types.c tests/test-qapi-types.h :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
@@ -464,6 +468,7 @@ tests/test-mul64$(EXESUF): tests/test-mul64.o $(test-util-obj-y)
tests/test-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y)
tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o $(test-crypto-obj-y)
tests/test-crypto-cipher$(EXESUF): tests/test-crypto-cipher.o $(test-crypto-obj-y)
+tests/test-crypto-secret$(EXESUF): tests/test-crypto-secret.o $(test-crypto-obj-y)
tests/crypto-tls-x509-helpers.o-cflags := $(TASN1_CFLAGS)
tests/crypto-tls-x509-helpers.o-libs := $(TASN1_LIBS)
diff --git a/tests/test-base64.c b/tests/test-base64.c
new file mode 100644
index 0000000000..a0ca2d8de8
--- /dev/null
+++ b/tests/test-base64.c
@@ -0,0 +1,109 @@
+/*
+ * QEMU base64 helper test
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <glib.h>
+
+#include "qemu/base64.h"
+
+
+static void test_base64_good(void)
+{
+ const char input[] =
+ "QmVjYXVzZSB3ZSBmb2N1c2VkIG9uIHRoZSBzbmFrZSwgd2UgbW\n"
+ "lzc2VkIHRoZSBzY29ycGlvbi4=";
+ const char expect[] = "Because we focused on the snake, "
+ "we missed the scorpion.";
+
+ size_t len;
+ uint8_t *actual = qbase64_decode(input,
+ -1,
+ &len,
+ &error_abort);
+
+ g_assert(actual != NULL);
+ g_assert_cmpint(len, ==, strlen(expect));
+ g_assert_cmpstr((char *)actual, ==, expect);
+ g_free(actual);
+}
+
+
+static void test_base64_bad(const char *input,
+ size_t input_len)
+{
+ size_t len;
+ Error *err = NULL;
+ uint8_t *actual = qbase64_decode(input,
+ input_len,
+ &len,
+ &err);
+
+ g_assert(err != NULL);
+ g_assert(actual == NULL);
+ g_assert_cmpint(len, ==, 0);
+ error_free(err);
+}
+
+
+static void test_base64_embedded_nul(void)
+{
+ /* We put a NUL character in the middle of the base64
+ * text which is invalid data, given the expected length */
+ const char input[] =
+ "QmVjYXVzZSB3ZSBmb2N1c2VkIG9uIHRoZSBzbmFrZSwgd2UgbW\0"
+ "lzc2VkIHRoZSBzY29ycGlvbi4=";
+
+ test_base64_bad(input, G_N_ELEMENTS(input) - 1);
+}
+
+
+static void test_base64_not_nul_terminated(void)
+{
+ const char input[] =
+ "QmVjYXVzZSB3ZSBmb2N1c2VkIG9uIHRoZSBzbmFrZSwgd2UgbW\n"
+ "lzc2VkIHRoZSBzY29ycGlvbi4=";
+
+ /* Using '-2' to make us drop the trailing NUL, thus
+ * creating an invalid base64 sequence for decoding */
+ test_base64_bad(input, G_N_ELEMENTS(input) - 2);
+}
+
+
+static void test_base64_invalid_chars(void)
+{
+ /* We put a single quote character in the middle
+ * of the base64 text which is invalid data */
+ const char input[] =
+ "QmVjYXVzZSB3ZSBmb2N1c2VkIG9uIHRoZSBzbmFrZSwgd2UgbW'"
+ "lzc2VkIHRoZSBzY29ycGlvbi4=";
+
+ test_base64_bad(input, strlen(input));
+}
+
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/util/base64/good", test_base64_good);
+ g_test_add_func("/util/base64/embedded-nul", test_base64_embedded_nul);
+ g_test_add_func("/util/base64/not-nul-terminated",
+ test_base64_not_nul_terminated);
+ g_test_add_func("/util/base64/invalid-chars", test_base64_invalid_chars);
+ return g_test_run();
+}
diff --git a/tests/test-crypto-secret.c b/tests/test-crypto-secret.c
new file mode 100644
index 0000000000..a49c8e31e8
--- /dev/null
+++ b/tests/test-crypto-secret.c
@@ -0,0 +1,452 @@
+/*
+ * QEMU Crypto secret handling
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <glib.h>
+
+#include "crypto/init.h"
+#include "crypto/secret.h"
+
+static void test_secret_direct(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "123456",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "123456");
+
+ object_unparent(sec);
+ g_free(pw);
+}
+
+
+static void test_secret_indirect_good(void)
+{
+ Object *sec;
+ char *fname = NULL;
+ int fd = g_file_open_tmp("secretXXXXXX",
+ &fname,
+ NULL);
+
+ g_assert(fd >= 0);
+ g_assert_nonnull(fname);
+
+ g_assert(write(fd, "123456", 6) == 6);
+
+ sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "file", fname,
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "123456");
+
+ object_unparent(sec);
+ g_free(pw);
+ close(fd);
+ g_free(fname);
+}
+
+
+static void test_secret_indirect_badfile(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ NULL,
+ "file", "does-not-exist",
+ NULL);
+
+ g_assert(sec == NULL);
+}
+
+
+static void test_secret_indirect_emptyfile(void)
+{
+ Object *sec;
+ char *fname = NULL;
+ int fd = g_file_open_tmp("secretXXXXXX",
+ &fname,
+ NULL);
+
+ g_assert(fd >= 0);
+ g_assert_nonnull(fname);
+
+ sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "file", fname,
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "");
+
+ object_unparent(sec);
+ g_free(pw);
+ close(fd);
+ g_free(fname);
+}
+
+
+static void test_secret_noconv_base64_good(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "MTIzNDU2",
+ "format", "base64",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_base64("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "MTIzNDU2");
+
+ object_unparent(sec);
+ g_free(pw);
+}
+
+
+static void test_secret_noconv_base64_bad(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ NULL,
+ "data", "MTI$NDU2",
+ "format", "base64",
+ NULL);
+
+ g_assert(sec == NULL);
+}
+
+
+static void test_secret_noconv_utf8(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "123456",
+ "format", "raw",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "123456");
+
+ object_unparent(sec);
+ g_free(pw);
+}
+
+
+static void test_secret_conv_base64_utf8valid(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "MTIzNDU2",
+ "format", "base64",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "123456");
+
+ object_unparent(sec);
+ g_free(pw);
+}
+
+
+static void test_secret_conv_base64_utf8invalid(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "f0VMRgIBAQAAAA==",
+ "format", "base64",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ NULL);
+ g_assert(pw == NULL);
+
+ object_unparent(sec);
+}
+
+
+static void test_secret_conv_utf8_base64(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "123456",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_base64("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "MTIzNDU2");
+
+ object_unparent(sec);
+ g_free(pw);
+}
+
+
+static void test_secret_crypt_raw(void)
+{
+ Object *master = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "master",
+ &error_abort,
+ "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
+ "format", "base64",
+ NULL);
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data",
+ "\xCC\xBF\xF7\x09\x46\x19\x0B\x52\x2A\x3A\xB4\x6B\xCD\x7A\xB0\xB0",
+ "format", "raw",
+ "keyid", "master",
+ "iv", "0I7Gw/TKuA+Old2W2apQ3g==",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "123456");
+
+ object_unparent(sec);
+ object_unparent(master);
+ g_free(pw);
+}
+
+
+static void test_secret_crypt_base64(void)
+{
+ Object *master = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "master",
+ &error_abort,
+ "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
+ "format", "base64",
+ NULL);
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "zL/3CUYZC1IqOrRrzXqwsA==",
+ "format", "base64",
+ "keyid", "master",
+ "iv", "0I7Gw/TKuA+Old2W2apQ3g==",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "123456");
+
+ object_unparent(sec);
+ object_unparent(master);
+ g_free(pw);
+}
+
+
+static void test_secret_crypt_short_key(void)
+{
+ Object *master = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "master",
+ &error_abort,
+ "data", "9miloPQCzGy+TL6aonfzVc",
+ "format", "base64",
+ NULL);
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ NULL,
+ "data", "zL/3CUYZC1IqOrRrzXqwsA==",
+ "format", "raw",
+ "keyid", "master",
+ "iv", "0I7Gw/TKuA+Old2W2apQ3g==",
+ NULL);
+
+ g_assert(sec == NULL);
+ object_unparent(master);
+}
+
+
+static void test_secret_crypt_short_iv(void)
+{
+ Object *master = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "master",
+ &error_abort,
+ "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
+ "format", "base64",
+ NULL);
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ NULL,
+ "data", "zL/3CUYZC1IqOrRrzXqwsA==",
+ "format", "raw",
+ "keyid", "master",
+ "iv", "0I7Gw/TKuA+Old2W2a",
+ NULL);
+
+ g_assert(sec == NULL);
+ object_unparent(master);
+}
+
+
+static void test_secret_crypt_missing_iv(void)
+{
+ Object *master = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "master",
+ &error_abort,
+ "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
+ "format", "base64",
+ NULL);
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ NULL,
+ "data", "zL/3CUYZC1IqOrRrzXqwsA==",
+ "format", "raw",
+ "keyid", "master",
+ NULL);
+
+ g_assert(sec == NULL);
+ object_unparent(master);
+}
+
+
+static void test_secret_crypt_bad_iv(void)
+{
+ Object *master = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "master",
+ &error_abort,
+ "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
+ "format", "base64",
+ NULL);
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ NULL,
+ "data", "zL/3CUYZC1IqOrRrzXqwsA==",
+ "format", "raw",
+ "keyid", "master",
+ "iv", "0I7Gw/TK$$uA+Old2W2a",
+ NULL);
+
+ g_assert(sec == NULL);
+ object_unparent(master);
+}
+
+
+int main(int argc, char **argv)
+{
+ module_call_init(MODULE_INIT_QOM);
+ g_test_init(&argc, &argv, NULL);
+
+ g_assert(qcrypto_init(NULL) == 0);
+
+ g_test_add_func("/crypto/secret/direct",
+ test_secret_direct);
+ g_test_add_func("/crypto/secret/indirect/good",
+ test_secret_indirect_good);
+ g_test_add_func("/crypto/secret/indirect/badfile",
+ test_secret_indirect_badfile);
+ g_test_add_func("/crypto/secret/indirect/emptyfile",
+ test_secret_indirect_emptyfile);
+
+ g_test_add_func("/crypto/secret/noconv/base64/good",
+ test_secret_noconv_base64_good);
+ g_test_add_func("/crypto/secret/noconv/base64/bad",
+ test_secret_noconv_base64_bad);
+ g_test_add_func("/crypto/secret/noconv/utf8",
+ test_secret_noconv_utf8);
+ g_test_add_func("/crypto/secret/conv/base64/utf8valid",
+ test_secret_conv_base64_utf8valid);
+ g_test_add_func("/crypto/secret/conv/base64/utf8invalid",
+ test_secret_conv_base64_utf8invalid);
+ g_test_add_func("/crypto/secret/conv/utf8/base64",
+ test_secret_conv_utf8_base64);
+
+ g_test_add_func("/crypto/secret/crypt/raw",
+ test_secret_crypt_raw);
+ g_test_add_func("/crypto/secret/crypt/base64",
+ test_secret_crypt_base64);
+ g_test_add_func("/crypto/secret/crypt/shortkey",
+ test_secret_crypt_short_key);
+ g_test_add_func("/crypto/secret/crypt/shortiv",
+ test_secret_crypt_short_iv);
+ g_test_add_func("/crypto/secret/crypt/missingiv",
+ test_secret_crypt_missing_iv);
+ g_test_add_func("/crypto/secret/crypt/badiv",
+ test_secret_crypt_bad_iv);
+
+ return g_test_run();
+}