Thread safety for rand-w32

This commit is contained in:
Asanka Herath
2009-11-26 01:39:42 -05:00
parent e3882ffc62
commit 49d28d3f3a

View File

@@ -32,8 +32,8 @@
*/ */
#include <config.h> #include <config.h>
#include <roken.h>
#include <windows.h>
#include <wincrypt.h> #include <wincrypt.h>
#include <stdio.h> #include <stdio.h>
@@ -41,27 +41,37 @@
#include <rand.h> #include <rand.h>
#include <heim_threads.h> #include <heim_threads.h>
#include <roken.h>
#include "randi.h" #include "randi.h"
static HCRYPTPROV cryptprovider = 0; volatile static HCRYPTPROV g_cryptprovider = 0;
static HCRYPTPROV static HCRYPTPROV
_hc_CryptProvider(void) _hc_CryptProvider(void)
{ {
BOOL res; BOOL res;
HCRYPTPROV cryptprovider = 0;
if (g_cryptprovider != 0)
return g_cryptprovider;
if (cryptprovider != 0)
return cryptprovider;
res = CryptAcquireContext(&cryptprovider, NULL, res = CryptAcquireContext(&cryptprovider, NULL,
MS_ENHANCED_PROV, PROV_RSA_FULL, MS_ENHANCED_PROV, PROV_RSA_FULL,
0); 0);
if(!res)
CryptAcquireContext(&cryptprovider, NULL, if (GetLastError() == NTE_BAD_KEYSET) {
MS_ENHANCED_PROV, PROV_RSA_FULL, if(!res)
CRYPT_NEWKEYSET); res = CryptAcquireContext(&cryptprovider, NULL,
MS_ENHANCED_PROV, PROV_RSA_FULL,
CRYPT_NEWKEYSET);
}
if (res &&
InterlockedCompareExchange(&g_cryptprovider, cryptprovider, 0) != 0) {
CryptReleaseContext(cryptprovider, 0);
cryptprovider = g_cryptprovider;
}
return cryptprovider; return cryptprovider;
} }
@@ -79,7 +89,7 @@ w32crypto_seed(const void *indata, int size)
static int static int
w32crypto_bytes(unsigned char *outdata, int size) w32crypto_bytes(unsigned char *outdata, int size)
{ {
if (CryptGenRandom(_hc_CryptProvider(), size, outdata) == 0) if (CryptGenRandom(_hc_CryptProvider(), size, outdata))
return 0; return 0;
return 1; return 1;
} }
@@ -97,12 +107,13 @@ w32crypto_add(const void *indata, int size, double entropi)
static int static int
w32crypto_pseudorand(unsigned char *outdata, int size) w32crypto_pseudorand(unsigned char *outdata, int size)
{ {
return 1;
} }
static int static int
w32crypto_status(void) w32crypto_status(void)
{ {
if (_hc_CryptProvider() == NULL) if (_hc_CryptProvider() == 0)
return 0; return 0;
return 1; return 1;
} }