diff options
author | Geert Martin Ijewski <gm.ijewski@web.de> | 2017-04-26 00:15:01 +0200 |
---|---|---|
committer | Daniel P. Berrange <berrange@redhat.com> | 2017-05-09 14:41:47 +0100 |
commit | a37278169d0d7d33270c6817f4a2e4f7345e1098 (patch) | |
tree | e3f7866ae58d6dad3b84240cca0fe7852124e04b | |
parent | e4a3507e86a1ef1453d603031bca27d5ac4cff3c (diff) |
crypto: qcrypto_random_bytes() now works on windows w/o any other crypto libs
If no crypto library is included in the build, QEMU uses
qcrypto_random_bytes() to generate random data. That function tried to open
/dev/urandom or /dev/random and if opening both files failed it errored out.
Those files obviously do not exist on windows, so there the code uses
CryptGenRandom().
Furthermore there was some refactoring and a new function
qcrypto_random_init() was introduced. If a proper crypto library (gnutls or
libgcrypt) is included in the build, this function does nothing. If neither
is included it initializes the (platform specific) handles that are used by
qcrypto_random_bytes().
Either:
* a handle to /dev/urandom | /dev/random on unix like systems
* a handle to a cryptographic service provider on windows
Signed-off-by: Geert Martin Ijewski <gm.ijewski@web.de>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
-rw-r--r-- | crypto/init.c | 6 | ||||
-rw-r--r-- | crypto/random-gcrypt.c | 2 | ||||
-rw-r--r-- | crypto/random-gnutls.c | 3 | ||||
-rw-r--r-- | crypto/random-platform.c | 45 | ||||
-rw-r--r-- | include/crypto/random.h | 9 |
5 files changed, 57 insertions, 8 deletions
diff --git a/crypto/init.c b/crypto/init.c index f65207e57d..f131c42306 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -32,6 +32,8 @@ #include <gcrypt.h> #endif +#include "crypto/random.h" + /* #define DEBUG_GNUTLS */ /* @@ -146,5 +148,9 @@ int qcrypto_init(Error **errp) gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); #endif + if (qcrypto_random_init(errp) < 0) { + return -1; + } + return 0; } diff --git a/crypto/random-gcrypt.c b/crypto/random-gcrypt.c index 0de9a096df..9f1c9ee60e 100644 --- a/crypto/random-gcrypt.c +++ b/crypto/random-gcrypt.c @@ -31,3 +31,5 @@ int qcrypto_random_bytes(uint8_t *buf, gcry_randomize(buf, buflen, GCRY_STRONG_RANDOM); return 0; } + +int qcrypto_random_init(Error **errp G_GNUC_UNUSED) { return 0; } diff --git a/crypto/random-gnutls.c b/crypto/random-gnutls.c index 04b45a8f8f..5350003a0b 100644 --- a/crypto/random-gnutls.c +++ b/crypto/random-gnutls.c @@ -41,3 +41,6 @@ int qcrypto_random_bytes(uint8_t *buf, return 0; } + + +int qcrypto_random_init(Error **errp G_GNUC_UNUSED) { return 0; } diff --git a/crypto/random-platform.c b/crypto/random-platform.c index 82b755afad..0eddb915b7 100644 --- a/crypto/random-platform.c +++ b/crypto/random-platform.c @@ -22,14 +22,16 @@ #include "crypto/random.h" -int qcrypto_random_bytes(uint8_t *buf G_GNUC_UNUSED, - size_t buflen G_GNUC_UNUSED, - Error **errp) -{ - int fd; - int ret = -1; - int got; +#ifdef _WIN32 +#include <Wincrypt.h> +static HCRYPTPROV hCryptProv; +#else +static int fd; /* a file handle to either /dev/urandom or /dev/random */ +#endif +int qcrypto_random_init(Error **errp) +{ +#ifndef _WIN32 /* TBD perhaps also add support for BSD getentropy / Linux * getrandom syscalls directly */ fd = open("/dev/urandom", O_RDONLY); @@ -41,6 +43,25 @@ int qcrypto_random_bytes(uint8_t *buf G_GNUC_UNUSED, error_setg(errp, "No /dev/urandom or /dev/random found"); return -1; } +#else + if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, + CRYPT_SILENT | CRYPT_VERIFYCONTEXT)) { + error_setg_win32(errp, GetLastError(), + "Unable to create cryptographic provider"); + return -1; + } +#endif + + return 0; +} + +int qcrypto_random_bytes(uint8_t *buf G_GNUC_UNUSED, + size_t buflen G_GNUC_UNUSED, + Error **errp) +{ +#ifndef _WIN32 + int ret = -1; + int got; while (buflen > 0) { got = read(fd, buf, buflen); @@ -59,6 +80,14 @@ int qcrypto_random_bytes(uint8_t *buf G_GNUC_UNUSED, ret = 0; cleanup: - close(fd); return ret; +#else + if (!CryptGenRandom(hCryptProv, buflen, buf)) { + error_setg_win32(errp, GetLastError(), + "Unable to read random bytes"); + return -1; + } + + return 0; +#endif } diff --git a/include/crypto/random.h b/include/crypto/random.h index a101353202..a07229ce96 100644 --- a/include/crypto/random.h +++ b/include/crypto/random.h @@ -40,5 +40,14 @@ int qcrypto_random_bytes(uint8_t *buf, size_t buflen, Error **errp); +/** + * qcrypto_random_init: + * @errp: pointer to a NULL-initialized error object + * + * Initializes the handles used by qcrypto_random_bytes + * + * Returns 0 on success, -1 on error + */ +int qcrypto_random_init(Error **errp); #endif /* QCRYPTO_RANDOM_H */ |