-
Notifications
You must be signed in to change notification settings - Fork 37
/
crypto_windows.c
170 lines (136 loc) · 4.14 KB
/
crypto_windows.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
* 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