ReactOS 0.4.17-dev-414-ge848ce1
unixlib.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS win32 DLLs
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: ReactOS emulation layer for crypt32 unixlib calls
5 * COPYRIGHT: Copyright 2026 Timo Kreuzer <timo.kreuzer@reactos.org>
6 */
7#include <assert.h>
8#include <windef.h>
9#include <winbase.h>
10#include <winreg.h>
11#include <wincrypt.h>
12#include <wine/debug.h>
13#include "crypt32_private.h"
14
16
17// See https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gpef/e051aba9-c9df-4f82-a42a-c13012c9d381
18typedef struct _CRYPT_CERT_PROP
19{
25
26static
27BOOL
29 _In_ const CRYPT_DATA_BLOB* RegBlob,
30 _Out_ PCRYPT_DER_BLOB OutCertBlob)
31{
33 DWORD offset = 0;
34
35 /* Parse the registry blob */
36 while ((offset + sizeof(CRYPT_CERT_PROP)) < RegBlob->cbData)
37 {
38 prop = (PCRYPT_CERT_PROP)(RegBlob->pbData + offset);
39
40 if (prop->dwReserved != 0x00000001)
41 {
42 /* Invalid reserved field */
43 return FALSE;
44 }
45
46 /* Check for the certificate property (ID 32) */
47 if (prop->dwPropId == 32)
48 {
49 if ((offset + prop->cbData) > RegBlob->cbData)
50 {
51 /* Invalid data size */
52 return FALSE;
53 }
54
55 OutCertBlob->cbData = prop->cbData;
56 OutCertBlob->pbData = prop->ajData;
57 return TRUE;
58 }
59
60 /* Move to the next property */
61 offset += FIELD_OFFSET(CRYPT_CERT_PROP, ajData) + prop->cbData;
62 }
63
64 return FALSE;
65}
66
67static
68BOOL
70 _In_ HKEY hRootKey,
71 _In_z_ PWSTR pwszSubkeyName,
72 _Out_ PCRYPT_DATA_BLOB RegDataBlob)
73{
74 HKEY hCert;
75 DWORD dwLength = 0;
76 DWORD dwType;
78 PVOID pvBuffer = NULL;
79
80 RegDataBlob->cbData = 0;
81 RegDataBlob->pbData = NULL;
82
83 /* Open the certificate subkey */
84 ret = RegOpenKeyExW(hRootKey, pwszSubkeyName, 0, KEY_READ, &hCert);
85 if (ret != ERROR_SUCCESS)
86 {
87 return FALSE;
88 }
89
90 /* Query blob size */
91 ret = RegQueryValueExW(hCert, L"Blob", NULL, &dwType, NULL, &dwLength);
92 if (ret != ERROR_SUCCESS || dwType != REG_BINARY)
93 {
94 RegCloseKey(hCert);
95 return FALSE;
96 }
97
98 /* Allocate the buffer */
99 pvBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
100 if (pvBuffer == NULL)
101 {
102 RegCloseKey(hCert);
103 return FALSE;
104 }
105
106 /* Fetch the registry blob */
107 ret = RegQueryValueExW(hCert, L"Blob", NULL, &dwType, pvBuffer, &dwLength);
108 RegCloseKey(hCert);
109
110 if ((ret != ERROR_SUCCESS) || (dwType != REG_BINARY))
111 {
112 HeapFree(GetProcessHeap(), 0, pvBuffer);
113 return FALSE;
114 }
115
116 RegDataBlob->pbData = pvBuffer;
117 RegDataBlob->cbData = dwLength;
118 return TRUE;
119}
120
121static
124 HKEY hRoot,
125 DWORD dwIndex,
126 PVOID pvBuffer,
127 DWORD cbBufferSize,
128 PDWORD pcbRequired)
129{
130 WCHAR awcSubkey[64];
131 CRYPT_DATA_BLOB regBlob;
132 CRYPT_DER_BLOB certBlob;
133 LSTATUS ret;
134
135 if (pcbRequired == 0)
136 {
138 }
139
140 /* Enumerate next subkey */
141 ret = RegEnumKeyW(hRoot, dwIndex, awcSubkey, ARRAYSIZE(awcSubkey));
142 if (ret != ERROR_SUCCESS)
143 {
144 return ret;
145 }
146
147 /* Load the registry blob */
148 if (!LoadCertBlobFromReg(hRoot, awcSubkey, &regBlob))
149 {
150 return ERROR_NO_DATA;
151 }
152
153 /* Extract the certificate from the registry blob */
154 if (!FindCertInRegBlob(&regBlob, &certBlob))
155 {
156 HeapFree(GetProcessHeap(), 0, regBlob.pbData);
157 return ERROR_NO_DATA;
158 }
159
160 *pcbRequired = certBlob.cbData;
161
162 /* Check if we have a usable buffer */
163 if ((pvBuffer != NULL) && (cbBufferSize >= certBlob.cbData))
164 {
165 /* Copy the certificate data to the output buffer */
166 memcpy(pvBuffer, certBlob.pbData, certBlob.cbData);
168 }
169 else
170 {
172 }
173
174 /* Free the registry blob buffer */
175 HeapFree(GetProcessHeap(), 0, regBlob.pbData);
176
177 /* Successfully retrieved a certificate */
178 return ret;
179}
180
181// Note: this function is not thread-safe! It is called under a lock in crypt32.
182static
183int
185 PVOID pvBuffer,
186 DWORD cbBufferSize,
187 PDWORD pcbRequired)
188{
189 const WCHAR* aszStoreKeyNames[] = {
190 L"Software\\Microsoft\\SystemCertificates\\Root\\Certificates",
191 L"Software\\Microsoft\\SystemCertificates\\AuthRoot\\Certificates"
192 };
193 static DWORD dwStoreIndex = 0;
194 static HKEY hStoreKey = NULL;
195 static DWORD dwCertIndex = 0;
196 LSTATUS ret;
197
198 assert(pcbRequired != NULL);
199
200 /* Root store enumeration loop */
201 for (; dwStoreIndex < ARRAYSIZE(aszStoreKeyNames); dwStoreIndex++)
202 {
203 if (hStoreKey == NULL)
204 {
205 /* Open the key for the root certificates */
207 aszStoreKeyNames[dwStoreIndex],
208 0,
209 KEY_READ,
210 &hStoreKey);
211 if (ret != ERROR_SUCCESS)
212 continue;
213 }
214
215 /* Cert enumeration loop */
216 for (; dwCertIndex < MAXDWORD; dwCertIndex++)
217 {
218
219 ret = LoadCertificateFromStore(hStoreKey,
220 dwCertIndex,
221 pvBuffer,
222 cbBufferSize,
223 pcbRequired);
224 if (ret == ERROR_SUCCESS)
225 {
226 /* Successfully retrieved a certificate */
227 dwCertIndex++;
228 return 0;
229 }
230
232 {
233 /* Buffer too small, return required size, but don't increment index! */
234 return ENOBUFS;
235 }
236
238 {
239 /* No more certificates in this store, break to move to next store */
240 break;
241 }
242 }
243
244 /* Move to the next root store */
245 RegCloseKey(hStoreKey);
246 hStoreKey = NULL;
247 dwCertIndex = 0;
248 }
249
250 /* No more certificates in any store */
251 if (hStoreKey != NULL)
252 RegCloseKey(hStoreKey);
253 hStoreKey = NULL;
254 dwStoreIndex = 0;
255 dwCertIndex = 0;
256 return ENOENT;
257}
258
260{
262 return EnumerateRootCertificates(params->buffer,
263 params->size,
264 params->needed);
265}
266
267static
268int
270 CRYPT_DATA_BLOB *pfx,
271 const WCHAR *password,
272 cert_store_data_t *data_ret)
273{
275 return -1;
276}
277
279{
281 return OpenCertStore(params->pfx,
282 params->password,
283 params->data_ret);
284}
285
286static
287int
289{
291 return -1;
292}
293
295{
297 return CloseCertStore(params->data);
298}
299
300static
301int
304 void *buf,
305 DWORD *buf_size)
306{
308 return -1;
309}
310
312{
314 return ImportStoreKey(params->data,
315 params->buf,
316 params->buf_size);
317}
318
319static
320int
323 unsigned int index,
324 void *buf,
326{
328 return -1;
329}
330
332{
334 return ImportStoreCert(params->data,
335 params->index,
336 params->buf,
337 params->buf_size);
338}
char ** Args
Definition: acdebug.h:353
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
#define RegCloseKey(hKey)
Definition: registry.h:49
UINT64 cert_store_data_t
#define ERROR_SUCCESS
Definition: deptool.c:10
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
LONG WINAPI RegEnumKeyW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, DWORD cbName)
Definition: reg.c:2393
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define HeapAlloc
Definition: compat.h:733
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define HeapFree(x, y, z)
Definition: compat.h:735
static DWORD DWORD * dwLength
Definition: fusion.c:86
#define assert(_expr)
Definition: assert.h:32
#define ENOENT
Definition: errno.h:25
#define ENOBUFS
Definition: errno.h:86
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLintptr offset
Definition: glext.h:5920
GLuint index
Definition: glext.h:6031
GLenum const GLfloat * params
Definition: glext.h:5645
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static HTREEITEM hRoot
Definition: treeview.c:383
static WCHAR password[]
Definition: url.c:33
#define _In_z_
Definition: no_sal2.h:164
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define REG_BINARY
Definition: nt_native.h:1499
#define KEY_READ
Definition: nt_native.h:1026
#define MAXDWORD
short WCHAR
Definition: pedump.c:58
DWORD * PDWORD
Definition: pedump.c:68
static int ImportStoreKey(cert_store_data_t data, void *buf, DWORD *buf_size)
Definition: unixlib.c:302
static int ImportStoreCert(cert_store_data_t data, unsigned int index, void *buf, DWORD *buf_size)
Definition: unixlib.c:321
int __reactos_call_unix_import_store_cert(void *Args)
Definition: unixlib.c:331
int __reactos_call_unix_enum_root_certs(void *Args)
Definition: unixlib.c:259
static BOOL FindCertInRegBlob(_In_ const CRYPT_DATA_BLOB *RegBlob, _Out_ PCRYPT_DER_BLOB OutCertBlob)
Definition: unixlib.c:28
int __reactos_call_unix_open_cert_store(void *Args)
Definition: unixlib.c:278
static int CloseCertStore(cert_store_data_t data)
Definition: unixlib.c:288
static int OpenCertStore(CRYPT_DATA_BLOB *pfx, const WCHAR *password, cert_store_data_t *data_ret)
Definition: unixlib.c:269
static LSTATUS LoadCertificateFromStore(HKEY hRoot, DWORD dwIndex, PVOID pvBuffer, DWORD cbBufferSize, PDWORD pcbRequired)
Definition: unixlib.c:123
struct _CRYPT_CERT_PROP CRYPT_CERT_PROP
static int EnumerateRootCertificates(PVOID pvBuffer, DWORD cbBufferSize, PDWORD pcbRequired)
Definition: unixlib.c:184
struct _CRYPT_CERT_PROP * PCRYPT_CERT_PROP
static BOOL LoadCertBlobFromReg(_In_ HKEY hRootKey, _In_z_ PWSTR pwszSubkeyName, _Out_ PCRYPT_DATA_BLOB RegDataBlob)
Definition: unixlib.c:69
int __reactos_call_unix_close_cert_store(void *Args)
Definition: unixlib.c:294
int __reactos_call_unix_import_store_key(void *Args)
Definition: unixlib.c:311
BYTE * pbData
Definition: wincrypt.h:112
DWORD dwPropId
Definition: unixlib.c:20
DWORD dwReserved
Definition: unixlib.c:21
DWORD cbData
Definition: unixlib.c:22
BYTE ajData[ANYSIZE_ARRAY]
Definition: unixlib.c:23
uint16_t * PWSTR
Definition: typedefs.h:56
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define ANYSIZE_ARRAY
Definition: typedefs.h:46
#define ERROR_NO_DATA
Definition: winerror.h:406
#define SEC_E_BUFFER_TOO_SMALL
Definition: winerror.h:4336
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
unsigned char BYTE
Definition: xxhash.c:193