diff --git a/Makefile b/Makefile index 7873ad40..53ede052 100644 --- a/Makefile +++ b/Makefile @@ -218,7 +218,7 @@ qemu/config-host.h-timestamp: ./configure --cc="${CC}" --extra-cflags="$(UNICORN_CFLAGS)" --target-list="$(UNICORN_TARGETS)" ${UNICORN_QEMU_FLAGS} printf "$(UNICORN_ARCHS)" > config.log $(MAKE) -C qemu $(SMP_MFLAGS) - $(eval UC_TARGET_OBJ += $$(wildcard qemu/util/*.o) $$(wildcard qemu/*.o) $$(wildcard qemu/qom/*.o) $$(wildcard qemu/hw/core/*.o) $$(wildcard qemu/qapi/*.o) $$(wildcard qemu/qobject/*.o)) + $(eval UC_TARGET_OBJ += $$(wildcard qemu/util/*.o) $$(wildcard qemu/*.o) $$(wildcard qemu/crypto/*.o) $$(wildcard qemu/qom/*.o) $$(wildcard qemu/hw/core/*.o) $$(wildcard qemu/qapi/*.o) $$(wildcard qemu/qobject/*.o)) unicorn: $(LIBRARY) $(ARCHIVE) diff --git a/msvc/unicorn/unicorn/unicorn.vcxproj b/msvc/unicorn/unicorn/unicorn.vcxproj index d9f2adeb..76338e17 100644 --- a/msvc/unicorn/unicorn/unicorn.vcxproj +++ b/msvc/unicorn/unicorn/unicorn.vcxproj @@ -195,6 +195,8 @@ copy $(SolutionDir)..\include\unicorn\*.h $(SolutionDir)distro\include\unicorn\ + + @@ -285,6 +287,8 @@ copy $(SolutionDir)..\include\unicorn\*.h $(SolutionDir)distro\include\unicorn\ + + diff --git a/msvc/unicorn/unicorn_static/unicorn_static.vcxproj b/msvc/unicorn/unicorn_static/unicorn_static.vcxproj index 9b05cb69..6c3aa890 100644 --- a/msvc/unicorn/unicorn_static/unicorn_static.vcxproj +++ b/msvc/unicorn/unicorn_static/unicorn_static.vcxproj @@ -22,6 +22,8 @@ + + @@ -98,6 +100,8 @@ + + diff --git a/qemu/Makefile.objs b/qemu/Makefile.objs index e8d4dfa5..e23f884f 100644 --- a/qemu/Makefile.objs +++ b/qemu/Makefile.objs @@ -1,6 +1,7 @@ ####################################################################### # Common libraries for tools and emulators util-obj-y = util/ qobject/ qapi/ qapi-types.o qapi-visit.o +util-obj-y += crypto/ ####################################################################### # block-obj-y is code used by both qemu system emulation and qemu-img diff --git a/qemu/aarch64.h b/qemu/aarch64.h index ef3453cc..cbc777c9 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -2366,6 +2366,14 @@ #define qbus_finalize qbus_finalize_aarch64 #define qbus_initfn qbus_initfn_aarch64 #define qbus_realize qbus_realize_aarch64 +#define qcrypto_hash_base64 qcrypto_hash_base64_aarch64 +#define qcrypto_hash_base64v qcrypto_hash_base64v_aarch64 +#define qcrypto_hash_bytes qcrypto_hash_bytes_aarch64 +#define qcrypto_hash_bytesv qcrypto_hash_bytesv_aarch64 +#define qcrypto_hash_digest qcrypto_hash_digest_aarch64 +#define qcrypto_hash_digestv qcrypto_hash_digestv_aarch64 +#define qcrypto_hash_supports qcrypto_hash_supports_aarch64 +#define qcrypto_init qcrypto_init_aarch64 #define qdev_create qdev_create_aarch64 #define qdev_get_type qdev_get_type_aarch64 #define qdev_register_types qdev_register_types_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index e3e491ca..2310c7f4 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -2366,6 +2366,14 @@ #define qbus_finalize qbus_finalize_aarch64eb #define qbus_initfn qbus_initfn_aarch64eb #define qbus_realize qbus_realize_aarch64eb +#define qcrypto_hash_base64 qcrypto_hash_base64_aarch64eb +#define qcrypto_hash_base64v qcrypto_hash_base64v_aarch64eb +#define qcrypto_hash_bytes qcrypto_hash_bytes_aarch64eb +#define qcrypto_hash_bytesv qcrypto_hash_bytesv_aarch64eb +#define qcrypto_hash_digest qcrypto_hash_digest_aarch64eb +#define qcrypto_hash_digestv qcrypto_hash_digestv_aarch64eb +#define qcrypto_hash_supports qcrypto_hash_supports_aarch64eb +#define qcrypto_init qcrypto_init_aarch64eb #define qdev_create qdev_create_aarch64eb #define qdev_get_type qdev_get_type_aarch64eb #define qdev_register_types qdev_register_types_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index 3d30070c..cf8b9545 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -2366,6 +2366,14 @@ #define qbus_finalize qbus_finalize_arm #define qbus_initfn qbus_initfn_arm #define qbus_realize qbus_realize_arm +#define qcrypto_hash_base64 qcrypto_hash_base64_arm +#define qcrypto_hash_base64v qcrypto_hash_base64v_arm +#define qcrypto_hash_bytes qcrypto_hash_bytes_arm +#define qcrypto_hash_bytesv qcrypto_hash_bytesv_arm +#define qcrypto_hash_digest qcrypto_hash_digest_arm +#define qcrypto_hash_digestv qcrypto_hash_digestv_arm +#define qcrypto_hash_supports qcrypto_hash_supports_arm +#define qcrypto_init qcrypto_init_arm #define qdev_create qdev_create_arm #define qdev_get_type qdev_get_type_arm #define qdev_register_types qdev_register_types_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index 5488361d..4496c15a 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -2366,6 +2366,14 @@ #define qbus_finalize qbus_finalize_armeb #define qbus_initfn qbus_initfn_armeb #define qbus_realize qbus_realize_armeb +#define qcrypto_hash_base64 qcrypto_hash_base64_armeb +#define qcrypto_hash_base64v qcrypto_hash_base64v_armeb +#define qcrypto_hash_bytes qcrypto_hash_bytes_armeb +#define qcrypto_hash_bytesv qcrypto_hash_bytesv_armeb +#define qcrypto_hash_digest qcrypto_hash_digest_armeb +#define qcrypto_hash_digestv qcrypto_hash_digestv_armeb +#define qcrypto_hash_supports qcrypto_hash_supports_armeb +#define qcrypto_init qcrypto_init_armeb #define qdev_create qdev_create_armeb #define qdev_get_type qdev_get_type_armeb #define qdev_register_types qdev_register_types_armeb diff --git a/qemu/crypto/Makefile.objs b/qemu/crypto/Makefile.objs new file mode 100644 index 00000000..3ac3dfa2 --- /dev/null +++ b/qemu/crypto/Makefile.objs @@ -0,0 +1,2 @@ +util-obj-y = init.o +util-obj-y += hash.o \ No newline at end of file diff --git a/qemu/crypto/hash.c b/qemu/crypto/hash.c new file mode 100644 index 00000000..e799ac55 --- /dev/null +++ b/qemu/crypto/hash.c @@ -0,0 +1,199 @@ +/* + * 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 . + * + */ + +#include "crypto/hash.h" + +#ifdef CONFIG_GNUTLS_HASH +#include +#include + +static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG_LAST] = { + GNUTLS_DIG_MD5, + GNUTLS_DIG_SHA1, + GNUTLS_DIG_SHA256, +}; + +gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg) +{ + if (alg < (sizeof(qcrypto_hash_alg_map) / sizeof(qcrypto_hash_alg_map[0]))) { + return true; + } + return false; +} + +int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg, + const struct iovec *iov, + size_t niov, + uint8_t **result, + size_t *resultlen, + Error **errp) +{ + int i, ret; + gnutls_hash_hd_t dig; + + if (alg >= (sizeof(qcrypto_hash_alg_map) / sizeof(qcrypto_hash_alg_map[0]))) { + error_setg(errp, + "Unknown hash algorithm %d", + alg); + return -1; + } + + ret = gnutls_hash_init(&dig, qcrypto_hash_alg_map[alg]); + + if (ret < 0) { + error_setg(errp, + "Unable to initialize hash algorithm: %s", + gnutls_strerror(ret)); + return -1; + } + + for (i = 0; i < niov; i++) { + ret = gnutls_hash(dig, iov[i].iov_base, iov[i].iov_len); + if (ret < 0) { + error_setg(errp, + "Unable process hash data: %s", + gnutls_strerror(ret)); + goto error; + } + } + + ret = gnutls_hash_get_len(qcrypto_hash_alg_map[alg]); + if (ret <= 0) { + error_setg(errp, + "Unable to get hash length: %s", + gnutls_strerror(ret)); + goto error; + } + if (*resultlen == 0) { + *resultlen = ret; + *result = g_new0(uint8_t, *resultlen); + } else if (*resultlen != ret) { + error_setg(errp, + "Result buffer size %zu is smaller than hash %d", + *resultlen, ret); + goto error; + } + + gnutls_hash_deinit(dig, *result); + return 0; + + error: + gnutls_hash_deinit(dig, NULL); + return -1; +} + +#else /* ! CONFIG_GNUTLS_HASH */ + +gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg) +{ + return false; +} + +int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg, + const struct iovec *iov, + size_t niov, + uint8_t **result, + size_t *resultlen, + Error **errp) +{ + error_setg(errp, + "Hash algorithm %d not supported without GNUTLS", + alg); + return -1; +} + +#endif /* ! CONFIG_GNUTLS_HASH */ + +int qcrypto_hash_bytes(QCryptoHashAlgorithm alg, + const char *buf, + size_t len, + uint8_t **result, + size_t *resultlen, + Error **errp) +{ + struct iovec iov = { (char *)buf, len }; + return qcrypto_hash_bytesv(alg, &iov, 1, result, resultlen, errp); +} + +static const char hex[] = "0123456789abcdef"; + +int qcrypto_hash_digestv(QCryptoHashAlgorithm alg, + const struct iovec *iov, + size_t niov, + char **digest, + Error **errp) +{ + uint8_t *result = NULL; + size_t resultlen = 0; + size_t i; + + if (qcrypto_hash_bytesv(alg, iov, niov, &result, &resultlen, errp) < 0) { + return -1; + } + + *digest = g_new0(char, (resultlen * 2) + 1); + for (i = 0 ; i < resultlen ; i++) { + (*digest)[(i * 2)] = hex[(result[i] >> 4) & 0xf]; + (*digest)[(i * 2) + 1] = hex[result[i] & 0xf]; + } + (*digest)[resultlen * 2] = '\0'; + g_free(result); + return 0; +} + +int qcrypto_hash_digest(QCryptoHashAlgorithm alg, + const char *buf, + size_t len, + char **digest, + Error **errp) +{ + struct iovec iov = { (char *)buf, len }; + + return qcrypto_hash_digestv(alg, &iov, 1, digest, errp); +} + +int qcrypto_hash_base64v(QCryptoHashAlgorithm alg, + const struct iovec *iov, + size_t niov, + char **base64, + Error **errp) +{ + uint8_t *result = NULL; + size_t resultlen = 0; + + if (qcrypto_hash_bytesv(alg, iov, niov, &result, &resultlen, errp) < 0) { + return -1; + } + + *base64 = g_base64_encode(result, resultlen); + g_free(result); + return 0; +} + +int qcrypto_hash_base64(QCryptoHashAlgorithm alg, + const char *buf, + size_t len, + char **base64, + Error **errp) +{ + struct iovec iov = { (char *)buf, len }; + + return qcrypto_hash_base64v(alg, &iov, 1, base64, errp); +} diff --git a/qemu/crypto/init.c b/qemu/crypto/init.c new file mode 100644 index 00000000..50d13e6e --- /dev/null +++ b/qemu/crypto/init.c @@ -0,0 +1,60 @@ +/* + * QEMU Crypto initialization + * + * 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 . + * + */ + +#include "crypto/init.h" + +#ifdef CONFIG_GNUTLS +#include +#include + +/* #define DEBUG_GNUTLS */ + +#ifdef DEBUG_GNUTLS +static void qcrypto_gnutls_log(int level, const char *str) +{ + fprintf(stderr, "%d: %s", level, str); +} +#endif + +int qcrypto_init(Error **errp) +{ + int ret; + ret = gnutls_global_init(); + if (ret < 0) { + error_setg(errp, + "Unable to initialize GNUTLS library: %s", + gnutls_strerror(ret)); + return -1; + } +#ifdef DEBUG_GNUTLS + gnutls_global_set_log_level(10); + gnutls_global_set_log_function(qcrypto_gnutls_log); +#endif + return 0; +} + +#else /* ! CONFIG_GNUTLS */ + +int qcrypto_init(Error **errp) +{ + return 0; +} + +#endif /* ! CONFIG_GNUTLS */ diff --git a/qemu/glib_compat.c b/qemu/glib_compat.c index 13225524..3afa7fe5 100644 --- a/qemu/glib_compat.c +++ b/qemu/glib_compat.c @@ -1452,3 +1452,286 @@ gchar** g_strsplit (const gchar *string, return str_array; } + +static const char base64_alphabet[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static gsize g_base64_encode_step(const guchar *in, gsize len, + gboolean break_lines, + gchar *out, gint *state, + gint *save) +{ + char *outptr; + const guchar *inptr; + + if (in == NULL || out == NULL || state == NULL || save == NULL) { + return 0; + } + + if (len <= 0) { + return 0; + } + + inptr = in; + outptr = out; + + if (len + ((char *) save) [0] > 2) + { + const guchar *inend = in + len - 2; + int c1, c2, c3; + int already; + + already = *state; + + switch (((char *) save)[0]) + { + case 1: + c1 = ((unsigned char *) save)[1]; + goto skip1; + case 2: + c1 = ((unsigned char *) save)[1]; + c2 = ((unsigned char *) save)[2]; + goto skip2; + } + + /* + * yes, we jump into the loop, no i'm not going to change it, + * it's beautiful! + */ + while (inptr < inend) + { + c1 = *inptr++; + skip1: + c2 = *inptr++; + skip2: + c3 = *inptr++; + *outptr++ = base64_alphabet[c1 >> 2]; + *outptr++ = base64_alphabet[c2 >> 4 | ((c1 & 0x3) << 4)]; + *outptr++ = base64_alphabet[((c2 & 0x0f) << 2) | (c3 >> 6)]; + *outptr++ = base64_alphabet[c3 & 0x3f]; + /* this is a bit ugly ... */ + if (break_lines && (++already) >= 19) + { + *outptr++ = '\n'; + already = 0; + } + } + + ((char *)save)[0] = 0; + len = 2 - (inptr - inend); + *state = already; + } + + if (len > 0) + { + char *saveout; + + /* points to the slot for the next char to save */ + saveout = & (((char *)save)[1]) + ((char *)save)[0]; + + /* len can only be 0 1 or 2 */ + switch (len) + { + case 2: *saveout++ = *inptr++; + case 1: *saveout++ = *inptr++; + } + ((char *) save)[0] += len; + } + + return outptr - out; +} + +gsize g_base64_encode_close(gboolean break_lines, gchar *out, + gint *state, gint *save) +{ + int c1, c2; + char *outptr = out; + + if (out == NULL || state == NULL || save == NULL) { + return 0; + } + + c1 = ((unsigned char *) save)[1]; + c2 = ((unsigned char *) save)[2]; + + switch (((char *) save)[0]) + { + case 2: + outptr[2] = base64_alphabet[((c2 &0x0f) << 2)]; + g_assert(outptr[2] != 0); + goto skip; + case 1: + outptr[2] = '='; + c2 = 0; /* saved state here is not relevant */ + skip: + outptr[0] = base64_alphabet[c1 >> 2 ]; + outptr[1] = base64_alphabet[c2 >> 4 | ((c1 & 0x3) << 4)]; + outptr[3] = '='; + outptr += 4; + break; + } + if (break_lines) { + *outptr++ = '\n'; + } + + *save = 0; + *state = 0; + + return outptr - out; +} + +gchar *g_base64_encode(const guchar *data, gsize len) +{ + gchar *out; + gint state = 0, outlen; + gint save = 0; + + if (data == NULL && len != 0) { + return NULL; + } + + /* We can use a smaller limit here, since we know the saved state is 0, + +1 is needed for trailing \0, also check for unlikely integer overflow */ + if (len >= ((SIZE_MAX - 1) / 4 - 1) * 3) { + //g_error("%s: input too large for Base64 encoding (%"G_GSIZE_FORMAT" chars)", + // G_STRLOC, len); + return NULL; + } + + out = g_malloc((len / 3 + 1) * 4 + 1); + + outlen = g_base64_encode_step(data, len, FALSE, out, &state, &save); + outlen += g_base64_encode_close(FALSE, out + outlen, &state, &save); + out[outlen] = '\0'; + + return (gchar *) out; +} + +static const unsigned char mime_base64_rank[256] = { + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, + 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, + 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +}; + +static gsize g_base64_decode_step(const gchar *in, gsize len, + guchar *out, gint *state, + guint *save) +{ + const guchar *inptr; + guchar *outptr; + const guchar *inend; + guchar c, rank; + guchar last[2]; + unsigned int v; + int i; + + if (in == NULL || out == NULL || state == NULL || save == NULL) { + return 0; + } + + if (len <= 0) { + return 0; + } + + inend = (const guchar *)in+len; + outptr = out; + + /* convert 4 base64 bytes to 3 normal bytes */ + v = *save; + i = *state; + + last[0] = last[1] = 0; + + /* we use the sign in the state to determine if we got a padding character + in the previous sequence */ + if (i < 0) + { + i = -i; + last[0] = '='; + } + + inptr = (const guchar *)in; + while (inptr < inend) + { + c = *inptr++; + rank = mime_base64_rank[c]; + if (rank != 0xff) + { + last[1] = last[0]; + last[0] = c; + v = (v << 6) | rank; + i++; + if (i == 4) + { + *outptr++ = v >> 16; + if (last[1] != '=') { + *outptr++ = v >> 8; + } + if (last[0] != '=') { + *outptr++ = v; + } + i = 0; + } + } + } + + *save = v; + *state = last[0] == '=' ? -i : i; + + return outptr - out; +} + +guchar *g_base64_decode(const gchar *text, gsize *out_len) +{ + guchar *ret; + gsize input_length; + gint state = 0; + guint save = 0; + + if (text == NULL || out_len == NULL) { + return NULL; + } + + input_length = strlen(text); + + /* We can use a smaller limit here, since we know the saved state is 0, + +1 used to avoid calling g_malloc0(0), and hence returning NULL */ + ret = g_malloc0((input_length / 4) * 3 + 1); + + *out_len = g_base64_decode_step(text, input_length, ret, &state, &save); + + return ret; +} + +guchar *g_base64_decode_inplace(gchar *text, gsize *out_len) +{ + gint input_length, state = 0; + guint save = 0; + + if (text == NULL || out_len == NULL) { + return NULL; + } + + input_length = strlen(text); + + if (input_length <= 1) { + return NULL; + } + + *out_len = g_base64_decode_step(text, input_length, (guchar *) text, &state, &save); + + return (guchar *) text; +} diff --git a/qemu/header_gen.py b/qemu/header_gen.py index a0554aa6..11ac4729 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -2372,6 +2372,14 @@ symbols = ( 'qbus_finalize', 'qbus_initfn', 'qbus_realize', + 'qcrypto_hash_base64', + 'qcrypto_hash_base64v', + 'qcrypto_hash_bytes', + 'qcrypto_hash_bytesv', + 'qcrypto_hash_digest', + 'qcrypto_hash_digestv', + 'qcrypto_hash_supports', + 'qcrypto_init', 'qdev_create', 'qdev_get_type', 'qdev_register_types', diff --git a/qemu/include/crypto/hash.h b/qemu/include/crypto/hash.h new file mode 100644 index 00000000..b5acbf63 --- /dev/null +++ b/qemu/include/crypto/hash.h @@ -0,0 +1,189 @@ +/* + * 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 . + * + */ + +#ifndef QCRYPTO_HASH_H__ +#define QCRYPTO_HASH_H__ + +#include "qemu-common.h" +#include "qapi/error.h" + +typedef enum { + QCRYPTO_HASH_ALG_MD5, + QCRYPTO_HASH_ALG_SHA1, + QCRYPTO_HASH_ALG_SHA256, + + QCRYPTO_HASH_ALG_LAST +} QCryptoHashAlgorithm; + + +/** + * qcrypto_hash_supports: + * @alg: the hash algorithm + * + * Determine if @alg hash algorithm is supported by the + * current configured build. + * + * Returns: true if the algorithm is supported, false otherwise + */ +gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg); + +/** + * qcrypto_hash_bytesv: + * @alg: the hash algorithm + * @iov: the array of memory regions to hash + * @niov: the length of @iov + * @result: pointer to hold output hash + * @resultlen: pointer to hold length of @result + * @errp: pointer to uninitialized error object + * + * Computes the hash across all the memory regions + * present in @iov. The @result pointer will be + * filled with raw bytes representing the computed + * hash, which will have length @resultlen. The + * memory pointer in @result must be released + * with a call to g_free() when no longer required. + * + * Returns: 0 on success, -1 on error + */ +int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg, + const struct iovec *iov, + size_t niov, + uint8_t **result, + size_t *resultlen, + Error **errp); + +/** + * qcrypto_hash_bytes: + * @alg: the hash algorithm + * @buf: the memory region to hash + * @len: the length of @buf + * @result: pointer to hold output hash + * @resultlen: pointer to hold length of @result + * @errp: pointer to uninitialized error object + * + * Computes the hash across all the memory region + * @buf of length @len. The @result pointer will be + * filled with raw bytes representing the computed + * hash, which will have length @resultlen. The + * memory pointer in @result must be released + * with a call to g_free() when no longer required. + * + * Returns: 0 on success, -1 on error + */ +int qcrypto_hash_bytes(QCryptoHashAlgorithm alg, + const char *buf, + size_t len, + uint8_t **result, + size_t *resultlen, + Error **errp); + +/** + * qcrypto_hash_digestv: + * @alg: the hash algorithm + * @iov: the array of memory regions to hash + * @niov: the length of @iov + * @digest: pointer to hold output hash + * @errp: pointer to uninitialized error object + * + * Computes the hash across all the memory regions + * present in @iov. The @digest pointer will be + * filled with the printable hex digest of the computed + * hash, which will be terminated by '\0'. The + * memory pointer in @digest must be released + * with a call to g_free() when no longer required. + * + * Returns: 0 on success, -1 on error + */ +int qcrypto_hash_digestv(QCryptoHashAlgorithm alg, + const struct iovec *iov, + size_t niov, + char **digest, + Error **errp); + +/** + * qcrypto_hash_digest: + * @alg: the hash algorithm + * @buf: the memory region to hash + * @len: the length of @buf + * @digest: pointer to hold output hash + * @errp: pointer to uninitialized error object + * + * Computes the hash across all the memory region + * @buf of length @len. The @digest pointer will be + * filled with the printable hex digest of the computed + * hash, which will be terminated by '\0'. The + * memory pointer in @digest must be released + * with a call to g_free() when no longer required. + * + * Returns: 0 on success, -1 on error + */ +int qcrypto_hash_digest(QCryptoHashAlgorithm alg, + const char *buf, + size_t len, + char **digest, + Error **errp); + +/** + * qcrypto_hash_base64v: + * @alg: the hash algorithm + * @iov: the array of memory regions to hash + * @niov: the length of @iov + * @base64: pointer to hold output hash + * @errp: pointer to uninitialized error object + * + * Computes the hash across all the memory regions + * present in @iov. The @base64 pointer will be + * filled with the base64 encoding of the computed + * hash, which will be terminated by '\0'. The + * memory pointer in @base64 must be released + * with a call to g_free() when no longer required. + * + * Returns: 0 on success, -1 on error + */ +int qcrypto_hash_base64v(QCryptoHashAlgorithm alg, + const struct iovec *iov, + size_t niov, + char **base64, + Error **errp); + +/** + * qcrypto_hash_base64: + * @alg: the hash algorithm + * @buf: the memory region to hash + * @len: the length of @buf + * @base64: pointer to hold output hash + * @errp: pointer to uninitialized error object + * + * Computes the hash across all the memory region + * @buf of length @len. The @base64 pointer will be + * filled with the base64 encoding of the computed + * hash, which will be terminated by '\0'. The + * memory pointer in @base64 must be released + * with a call to g_free() when no longer required. + * + * Returns: 0 on success, -1 on error + */ +int qcrypto_hash_base64(QCryptoHashAlgorithm alg, + const char *buf, + size_t len, + char **base64, + Error **errp); + +#endif /* QCRYPTO_HASH_H__ */ diff --git a/qemu/include/crypto/init.h b/qemu/include/crypto/init.h new file mode 100644 index 00000000..5fc510c4 --- /dev/null +++ b/qemu/include/crypto/init.h @@ -0,0 +1,29 @@ +/* + * QEMU Crypto initialization + * + * 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 . + * + */ + +#ifndef QCRYPTO_INIT_H__ +#define QCRYPTO_INIT_H__ + +#include "qemu-common.h" +#include "qapi/error.h" + +int qcrypto_init(Error **errp); + +#endif /* QCRYPTO_INIT_H__ */ diff --git a/qemu/include/glib_compat.h b/qemu/include/glib_compat.h index 2d627ed2..6eb3827b 100644 --- a/qemu/include/glib_compat.h +++ b/qemu/include/glib_compat.h @@ -44,6 +44,7 @@ typedef uint32_t guint32; typedef uint64_t guint64; typedef unsigned int guint; typedef char gchar; +typedef unsigned char guchar; typedef int gboolean; typedef unsigned long gulong; typedef unsigned long gsize; @@ -128,6 +129,12 @@ gchar** g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens); +/* replacement for base64 dependency */ +gsize g_base64_encode_close(gboolean break_lines, gchar *out, + gint *state, gint *save); +gchar *g_base64_encode(const guchar *data, gsize len); +guchar *g_base64_decode(const gchar *text, gsize *out_len); +guchar *g_base64_decode_inplace(gchar *text, gsize *out_len); #define g_new(struct_type, n_structs) ((struct_type*)g_new_(sizeof(struct_type), n_structs)) #define g_new0(struct_type, n_structs) ((struct_type*)g_new0_(sizeof(struct_type), n_structs)) diff --git a/qemu/include/qemu/osdep.h b/qemu/include/qemu/osdep.h index 5387816d..5d00ecd6 100644 --- a/qemu/include/qemu/osdep.h +++ b/qemu/include/qemu/osdep.h @@ -116,6 +116,13 @@ void qemu_anon_ram_free(void *ptr, size_t size); #define FMT_pid "%d" #endif +#ifndef CONFIG_IOVEC +struct iovec { + void *iov_base; + size_t iov_len; +}; +#endif + /** * qemu_getauxval: * @type: the auxiliary vector key to lookup diff --git a/qemu/m68k.h b/qemu/m68k.h index 4e785262..824020b0 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -2366,6 +2366,14 @@ #define qbus_finalize qbus_finalize_m68k #define qbus_initfn qbus_initfn_m68k #define qbus_realize qbus_realize_m68k +#define qcrypto_hash_base64 qcrypto_hash_base64_m68k +#define qcrypto_hash_base64v qcrypto_hash_base64v_m68k +#define qcrypto_hash_bytes qcrypto_hash_bytes_m68k +#define qcrypto_hash_bytesv qcrypto_hash_bytesv_m68k +#define qcrypto_hash_digest qcrypto_hash_digest_m68k +#define qcrypto_hash_digestv qcrypto_hash_digestv_m68k +#define qcrypto_hash_supports qcrypto_hash_supports_m68k +#define qcrypto_init qcrypto_init_m68k #define qdev_create qdev_create_m68k #define qdev_get_type qdev_get_type_m68k #define qdev_register_types qdev_register_types_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 173d9520..f35c01ad 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -2366,6 +2366,14 @@ #define qbus_finalize qbus_finalize_mips #define qbus_initfn qbus_initfn_mips #define qbus_realize qbus_realize_mips +#define qcrypto_hash_base64 qcrypto_hash_base64_mips +#define qcrypto_hash_base64v qcrypto_hash_base64v_mips +#define qcrypto_hash_bytes qcrypto_hash_bytes_mips +#define qcrypto_hash_bytesv qcrypto_hash_bytesv_mips +#define qcrypto_hash_digest qcrypto_hash_digest_mips +#define qcrypto_hash_digestv qcrypto_hash_digestv_mips +#define qcrypto_hash_supports qcrypto_hash_supports_mips +#define qcrypto_init qcrypto_init_mips #define qdev_create qdev_create_mips #define qdev_get_type qdev_get_type_mips #define qdev_register_types qdev_register_types_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 5fd876ab..8a0c8c65 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -2366,6 +2366,14 @@ #define qbus_finalize qbus_finalize_mips64 #define qbus_initfn qbus_initfn_mips64 #define qbus_realize qbus_realize_mips64 +#define qcrypto_hash_base64 qcrypto_hash_base64_mips64 +#define qcrypto_hash_base64v qcrypto_hash_base64v_mips64 +#define qcrypto_hash_bytes qcrypto_hash_bytes_mips64 +#define qcrypto_hash_bytesv qcrypto_hash_bytesv_mips64 +#define qcrypto_hash_digest qcrypto_hash_digest_mips64 +#define qcrypto_hash_digestv qcrypto_hash_digestv_mips64 +#define qcrypto_hash_supports qcrypto_hash_supports_mips64 +#define qcrypto_init qcrypto_init_mips64 #define qdev_create qdev_create_mips64 #define qdev_get_type qdev_get_type_mips64 #define qdev_register_types qdev_register_types_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index da89a17b..3e9d13a7 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -2366,6 +2366,14 @@ #define qbus_finalize qbus_finalize_mips64el #define qbus_initfn qbus_initfn_mips64el #define qbus_realize qbus_realize_mips64el +#define qcrypto_hash_base64 qcrypto_hash_base64_mips64el +#define qcrypto_hash_base64v qcrypto_hash_base64v_mips64el +#define qcrypto_hash_bytes qcrypto_hash_bytes_mips64el +#define qcrypto_hash_bytesv qcrypto_hash_bytesv_mips64el +#define qcrypto_hash_digest qcrypto_hash_digest_mips64el +#define qcrypto_hash_digestv qcrypto_hash_digestv_mips64el +#define qcrypto_hash_supports qcrypto_hash_supports_mips64el +#define qcrypto_init qcrypto_init_mips64el #define qdev_create qdev_create_mips64el #define qdev_get_type qdev_get_type_mips64el #define qdev_register_types qdev_register_types_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index a8c575e4..ae03514c 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -2366,6 +2366,14 @@ #define qbus_finalize qbus_finalize_mipsel #define qbus_initfn qbus_initfn_mipsel #define qbus_realize qbus_realize_mipsel +#define qcrypto_hash_base64 qcrypto_hash_base64_mipsel +#define qcrypto_hash_base64v qcrypto_hash_base64v_mipsel +#define qcrypto_hash_bytes qcrypto_hash_bytes_mipsel +#define qcrypto_hash_bytesv qcrypto_hash_bytesv_mipsel +#define qcrypto_hash_digest qcrypto_hash_digest_mipsel +#define qcrypto_hash_digestv qcrypto_hash_digestv_mipsel +#define qcrypto_hash_supports qcrypto_hash_supports_mipsel +#define qcrypto_init qcrypto_init_mipsel #define qdev_create qdev_create_mipsel #define qdev_get_type qdev_get_type_mipsel #define qdev_register_types qdev_register_types_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index a3716f05..c480478b 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -2366,6 +2366,14 @@ #define qbus_finalize qbus_finalize_powerpc #define qbus_initfn qbus_initfn_powerpc #define qbus_realize qbus_realize_powerpc +#define qcrypto_hash_base64 qcrypto_hash_base64_powerpc +#define qcrypto_hash_base64v qcrypto_hash_base64v_powerpc +#define qcrypto_hash_bytes qcrypto_hash_bytes_powerpc +#define qcrypto_hash_bytesv qcrypto_hash_bytesv_powerpc +#define qcrypto_hash_digest qcrypto_hash_digest_powerpc +#define qcrypto_hash_digestv qcrypto_hash_digestv_powerpc +#define qcrypto_hash_supports qcrypto_hash_supports_powerpc +#define qcrypto_init qcrypto_init_powerpc #define qdev_create qdev_create_powerpc #define qdev_get_type qdev_get_type_powerpc #define qdev_register_types qdev_register_types_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index f83eefb8..c62cb60c 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -2366,6 +2366,14 @@ #define qbus_finalize qbus_finalize_sparc #define qbus_initfn qbus_initfn_sparc #define qbus_realize qbus_realize_sparc +#define qcrypto_hash_base64 qcrypto_hash_base64_sparc +#define qcrypto_hash_base64v qcrypto_hash_base64v_sparc +#define qcrypto_hash_bytes qcrypto_hash_bytes_sparc +#define qcrypto_hash_bytesv qcrypto_hash_bytesv_sparc +#define qcrypto_hash_digest qcrypto_hash_digest_sparc +#define qcrypto_hash_digestv qcrypto_hash_digestv_sparc +#define qcrypto_hash_supports qcrypto_hash_supports_sparc +#define qcrypto_init qcrypto_init_sparc #define qdev_create qdev_create_sparc #define qdev_get_type qdev_get_type_sparc #define qdev_register_types qdev_register_types_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index a96b632d..e7baf1be 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -2366,6 +2366,14 @@ #define qbus_finalize qbus_finalize_sparc64 #define qbus_initfn qbus_initfn_sparc64 #define qbus_realize qbus_realize_sparc64 +#define qcrypto_hash_base64 qcrypto_hash_base64_sparc64 +#define qcrypto_hash_base64v qcrypto_hash_base64v_sparc64 +#define qcrypto_hash_bytes qcrypto_hash_bytes_sparc64 +#define qcrypto_hash_bytesv qcrypto_hash_bytesv_sparc64 +#define qcrypto_hash_digest qcrypto_hash_digest_sparc64 +#define qcrypto_hash_digestv qcrypto_hash_digestv_sparc64 +#define qcrypto_hash_supports qcrypto_hash_supports_sparc64 +#define qcrypto_init qcrypto_init_sparc64 #define qdev_create qdev_create_sparc64 #define qdev_get_type qdev_get_type_sparc64 #define qdev_register_types qdev_register_types_sparc64 diff --git a/qemu/vl.c b/qemu/vl.c index f6c68b47..8e42985f 100644 --- a/qemu/vl.c +++ b/qemu/vl.c @@ -30,6 +30,7 @@ #include "sysemu/cpus.h" #include "vl.h" #include "uc_priv.h" +#include "crypto/init.h" #define DEFAULT_RAM_SIZE 128 @@ -80,6 +81,7 @@ int machine_initialize(struct uc_struct *uc) { MachineClass *machine_class; MachineState *current_machine; + Error *err = NULL; module_call_init(uc, MODULE_INIT_QOM); register_types_object(uc); @@ -88,6 +90,13 @@ int machine_initialize(struct uc_struct *uc) cpu_register_types(uc); qdev_register_types(uc); + // Init crypto + if (qcrypto_init(&err) < 0) { + //fprintf(stderr, "Cannot initialize crypto: %s\n", + // error_get_pretty(err)); + return -1; + } + // Initialize arch specific. uc->init_arch(uc); diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 6ba2e52b..36bc833e 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -2366,6 +2366,14 @@ #define qbus_finalize qbus_finalize_x86_64 #define qbus_initfn qbus_initfn_x86_64 #define qbus_realize qbus_realize_x86_64 +#define qcrypto_hash_base64 qcrypto_hash_base64_x86_64 +#define qcrypto_hash_base64v qcrypto_hash_base64v_x86_64 +#define qcrypto_hash_bytes qcrypto_hash_bytes_x86_64 +#define qcrypto_hash_bytesv qcrypto_hash_bytesv_x86_64 +#define qcrypto_hash_digest qcrypto_hash_digest_x86_64 +#define qcrypto_hash_digestv qcrypto_hash_digestv_x86_64 +#define qcrypto_hash_supports qcrypto_hash_supports_x86_64 +#define qcrypto_init qcrypto_init_x86_64 #define qdev_create qdev_create_x86_64 #define qdev_get_type qdev_get_type_x86_64 #define qdev_register_types qdev_register_types_x86_64