aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-07-08 20:46:35 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-07-08 20:46:35 +0100
commitacf7b7fdf31fa76b53803790917c8acf23a2badb (patch)
tree999bae49ca3a0ea7ef5476c1764c6166b17a0c12 /tests
parentc8e84287da7dd6a46c0bb0e53190e79ba4eedf24 (diff)
parent2828a307232ffceeddec9feb6a87ac660b68b693 (diff)
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
Bugfixes and Daniel Berrange's crypto library. # gpg: Signature made Wed Jul 8 12:12:29 2015 BST using RSA key ID 78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: ossaudio: fix memory leak ui: convert VNC to use generic cipher API block: convert qcow/qcow2 to use generic cipher API ui: convert VNC websockets to use crypto APIs block: convert quorum blockdrv to use crypto APIs crypto: add a nettle cipher implementation crypto: add a gcrypt cipher implementation crypto: introduce generic cipher API & built-in implementation crypto: move built-in D3DES implementation into crypto/ crypto: move built-in AES implementation into crypto/ crypto: introduce new module for computing hash digests vl: move rom_load_all after machine init done Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/.gitignore2
-rw-r--r--tests/Makefile4
-rw-r--r--tests/test-crypto-cipher.c290
-rw-r--r--tests/test-crypto-hash.c209
4 files changed, 505 insertions, 0 deletions
diff --git a/tests/.gitignore b/tests/.gitignore
index dc813c2713..ccc92e4761 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -10,6 +10,8 @@ rcutorture
test-aio
test-bitops
test-coroutine
+test-crypto-cipher
+test-crypto-hash
test-cutils
test-hbitmap
test-int128
diff --git a/tests/Makefile b/tests/Makefile
index e843a7e229..2c4b8dc5ec 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -74,6 +74,8 @@ check-unit-y += tests/test-qemu-opts$(EXESUF)
gcov-files-test-qemu-opts-y = qom/test-qemu-opts.c
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-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
@@ -343,6 +345,8 @@ tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y) l
tests/test-mul64$(EXESUF): tests/test-mul64.o libqemuutil.a
tests/test-bitops$(EXESUF): tests/test-bitops.o libqemuutil.a
+tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o libqemuutil.a libqemustub.a
+tests/test-crypto-cipher$(EXESUF): tests/test-crypto-cipher.o libqemuutil.a libqemustub.a
libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o tests/libqos/malloc.o
libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o
diff --git a/tests/test-crypto-cipher.c b/tests/test-crypto-cipher.c
new file mode 100644
index 0000000000..f9b1a03a02
--- /dev/null
+++ b/tests/test-crypto-cipher.c
@@ -0,0 +1,290 @@
+/*
+ * QEMU Crypto cipher algorithms
+ *
+ * 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/cipher.h"
+
+typedef struct QCryptoCipherTestData QCryptoCipherTestData;
+struct QCryptoCipherTestData {
+ const char *path;
+ QCryptoCipherAlgorithm alg;
+ QCryptoCipherMode mode;
+ const char *key;
+ const char *plaintext;
+ const char *ciphertext;
+ const char *iv;
+};
+
+/* AES test data comes from appendix F of:
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ */
+static QCryptoCipherTestData test_data[] = {
+ {
+ /* NIST F.1.1 ECB-AES128.Encrypt */
+ .path = "/crypto/cipher/aes-ecb-128",
+ .alg = QCRYPTO_CIPHER_ALG_AES_128,
+ .mode = QCRYPTO_CIPHER_MODE_ECB,
+ .key = "2b7e151628aed2a6abf7158809cf4f3c",
+ .plaintext =
+ "6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710",
+ .ciphertext =
+ "3ad77bb40d7a3660a89ecaf32466ef97"
+ "f5d3d58503b9699de785895a96fdbaaf"
+ "43b1cd7f598ece23881b00e3ed030688"
+ "7b0c785e27e8ad3f8223207104725dd4"
+ },
+ {
+ /* NIST F.1.3 ECB-AES192.Encrypt */
+ .path = "/crypto/cipher/aes-ecb-192",
+ .alg = QCRYPTO_CIPHER_ALG_AES_192,
+ .mode = QCRYPTO_CIPHER_MODE_ECB,
+ .key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
+ .plaintext =
+ "6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710",
+ .ciphertext =
+ "bd334f1d6e45f25ff712a214571fa5cc"
+ "974104846d0ad3ad7734ecb3ecee4eef"
+ "ef7afd2270e2e60adce0ba2face6444e"
+ "9a4b41ba738d6c72fb16691603c18e0e"
+ },
+ {
+ /* NIST F.1.5 ECB-AES256.Encrypt */
+ .path = "/crypto/cipher/aes-ecb-256",
+ .alg = QCRYPTO_CIPHER_ALG_AES_256,
+ .mode = QCRYPTO_CIPHER_MODE_ECB,
+ .key =
+ "603deb1015ca71be2b73aef0857d7781"
+ "1f352c073b6108d72d9810a30914dff4",
+ .plaintext =
+ "6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710",
+ .ciphertext =
+ "f3eed1bdb5d2a03c064b5a7e3db181f8"
+ "591ccb10d410ed26dc5ba74a31362870"
+ "b6ed21b99ca6f4f9f153e7b1beafed1d"
+ "23304b7a39f9f3ff067d8d8f9e24ecc7",
+ },
+ {
+ /* NIST F.2.1 CBC-AES128.Encrypt */
+ .path = "/crypto/cipher/aes-cbc-128",
+ .alg = QCRYPTO_CIPHER_ALG_AES_128,
+ .mode = QCRYPTO_CIPHER_MODE_CBC,
+ .key = "2b7e151628aed2a6abf7158809cf4f3c",
+ .iv = "000102030405060708090a0b0c0d0e0f",
+ .plaintext =
+ "6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710",
+ .ciphertext =
+ "7649abac8119b246cee98e9b12e9197d"
+ "5086cb9b507219ee95db113a917678b2"
+ "73bed6b8e3c1743b7116e69e22229516"
+ "3ff1caa1681fac09120eca307586e1a7",
+ },
+ {
+ /* NIST F.2.3 CBC-AES128.Encrypt */
+ .path = "/crypto/cipher/aes-cbc-192",
+ .alg = QCRYPTO_CIPHER_ALG_AES_192,
+ .mode = QCRYPTO_CIPHER_MODE_CBC,
+ .key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
+ .iv = "000102030405060708090a0b0c0d0e0f",
+ .plaintext =
+ "6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710",
+ .ciphertext =
+ "4f021db243bc633d7178183a9fa071e8"
+ "b4d9ada9ad7dedf4e5e738763f69145a"
+ "571b242012fb7ae07fa9baac3df102e0"
+ "08b0e27988598881d920a9e64f5615cd",
+ },
+ {
+ /* NIST F.2.5 CBC-AES128.Encrypt */
+ .path = "/crypto/cipher/aes-cbc-256",
+ .alg = QCRYPTO_CIPHER_ALG_AES_256,
+ .mode = QCRYPTO_CIPHER_MODE_CBC,
+ .key =
+ "603deb1015ca71be2b73aef0857d7781"
+ "1f352c073b6108d72d9810a30914dff4",
+ .iv = "000102030405060708090a0b0c0d0e0f",
+ .plaintext =
+ "6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710",
+ .ciphertext =
+ "f58c4c04d6e5f1ba779eabfb5f7bfbd6"
+ "9cfc4e967edb808d679f777bc6702c7d"
+ "39f23369a9d9bacfa530e26304231461"
+ "b2eb05e2c39be9fcda6c19078c6a9d1b",
+ },
+ {
+ .path = "/crypto/cipher/des-rfb-ecb-56",
+ .alg = QCRYPTO_CIPHER_ALG_DES_RFB,
+ .mode = QCRYPTO_CIPHER_MODE_ECB,
+ .key = "0123456789abcdef",
+ .plaintext =
+ "6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710",
+ .ciphertext =
+ "8f346aaf64eaf24040720d80648c52e7"
+ "aefc616be53ab1a3d301e69d91e01838"
+ "ffd29f1bb5596ad94ea2d8e6196b7f09"
+ "30d8ed0bf2773af36dd82a6280c20926",
+ },
+};
+
+
+static inline int unhex(char c)
+{
+ if (c >= 'a' && c <= 'f') {
+ return 10 + (c - 'a');
+ }
+ if (c >= 'A' && c <= 'F') {
+ return 10 + (c - 'A');
+ }
+ return c - '0';
+}
+
+static inline char hex(int i)
+{
+ if (i < 10) {
+ return '0' + i;
+ }
+ return 'a' + (i - 10);
+}
+
+static size_t unhex_string(const char *hexstr,
+ uint8_t **data)
+{
+ size_t len;
+ size_t i;
+
+ if (!hexstr) {
+ *data = NULL;
+ return 0;
+ }
+
+ len = strlen(hexstr);
+ *data = g_new0(uint8_t, len / 2);
+
+ for (i = 0; i < len; i += 2) {
+ (*data)[i/2] = (unhex(hexstr[i]) << 4) | unhex(hexstr[i+1]);
+ }
+ return len / 2;
+}
+
+static char *hex_string(const uint8_t *bytes,
+ size_t len)
+{
+ char *hexstr = g_new0(char, len * 2 + 1);
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ hexstr[i*2] = hex((bytes[i] >> 4) & 0xf);
+ hexstr[i*2+1] = hex(bytes[i] & 0xf);
+ }
+ hexstr[len*2] = '\0';
+
+ return hexstr;
+}
+
+static void test_cipher(const void *opaque)
+{
+ const QCryptoCipherTestData *data = opaque;
+
+ QCryptoCipher *cipher;
+ Error *err = NULL;
+ uint8_t *key, *iv, *ciphertext, *plaintext, *outtext;
+ size_t nkey, niv, nciphertext, nplaintext;
+ char *outtexthex;
+
+ g_test_message("foo");
+ nkey = unhex_string(data->key, &key);
+ niv = unhex_string(data->iv, &iv);
+ nciphertext = unhex_string(data->ciphertext, &ciphertext);
+ nplaintext = unhex_string(data->plaintext, &plaintext);
+
+ g_assert(nciphertext == nplaintext);
+
+ outtext = g_new0(uint8_t, nciphertext);
+
+ cipher = qcrypto_cipher_new(
+ data->alg, data->mode,
+ key, nkey,
+ &err);
+ g_assert(cipher != NULL);
+ g_assert(err == NULL);
+
+
+ if (iv) {
+ g_assert(qcrypto_cipher_setiv(cipher,
+ iv, niv,
+ &err) == 0);
+ g_assert(err == NULL);
+ }
+ g_assert(qcrypto_cipher_encrypt(cipher,
+ plaintext,
+ outtext,
+ nplaintext,
+ &err) == 0);
+ g_assert(err == NULL);
+
+ outtexthex = hex_string(outtext, nciphertext);
+
+ g_assert_cmpstr(outtexthex, ==, data->ciphertext);
+
+ g_free(outtext);
+ g_free(outtexthex);
+ g_free(key);
+ g_free(iv);
+ g_free(ciphertext);
+ g_free(plaintext);
+ qcrypto_cipher_free(cipher);
+}
+
+int main(int argc, char **argv)
+{
+ size_t i;
+
+ g_test_init(&argc, &argv, NULL);
+
+ g_assert(qcrypto_init(NULL) == 0);
+
+ for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
+ g_test_add_data_func(test_data[i].path, &test_data[i], test_cipher);
+ }
+ return g_test_run();
+}
diff --git a/tests/test-crypto-hash.c b/tests/test-crypto-hash.c
new file mode 100644
index 0000000000..911437e60d
--- /dev/null
+++ b/tests/test-crypto-hash.c
@@ -0,0 +1,209 @@
+/*
+ * QEMU Crypto hash algorithms
+ *
+ * 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/hash.h"
+
+#define INPUT_TEXT "Hiss hisss Hissss hiss Hiss hisss Hiss hiss"
+#define INPUT_TEXT1 "Hiss hisss "
+#define INPUT_TEXT2 "Hissss hiss "
+#define INPUT_TEXT3 "Hiss hisss Hiss hiss"
+
+#define OUTPUT_MD5 "628d206371563035ab8ef62f492bdec9"
+#define OUTPUT_SHA1 "b2e74f26758a3a421e509cee045244b78753cc02"
+#define OUTPUT_SHA256 "bc757abb0436586f392b437e5dd24096" \
+ "f7f224de6b74d4d86e2abc6121b160d0"
+
+#define OUTPUT_MD5_B64 "Yo0gY3FWMDWrjvYvSSveyQ=="
+#define OUTPUT_SHA1_B64 "sudPJnWKOkIeUJzuBFJEt4dTzAI="
+#define OUTPUT_SHA256_B64 "vHV6uwQ2WG85K0N+XdJAlvfyJN5rdNTYbiq8YSGxYNA="
+
+static const char *expected_outputs[] = {
+ [QCRYPTO_HASH_ALG_MD5] = OUTPUT_MD5,
+ [QCRYPTO_HASH_ALG_SHA1] = OUTPUT_SHA1,
+ [QCRYPTO_HASH_ALG_SHA256] = OUTPUT_SHA256,
+};
+static const char *expected_outputs_b64[] = {
+ [QCRYPTO_HASH_ALG_MD5] = OUTPUT_MD5_B64,
+ [QCRYPTO_HASH_ALG_SHA1] = OUTPUT_SHA1_B64,
+ [QCRYPTO_HASH_ALG_SHA256] = OUTPUT_SHA256_B64,
+};
+static const int expected_lens[] = {
+ [QCRYPTO_HASH_ALG_MD5] = 16,
+ [QCRYPTO_HASH_ALG_SHA1] = 20,
+ [QCRYPTO_HASH_ALG_SHA256] = 32,
+};
+
+static const char hex[] = "0123456789abcdef";
+
+/* Test with dynamic allocation */
+static void test_hash_alloc(void)
+{
+ size_t i;
+
+ g_assert(qcrypto_init(NULL) == 0);
+
+ for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
+ uint8_t *result = NULL;
+ size_t resultlen = 0;
+ int ret;
+ size_t j;
+
+ ret = qcrypto_hash_bytes(i,
+ INPUT_TEXT,
+ strlen(INPUT_TEXT),
+ &result,
+ &resultlen,
+ NULL);
+ g_assert(ret == 0);
+ g_assert(resultlen == expected_lens[i]);
+
+ for (j = 0; j < resultlen; j++) {
+ g_assert(expected_outputs[i][j * 2] == hex[(result[j] >> 4) & 0xf]);
+ g_assert(expected_outputs[i][j * 2 + 1] == hex[result[j] & 0xf]);
+ }
+ g_free(result);
+ }
+}
+
+/* Test with caller preallocating */
+static void test_hash_prealloc(void)
+{
+ size_t i;
+
+ g_assert(qcrypto_init(NULL) == 0);
+
+ for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
+ uint8_t *result;
+ size_t resultlen;
+ int ret;
+ size_t j;
+
+ resultlen = expected_lens[i];
+ result = g_new0(uint8_t, resultlen);
+
+ ret = qcrypto_hash_bytes(i,
+ INPUT_TEXT,
+ strlen(INPUT_TEXT),
+ &result,
+ &resultlen,
+ NULL);
+ g_assert(ret == 0);
+
+ g_assert(resultlen == expected_lens[i]);
+ for (j = 0; j < resultlen; j++) {
+ g_assert(expected_outputs[i][j * 2] == hex[(result[j] >> 4) & 0xf]);
+ g_assert(expected_outputs[i][j * 2 + 1] == hex[result[j] & 0xf]);
+ }
+ g_free(result);
+ }
+}
+
+
+/* Test with dynamic allocation */
+static void test_hash_iov(void)
+{
+ size_t i;
+
+ g_assert(qcrypto_init(NULL) == 0);
+
+ for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
+ struct iovec iov[3] = {
+ { .iov_base = (char *)INPUT_TEXT1, .iov_len = strlen(INPUT_TEXT1) },
+ { .iov_base = (char *)INPUT_TEXT2, .iov_len = strlen(INPUT_TEXT2) },
+ { .iov_base = (char *)INPUT_TEXT3, .iov_len = strlen(INPUT_TEXT3) },
+ };
+ uint8_t *result = NULL;
+ size_t resultlen = 0;
+ int ret;
+ size_t j;
+
+ ret = qcrypto_hash_bytesv(i,
+ iov, 3,
+ &result,
+ &resultlen,
+ NULL);
+ g_assert(ret == 0);
+ g_assert(resultlen == expected_lens[i]);
+ for (j = 0; j < resultlen; j++) {
+ g_assert(expected_outputs[i][j * 2] == hex[(result[j] >> 4) & 0xf]);
+ g_assert(expected_outputs[i][j * 2 + 1] == hex[result[j] & 0xf]);
+ }
+ g_free(result);
+ }
+}
+
+
+/* Test with printable hashing */
+static void test_hash_digest(void)
+{
+ size_t i;
+
+ g_assert(qcrypto_init(NULL) == 0);
+
+ for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
+ int ret;
+ char *digest;
+
+ ret = qcrypto_hash_digest(i,
+ INPUT_TEXT,
+ strlen(INPUT_TEXT),
+ &digest,
+ NULL);
+ g_assert(ret == 0);
+ g_assert(g_str_equal(digest, expected_outputs[i]));
+ g_free(digest);
+ }
+}
+
+/* Test with base64 encoding */
+static void test_hash_base64(void)
+{
+ size_t i;
+
+ g_assert(qcrypto_init(NULL) == 0);
+
+ for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
+ int ret;
+ char *digest;
+
+ ret = qcrypto_hash_base64(i,
+ INPUT_TEXT,
+ strlen(INPUT_TEXT),
+ &digest,
+ NULL);
+ g_assert(ret == 0);
+ g_assert(g_str_equal(digest, expected_outputs_b64[i]));
+ g_free(digest);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/crypto/hash/iov", test_hash_iov);
+ g_test_add_func("/crypto/hash/alloc", test_hash_alloc);
+ g_test_add_func("/crypto/hash/prealloc", test_hash_prealloc);
+ g_test_add_func("/crypto/hash/digest", test_hash_digest);
+ g_test_add_func("/crypto/hash/base64", test_hash_base64);
+ return g_test_run();
+}