2 * Copyright 2002 Mike McCormack for CodeWeavers
3 * Copyright 2005 Juan Lang
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
30 static const WCHAR szDllName[] = { 'D','l','l',0 };
32 static char *CRYPT_GetKeyName(DWORD dwEncodingType, LPCSTR pszFuncName,
35 static const char szEncodingTypeFmt[] =
36 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
38 char numericOID[7]; /* enough for "#65535" */
42 /* MSDN says the encoding type is a mask, but it isn't treated that way.
43 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
44 * "EncodingType 2" would be expected if it were a mask. Instead native
45 * stores values in "EncodingType 3".
49 snprintf(numericOID, sizeof(numericOID), "#%d", (int)pszOID);
55 /* This is enough: the lengths of the two string parameters are explicitly
56 * counted, and we need up to five additional characters for the encoding
57 * type. These are covered by the "%d", "%s", and "%s" characters in the
58 * format specifier that are removed by sprintf.
60 len = sizeof(szEncodingTypeFmt) + lstrlenA(pszFuncName) + lstrlenA(oid);
61 szKey = HeapAlloc(GetProcessHeap(), 0, len);
63 sprintf(szKey, szEncodingTypeFmt, dwEncodingType, pszFuncName, oid);
67 BOOL WINAPI CryptRegisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
68 LPCSTR pszOID, LPCWSTR pwszDll, LPCSTR pszOverrideFuncName)
74 TRACE("%lx %s %s %s %s\n", dwEncodingType, pszFuncName, pszOID,
75 debugstr_w(pwszDll), pszOverrideFuncName);
77 /* This only registers functions for encoding certs, not messages */
78 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
81 /* Native does nothing pwszDll is NULL */
85 /* I'm not matching MS bug for bug here, because I doubt any app depends on
87 * - native "succeeds" if pszFuncName is NULL, but the nonsensical entry
88 * it creates would never be used
89 * - native returns an HRESULT rather than a Win32 error if pszOID is NULL.
90 * Instead I disallow both of these with ERROR_INVALID_PARAMETER.
92 if (!pszFuncName || !pszOID)
94 SetLastError(ERROR_INVALID_PARAMETER);
98 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
99 TRACE("Key name is %s\n", debugstr_a(szKey));
104 r = RegCreateKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
105 HeapFree(GetProcessHeap(), 0, szKey);
106 if(r != ERROR_SUCCESS)
109 /* write the values */
110 if (pszOverrideFuncName)
111 RegSetValueExA(hKey, "FuncName", 0, REG_SZ, pszOverrideFuncName,
112 lstrlenA(pszOverrideFuncName) + 1);
113 RegSetValueExW(hKey, szDllName, 0, REG_SZ, (const BYTE*) pwszDll,
114 (lstrlenW(pwszDll) + 1) * sizeof (WCHAR));
120 BOOL WINAPI CryptUnregisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
126 TRACE("%lx %s %s\n", dwEncodingType, pszFuncName, pszOID);
128 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
131 if (!pszFuncName || !pszOID)
133 SetLastError(ERROR_INVALID_PARAMETER);
137 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
138 rc = RegDeleteKeyA(HKEY_LOCAL_MACHINE, szKey);
139 HeapFree(GetProcessHeap(), 0, szKey);
142 return rc ? FALSE : TRUE;
145 BOOL WINAPI CryptGetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
146 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD *pdwValueType, BYTE *pbValueData,
153 TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType, debugstr_a(pszFuncName),
154 debugstr_a(pszOID), debugstr_w(pwszValueName), pdwValueType, pbValueData,
157 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
160 if (!pszFuncName || !pszOID || !pwszValueName)
162 SetLastError(ERROR_INVALID_PARAMETER);
166 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
167 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
168 HeapFree(GetProcessHeap(), 0, szKey);
173 rc = RegQueryValueExW(hKey, pwszValueName, NULL, pdwValueType,
174 pbValueData, pcbValueData);
179 return rc ? FALSE : TRUE;
182 BOOL WINAPI CryptSetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
183 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD dwValueType,
184 const BYTE *pbValueData, DWORD cbValueData)
190 TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType, debugstr_a(pszFuncName),
191 debugstr_a(pszOID), debugstr_w(pwszValueName), dwValueType, pbValueData,
194 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
197 if (!pszFuncName || !pszOID || !pwszValueName)
199 SetLastError(ERROR_INVALID_PARAMETER);
203 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
204 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
205 HeapFree(GetProcessHeap(), 0, szKey);
210 rc = RegSetValueExW(hKey, pwszValueName, 0, dwValueType, pbValueData,
216 return rc ? FALSE : TRUE;
219 /* Gets the registered function named szFuncName for dwCertEncodingType and
220 * lpszStructType, or NULL if one could not be found. *lib will be set to the
221 * handle of the module it's in, or NULL if no module was loaded. If the
222 * return value is NULL, *lib will also be NULL, to simplify error handling.
224 static void *CRYPT_GetFunc(DWORD dwCertEncodingType, LPCSTR lpszStructType,
225 LPCSTR szFuncName, HMODULE *lib)
228 char *szKey = CRYPT_GetKeyName(dwCertEncodingType, szFuncName,
230 const char *funcName;
233 DWORD type, size = 0;
236 r = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
237 HeapFree(GetProcessHeap(), 0, szKey);
238 if(r != ERROR_SUCCESS)
241 RegQueryValueExA(hKey, "FuncName", NULL, &type, NULL, &size);
242 if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ)
244 funcName = HeapAlloc(GetProcessHeap(), 0, size);
245 RegQueryValueExA(hKey, "FuncName", NULL, &type, (LPBYTE)funcName,
249 funcName = szFuncName;
250 RegQueryValueExW(hKey, szDllName, NULL, &type, NULL, &size);
251 if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ)
253 LPWSTR dllName = HeapAlloc(GetProcessHeap(), 0, size);
255 RegQueryValueExW(hKey, szDllName, NULL, &type, (LPBYTE)dllName,
257 *lib = LoadLibraryW(dllName);
260 ret = GetProcAddress(*lib, funcName);
263 /* Unload the library, the caller doesn't want to unload it
264 * when the return value is NULL.
270 HeapFree(GetProcessHeap(), 0, dllName);
272 if (funcName != szFuncName)
273 HeapFree(GetProcessHeap(), 0, (char *)funcName);
277 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
280 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
281 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
285 CryptEncodeObjectFunc pCryptEncodeObject;
287 TRACE("(0x%08lx, %s, %p, %p, %p)\n",
288 dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
289 "(integer value)", pvStructInfo, pbEncoded, pcbEncoded);
291 if (!pbEncoded && !pcbEncoded)
293 SetLastError(ERROR_INVALID_PARAMETER);
297 /* Try registered DLL first.. */
299 (CryptEncodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType,
300 lpszStructType, "CryptEncodeObject", &lib);
301 if (pCryptEncodeObject)
303 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
304 pvStructInfo, pbEncoded, pcbEncoded);
309 /* If not, use CryptEncodeObjectEx */
310 ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
311 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
316 static BOOL CRYPT_EncodeInt(DWORD dwCertEncodingType, const void *pvStructInfo,
317 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
321 BYTE significantBytes, padByte = 0, bytesNeeded;
322 BOOL neg = FALSE, pad = FALSE;
324 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING &&
325 (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
327 SetLastError(ERROR_FILE_NOT_FOUND);
332 SetLastError(ERROR_INVALID_PARAMETER);
336 memcpy(&val, pvStructInfo, sizeof(val));
337 /* Count the number of significant bytes. Temporarily swap sign for
338 * negatives so I count the minimum number of bytes.
345 for (significantBytes = sizeof(val); !(val & 0xff000000);
346 val <<= 8, significantBytes--)
351 if ((val & 0xff000000) < 0x80000000)
357 else if ((val & 0xff000000) > 0x7f000000)
362 bytesNeeded = 2 + significantBytes;
365 if (!pbEncoded || bytesNeeded > *pcbEncoded)
367 *pcbEncoded = bytesNeeded;
368 SetLastError(ERROR_MORE_DATA);
373 SetLastError(ERROR_INVALID_PARAMETER);
376 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
378 if (pEncodePara && pEncodePara->pfnAlloc)
379 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
381 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
382 if (!*(BYTE **)pbEncoded)
384 pbEncoded = *(BYTE **)pbEncoded;
386 *pbEncoded++ = ASN_INTEGER;
389 *pbEncoded++ = significantBytes + 1;
390 *pbEncoded++ = padByte;
393 *pbEncoded++ = significantBytes;
394 for (i = 0; i < significantBytes; i++, val <<= 8)
395 *(pbEncoded + i) = (BYTE)((val & 0xff000000) >> 24);
399 typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *,
400 DWORD, PCRYPT_ENCODE_PARA, BYTE *, DWORD *);
402 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
403 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
404 BYTE *pbEncoded, DWORD *pcbEncoded)
406 BOOL ret = FALSE, encoded = FALSE;
408 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p): semi-stub\n",
409 dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
410 "(integer value)", pvStructInfo, dwFlags, pEncodePara, pbEncoded,
413 if (!pbEncoded && !pcbEncoded)
415 SetLastError(ERROR_INVALID_PARAMETER);
419 if (!HIWORD(lpszStructType))
421 switch (LOWORD(lpszStructType))
423 case (WORD)X509_INTEGER:
424 ret = CRYPT_EncodeInt(dwCertEncodingType, pvStructInfo, dwFlags,
425 pEncodePara, pbEncoded, pcbEncoded);
428 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
434 CryptEncodeObjectExFunc pCryptEncodeObjectEx =
435 (CryptEncodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType,
436 lpszStructType, "CryptEncodeObjectEx", &lib);
438 if (pCryptEncodeObjectEx)
440 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
441 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
448 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
449 DWORD, DWORD, void *, DWORD *);
451 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
452 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
453 DWORD *pcbStructInfo)
457 CryptDecodeObjectFunc pCryptDecodeObject;
459 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n",
460 dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
461 "(integer value)", pbEncoded, cbEncoded, dwFlags, pvStructInfo,
464 if (!pvStructInfo && !pcbStructInfo)
466 SetLastError(ERROR_INVALID_PARAMETER);
470 /* Try registered DLL first.. */
472 (CryptDecodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType,
473 lpszStructType, "CryptDecodeObject", &lib);
474 if (pCryptDecodeObject)
476 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
477 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
482 /* If not, use CryptDecodeObjectEx */
483 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
484 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
489 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
490 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
492 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
493 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
494 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
496 BOOL ret = FALSE, decoded = FALSE;
498 FIXME("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p): stub\n",
499 dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
500 "(integer value)", pbEncoded, cbEncoded, dwFlags, pDecodePara,
501 pvStructInfo, pcbStructInfo);
503 if (!pvStructInfo && !pcbStructInfo)
505 SetLastError(ERROR_INVALID_PARAMETER);
509 if (!HIWORD(lpszStructType))
511 switch (LOWORD(lpszStructType))
514 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
520 CryptDecodeObjectExFunc pCryptDecodeObjectEx =
521 (CryptDecodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType,
522 lpszStructType, "CryptDecodeObjectEx", &lib);
524 if (pCryptDecodeObjectEx)
526 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
527 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,