vlmcsd/crypto_windows.c
2015-11-29 17:30:52 +08:00

171 lines
4.1 KiB
C

/*
* crypto_windows.c
*/
#ifndef CONFIG
#define CONFIG "config.h"
#endif // CONFIG
#include CONFIG
#ifdef _CRYPTO_WINDOWS
#if !_WIN32 && !__CYGWIN__
#error You cannot use Windows CryptoAPI on non-Windows platforms
#else // _WIN32 || __CYGWIN__
#include "crypto_windows.h"
typedef struct _HMAC_KEYBLOB
{
BLOBHEADER hdr;
DWORD dwKeySize;
BYTE KeyData[16];
} HMAC_KEYBLOB;
/*
* MingW and Cygwin define NULL as ((void*)0) (Posix standard) which you can't assign to
* non-pointer types without compiler warning. Thus we use the following
*/
#define NULLHANDLE 0
#define NULLFLAGS 0
static HCRYPTPROV hRsaAesProvider = 0; // Needs to be initialized just once per process
static int_fast8_t AcquireCryptContext()
{
if (!hRsaAesProvider)
{
return CryptAcquireContextW
(
&hRsaAesProvider, // Provider handle
NULL, // No key container name
NULL, // Default provider
PROV_RSA_AES, // Provides SHA and AES
CRYPT_VERIFYCONTEXT // We don't need access to persistent keys
);
}
return TRUE;
}
int_fast8_t Sha256(BYTE* restrict data, DWORD DataSize, BYTE* restrict hash)
{
HCRYPTHASH hHash = 0;
DWORD HashSize = 32;
int_fast8_t success =
AcquireCryptContext() &&
CryptCreateHash
(
hRsaAesProvider,// Provider handle
CALG_SHA_256, // Algorithm
NULLHANDLE, // SHA256 requires no key
NULLFLAGS, // Use default flags
&hHash // Handle for hashing
) &&
CryptHashData
(
hHash, // Handle
data, // data to hash
DataSize, // size of data
NULLFLAGS // Use default flags
) &&
CryptGetHashParam
(
hHash, // Handle
HP_HASHVAL, // what you actually want to get (the resulting hash)
hash, // data to retrieve
&HashSize, // size of data
NULLFLAGS // currently reserved (as of this writing)
);
if (hHash) CryptDestroyHash(hHash);
return success;
}
int_fast8_t Sha256Hmac(const BYTE* key, BYTE* restrict data, DWORD len, BYTE* restrict hmac)
{
# ifndef USE_THREADS // In fork() mode thread-safety is not required
static
# endif
HMAC_KEYBLOB hmackeyblob = {
// Type, Version, Algorithm
{ PLAINTEXTKEYBLOB, CUR_BLOB_VERSION, 0, CALG_RC2 },
// Key length
16
};
HCRYPTKEY hKey = NULLHANDLE;
HCRYPTHASH hHmacHash = NULLHANDLE;
HMAC_INFO HmacInfo = { 0 };
DWORD dwHmacSize = 32;
HmacInfo.HashAlgid = CALG_SHA_256;
memcpy(hmackeyblob.KeyData, key, sizeof(hmackeyblob.KeyData));
BOOL success =
AcquireCryptContext() &&
CryptImportKey
(
hRsaAesProvider, // provider handle
(PBYTE)&hmackeyblob, // the actual key MS blob format
sizeof(HMAC_KEYBLOB), // size of the entire blob
NULLHANDLE, // password/key for the key store (none required here)
NULLFLAGS, // default flags
&hKey // key handle to retrieve (must be kept until you finish hashing)
) &&
CryptCreateHash
(
hRsaAesProvider, // provider handle
CALG_HMAC, // the actual key MS blob format
hKey, // size of the entire blob
NULLFLAGS, // password/key for the key store (none required here)
&hHmacHash // default flags
) && // key handle to retrieve (must be kept until you finish hashing)
CryptSetHashParam
(
hHmacHash, // hash handle
HP_HMAC_INFO, // parameter you want to set
(PBYTE)&HmacInfo, // the HMAC parameters (SHA256 with default ipad and opad)
NULLFLAGS // flags are reserved up to Windows 8.1
) &&
CryptHashData
(
hHmacHash, // hash handle
data, // Pointer to data you want to hash
len, // data length
NULLFLAGS // default flags
) &&
CryptGetHashParam
(
hHmacHash, // hash handle
HP_HASHVAL, // what you actually want to get (the resulting HMAC)
hmac, // data to retrieve
&dwHmacSize, // size of data
NULLFLAGS // currently reserved (as of this writing)
);
if (hKey) CryptDestroyKey(hKey);
if (hHmacHash) CryptDestroyHash(hHmacHash);
return success;
}
#endif // _WIN32 || __CYGWIN__
#endif // _CRYPTO_WINDOWS