#error Cannot use both OpenSSL and libmd.
#endif
+/* Common in other bcrypt implementations, but missing from VS2008. */
+#ifndef BCRYPT_SUCCESS
+#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
+#endif
+
/*
* Message digest functions for Windows platform.
*/
/*
* Initialize a Message digest.
*/
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+static int
+win_crypto_init(Digest_CTX *ctx, const WCHAR *algo)
+{
+ NTSTATUS status;
+ ctx->valid = 0;
+
+ status = BCryptOpenAlgorithmProvider(&ctx->hAlg, algo, NULL, 0);
+ if (!BCRYPT_SUCCESS(status))
+ return (ARCHIVE_FAILED);
+ status = BCryptCreateHash(ctx->hAlg, &ctx->hHash, NULL, 0, NULL, 0, 0);
+ if (!BCRYPT_SUCCESS(status)) {
+ BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
+ return (ARCHIVE_FAILED);
+ }
+
+ ctx->valid = 1;
+ return (ARCHIVE_OK);
+}
+#else
static int
win_crypto_init(Digest_CTX *ctx, DWORD prov, ALG_ID algId)
{
ctx->valid = 1;
return (ARCHIVE_OK);
}
+#endif
/*
* Update a Message digest.
if (!ctx->valid)
return (ARCHIVE_FAILED);
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ BCryptHashData(ctx->hHash,
+ (PUCHAR)(uintptr_t)buf,
+ len, 0);
+#else
CryptHashData(ctx->hash,
(unsigned char *)(uintptr_t)buf,
(DWORD)len, 0);
+#endif
return (ARCHIVE_OK);
}
static int
win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx)
{
+#if !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA)
DWORD siglen = (DWORD)bufsize;
+#endif
if (!ctx->valid)
return (ARCHIVE_FAILED);
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ BCryptFinishHash(ctx->hHash, buf, (ULONG)bufsize, 0);
+ BCryptDestroyHash(ctx->hHash);
+ BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
+#else
CryptGetHashParam(ctx->hash, HP_HASHVAL, buf, &siglen, 0);
CryptDestroyHash(ctx->hash);
CryptReleaseContext(ctx->cryptProv, 0);
+#endif
ctx->valid = 0;
return (ARCHIVE_OK);
}
static int
__archive_md5init(archive_md5_ctx *ctx)
{
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_MD5_ALGORITHM));
+#else
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5));
+#endif
}
static int
static int
__archive_sha1init(archive_sha1_ctx *ctx)
{
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_SHA1_ALGORITHM));
+#else
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1));
+#endif
}
static int
static int
__archive_sha256init(archive_sha256_ctx *ctx)
{
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_SHA256_ALGORITHM));
+#else
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256));
+#endif
}
static int
static int
__archive_sha384init(archive_sha384_ctx *ctx)
{
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_SHA384_ALGORITHM));
+#else
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384));
+#endif
}
static int
static int
__archive_sha512init(archive_sha512_ctx *ctx)
{
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_SHA512_ALGORITHM));
+#else
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512));
+#endif
}
static int
defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA512_WIN)
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+/* don't use bcrypt when XP needs to be supported */
+#include <bcrypt.h>
+typedef struct {
+ int valid;
+ BCRYPT_ALG_HANDLE hAlg;
+ BCRYPT_HASH_HANDLE hHash;
+} Digest_CTX;
+#else
#include <windows.h>
#include <wincrypt.h>
typedef struct {
HCRYPTHASH hash;
} Digest_CTX;
#endif
+#endif
/* typedefs */
#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
#include "archive.h"
#include "archive_random_private.h"
-#if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+/* don't use bcrypt when XP needs to be supported */
+#include <bcrypt.h>
+
+/* Common in other bcrypt implementations, but missing from VS2008. */
+#ifndef BCRYPT_SUCCESS
+#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
+#endif
+
+#elif defined(HAVE_WINCRYPT_H)
#include <wincrypt.h>
#endif
+#endif
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
archive_random(void *buf, size_t nbytes)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
+# if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ NTSTATUS status;
+ BCRYPT_ALG_HANDLE hAlg;
+
+ status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, NULL, 0);
+ if (!BCRYPT_SUCCESS(status))
+ return ARCHIVE_FAILED;
+ status = BCryptGenRandom(hAlg, buf, nbytes, 0);
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+ if (!BCRYPT_SUCCESS(status))
+ return ARCHIVE_FAILED;
+
+ return ARCHIVE_OK;
+# else
HCRYPTPROV hProv;
BOOL success;
#ifdef HAVE_STRING_H
#include <string.h>
#endif
-#if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+/* don't use bcrypt when XP needs to be supported */
+#include <bcrypt.h>
+
+/* Common in other bcrypt implementations, but missing from VS2008. */
+#ifndef BCRYPT_SUCCESS
+#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
+#endif
+
+#elif defined(HAVE_WINCRYPT_H)
#include <wincrypt.h>
#endif
+#endif
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
L'm', L'n', L'o', L'p', L'q', L'r', L's', L't',
L'u', L'v', L'w', L'x', L'y', L'z'
};
- HCRYPTPROV hProv;
struct archive_wstring temp_name;
wchar_t *ws;
DWORD attr;
wchar_t *xp, *ep;
int fd;
-
- hProv = (HCRYPTPROV)NULL;
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ BCRYPT_ALG_HANDLE hAlg = NULL;
+#else
+ HCRYPTPROV hProv = (HCRYPTPROV)NULL;
+#endif
fd = -1;
ws = NULL;
abort();
}
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM,
+ NULL, 0))) {
+ la_dosmaperr(GetLastError());
+ goto exit_tmpfile;
+ }
+#else
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) {
la_dosmaperr(GetLastError());
goto exit_tmpfile;
}
+#endif
for (;;) {
wchar_t *p;
/* Generate a random file name through CryptGenRandom(). */
p = xp;
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ if (!BCRYPT_SUCCESS(BCryptGenRandom(hAlg, (PUCHAR)p,
+ (DWORD)(ep - p)*sizeof(wchar_t), 0))) {
+ la_dosmaperr(GetLastError());
+ goto exit_tmpfile;
+ }
+#else
if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t),
(BYTE*)p)) {
la_dosmaperr(GetLastError());
goto exit_tmpfile;
}
+#endif
for (; p < ep; p++)
*p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))];
break;/* success! */
}
exit_tmpfile:
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ if (hAlg != NULL)
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+#else
if (hProv != (HCRYPTPROV)NULL)
CryptReleaseContext(hProv, 0);
+#endif
free(ws);
if (template == temp_name.s)
archive_wstring_free(&temp_name);