Message ID | e3fd9c8b-8976-eb31-4092-887e94f4a5ae@web.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, Apr 25, 2017 at 07:28:07PM +0200, Geert Martin Ijewski wrote: > 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 openeing neither file worked 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 initalizes 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> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> I'll add this to my queue unless someone raises further comments. Regards, Daniel
On 04/25/2017 12:28 PM, Geert Martin Ijewski wrote: > 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 openeing neither file worked it s/openeing/opening/ s/opening neither file worked/opening both files failed/ > 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 initalizes the (platform specific) handles that s/initalizes/initializes/ > 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> > --- > +int qcrypto_random_init(Error **errp) > +{ > +#ifdef _WIN32 Weird that you use #ifdef _WIN32 here... > +int qcrypto_random_bytes(uint8_t *buf G_GNUC_UNUSED, > + size_t buflen G_GNUC_UNUSED, > + Error **errp) > +{ > +#ifndef _WIN32 ...but #ifndef here. It would be more consistent if all dual-implemented functions have the #ifdefs in the same order, so that I can focus on first or second half without having to check sense. > +++ 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 > + * > + * Initalizes the handles used by qcrypto_random_bytes s/Initalizes/Initializes/ > + * > + * Returns 0 on success, -1 on error > + */ > +int qcrypto_random_init(Error **errp); > > #endif /* QCRYPTO_RANDOM_H */
diff --git a/crypto/init.c b/crypto/init.c index f65207e..f131c42 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 0de9a09..2446142 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 qcrpto_random_init(Error **errp G_GNUC_UNUSED) { return 0; } diff --git a/crypto/random-gnutls.c b/crypto/random-gnutls.c index 04b45a8..d80c786 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 qcrpto_random_init(Error **errp G_GNUC_UNUSED) { return 0; } diff --git a/crypto/random-platform.c b/crypto/random-platform.c index 82b755a..c613b23 100644 --- a/crypto/random-platform.c +++ b/crypto/random-platform.c @@ -22,14 +22,23 @@ #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) +{ +#ifdef _WIN32 + if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, + CRYPT_SILENT | CRYPT_VERIFYCONTEXT)) { + error_setg_win32(errp, GetLastError(), + "Unable to create cryptographic provider"); + return -1; + } +#else /* TBD perhaps also add support for BSD getentropy / Linux * getrandom syscalls directly */ fd = open("/dev/urandom", O_RDONLY); @@ -41,6 +50,18 @@ int qcrypto_random_bytes(uint8_t *buf G_GNUC_UNUSED, error_setg(errp, "No /dev/urandom or /dev/random found"); 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 a101353..82a3209 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 + * + * Initalizes the handles used by qcrypto_random_bytes + * + * Returns 0 on success, -1 on error + */ +int qcrypto_random_init(Error **errp); #endif /* QCRYPTO_RANDOM_H */
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 openeing neither file worked 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 initalizes 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> --- crypto/init.c | 6 ++++++ crypto/random-gcrypt.c | 2 ++ crypto/random-gnutls.c | 3 +++ crypto/random-platform.c | 45 +++++++++++++++++++++++++++++++++++++-------- include/crypto/random.h | 9 +++++++++ 5 files changed, 57 insertions(+), 8 deletions(-)