cd9eaddd807a6269eed34b94f12df56cf25b1ec5
[reactos.git] / reactos / lib / crypt32 / encode.c
1 /*
2 * Copyright 2002 Mike McCormack for CodeWeavers
3 * Copyright 2005 Juan Lang
4 *
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.
9 *
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.
14 *
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
18 *
19 * This file implements ASN.1 DER encoding and decoding of a limited set of
20 * types. It isn't a full ASN.1 implementation. Microsoft implements BER
21 * encoding of many of the basic types in msasn1.dll, but that interface is
22 * undocumented, so I implement them here.
23 *
24 * References:
25 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
26 * (available online, look for a PDF copy as the HTML versions tend to have
27 * translation errors.)
28 *
29 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 *
31 * MSDN, especially:
32 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
33 */
34
35 #include "precomp.h"
36
37 /* This is a bit arbitrary, but to set some limit: */
38 #define MAX_ENCODED_LEN 0x02000000
39
40 /* a few asn.1 tags we need */
41 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
42 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
43 #define ASN_OCTETSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x04)
44 #define ASN_ENUMERATED (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0a)
45 #define ASN_SETOF (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x11)
46 #define ASN_NUMERICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x12)
47 #define ASN_PRINTABLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x13)
48 #define ASN_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16)
49 #define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17)
50 #define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18)
51
52 #define ASN_FLAGS_MASK 0xf0
53 #define ASN_TYPE_MASK 0x0f
54
55 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
56
57 static const WCHAR szDllName[] = { 'D','l','l',0 };
58
59 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
60 BYTE *, DWORD *);
61 typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *,
62 DWORD, PCRYPT_ENCODE_PARA, BYTE *, DWORD *);
63 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
64 DWORD, DWORD, void *, DWORD *);
65 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
66 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
67
68 /* Prototypes for built-in encoders/decoders. They follow the Ex style
69 * prototypes. The dwCertEncodingType and lpszStructType are ignored by the
70 * built-in functions, but the parameters are retained to simplify
71 * CryptEncodeObjectEx/CryptDecodeObjectEx, since they must call functions in
72 * external DLLs that follow these signatures.
73 * FIXME: some built-in functions are suitable to be called directly by
74 * CryptEncodeObjectEx/CryptDecodeObjectEx (they implement exception handling
75 * and memory allocation if requested), others are only suitable to be called
76 * internally. Comment which are which.
77 */
78 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
80 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
81 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
82 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
83 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
84 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
86 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
87 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
88 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
89 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
90 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
93 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
94 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
95 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
96 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
97 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
98 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
99 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
100 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
101 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
102 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
103 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
104 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
105 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
106 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
107 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
108 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
109 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
110 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
111
112 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
113 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
114 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
115 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
116 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
117 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
118 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
119 * time, doesn't do memory allocation, and doesn't do exception handling.
120 * (This isn't intended to be the externally-called one.)
121 */
122 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
123 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
124 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
125 static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded,
126 DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId);
127 /* Assumes algo->Parameters.pbData is set ahead of time */
128 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
129 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
130 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
131 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
132 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
133 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
134 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
135 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
136 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
137 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
138 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
139 * member has been initialized, doesn't do exception handling, and doesn't do
140 * memory allocation.
141 */
142 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
143 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
144 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
145 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
146 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
147 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
148 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
149 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
150 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
151 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
152 * member has been initialized, doesn't do exception handling, and doesn't do
153 * memory allocation.
154 */
155 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
156 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
157 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
158 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
159 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
160 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
161 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
162 void *pvStructInfo, DWORD *pcbStructInfo);
163
164 /* filter for page-fault exceptions */
165 static WINE_EXCEPTION_FILTER(page_fault)
166 {
167 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
168 return EXCEPTION_EXECUTE_HANDLER;
169 return EXCEPTION_CONTINUE_SEARCH;
170 }
171
172 static char *CRYPT_GetKeyName(DWORD dwEncodingType, LPCSTR pszFuncName,
173 LPCSTR pszOID)
174 {
175 static const char szEncodingTypeFmt[] =
176 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
177 UINT len;
178 char numericOID[7]; /* enough for "#65535" */
179 const char *oid;
180 LPSTR szKey;
181
182 /* MSDN says the encoding type is a mask, but it isn't treated that way.
183 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
184 * "EncodingType 2" would be expected if it were a mask. Instead native
185 * stores values in "EncodingType 3".
186 */
187 if (!HIWORD(pszOID))
188 {
189 snprintf(numericOID, sizeof(numericOID), "#%d", LOWORD(pszOID));
190 oid = numericOID;
191 }
192 else
193 oid = pszOID;
194
195 /* This is enough: the lengths of the two string parameters are explicitly
196 * counted, and we need up to five additional characters for the encoding
197 * type. These are covered by the "%d", "%s", and "%s" characters in the
198 * format specifier that are removed by sprintf.
199 */
200 len = sizeof(szEncodingTypeFmt) + lstrlenA(pszFuncName) + lstrlenA(oid);
201 szKey = CryptMemAlloc(len);
202 if (szKey)
203 sprintf(szKey, szEncodingTypeFmt, dwEncodingType, pszFuncName, oid);
204 return szKey;
205 }
206
207 BOOL WINAPI CryptRegisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
208 LPCSTR pszOID, LPCWSTR pwszDll, LPCSTR pszOverrideFuncName)
209 {
210 LONG r;
211 HKEY hKey;
212 LPSTR szKey;
213
214 TRACE("%lx %s %s %s %s\n", dwEncodingType, pszFuncName, pszOID,
215 debugstr_w(pwszDll), pszOverrideFuncName);
216
217 /* This only registers functions for encoding certs, not messages */
218 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
219 return TRUE;
220
221 /* Native does nothing pwszDll is NULL */
222 if (!pwszDll)
223 return TRUE;
224
225 /* I'm not matching MS bug for bug here, because I doubt any app depends on
226 * it:
227 * - native "succeeds" if pszFuncName is NULL, but the nonsensical entry
228 * it creates would never be used
229 * - native returns an HRESULT rather than a Win32 error if pszOID is NULL.
230 * Instead I disallow both of these with ERROR_INVALID_PARAMETER.
231 */
232 if (!pszFuncName || !pszOID)
233 {
234 SetLastError(ERROR_INVALID_PARAMETER);
235 return FALSE;
236 }
237
238 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
239 TRACE("Key name is %s\n", debugstr_a(szKey));
240
241 if (!szKey)
242 return FALSE;
243
244 r = RegCreateKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
245 CryptMemFree(szKey);
246 if(r != ERROR_SUCCESS)
247 return FALSE;
248
249 /* write the values */
250 if (pszOverrideFuncName)
251 RegSetValueExA(hKey, "FuncName", 0, REG_SZ, (const BYTE*)pszOverrideFuncName,
252 lstrlenA(pszOverrideFuncName) + 1);
253 RegSetValueExW(hKey, szDllName, 0, REG_SZ, (const BYTE*) pwszDll,
254 (lstrlenW(pwszDll) + 1) * sizeof (WCHAR));
255
256 RegCloseKey(hKey);
257 return TRUE;
258 }
259
260 BOOL WINAPI CryptUnregisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
261 LPCSTR pszOID)
262 {
263 LPSTR szKey;
264 LONG rc;
265
266 TRACE("%lx %s %s\n", dwEncodingType, pszFuncName, pszOID);
267
268 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
269 return TRUE;
270
271 if (!pszFuncName || !pszOID)
272 {
273 SetLastError(ERROR_INVALID_PARAMETER);
274 return FALSE;
275 }
276
277 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
278 rc = RegDeleteKeyA(HKEY_LOCAL_MACHINE, szKey);
279 CryptMemFree(szKey);
280 if (rc)
281 SetLastError(rc);
282 return rc ? FALSE : TRUE;
283 }
284
285 BOOL WINAPI CryptGetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
286 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD *pdwValueType, BYTE *pbValueData,
287 DWORD *pcbValueData)
288 {
289 LPSTR szKey;
290 LONG rc;
291 HKEY hKey;
292
293 TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType, debugstr_a(pszFuncName),
294 debugstr_a(pszOID), debugstr_w(pwszValueName), pdwValueType, pbValueData,
295 pcbValueData);
296
297 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
298 return TRUE;
299
300 if (!pszFuncName || !pszOID || !pwszValueName)
301 {
302 SetLastError(ERROR_INVALID_PARAMETER);
303 return FALSE;
304 }
305
306 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
307 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
308 CryptMemFree(szKey);
309 if (rc)
310 SetLastError(rc);
311 else
312 {
313 rc = RegQueryValueExW(hKey, pwszValueName, NULL, pdwValueType,
314 pbValueData, pcbValueData);
315 if (rc)
316 SetLastError(rc);
317 RegCloseKey(hKey);
318 }
319 return rc ? FALSE : TRUE;
320 }
321
322 BOOL WINAPI CryptSetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
323 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD dwValueType,
324 const BYTE *pbValueData, DWORD cbValueData)
325 {
326 LPSTR szKey;
327 LONG rc;
328 HKEY hKey;
329
330 TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType, debugstr_a(pszFuncName),
331 debugstr_a(pszOID), debugstr_w(pwszValueName), dwValueType, pbValueData,
332 cbValueData);
333
334 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
335 return TRUE;
336
337 if (!pszFuncName || !pszOID || !pwszValueName)
338 {
339 SetLastError(ERROR_INVALID_PARAMETER);
340 return FALSE;
341 }
342
343 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
344 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
345 CryptMemFree(szKey);
346 if (rc)
347 SetLastError(rc);
348 else
349 {
350 rc = RegSetValueExW(hKey, pwszValueName, 0, dwValueType, pbValueData,
351 cbValueData);
352 if (rc)
353 SetLastError(rc);
354 RegCloseKey(hKey);
355 }
356 return rc ? FALSE : TRUE;
357 }
358
359 /* Gets the registered function named szFuncName for dwCertEncodingType and
360 * lpszStructType, or NULL if one could not be found. *lib will be set to the
361 * handle of the module it's in, or NULL if no module was loaded. If the
362 * return value is NULL, *lib will also be NULL, to simplify error handling.
363 */
364 static void *CRYPT_GetFunc(DWORD dwCertEncodingType, LPCSTR lpszStructType,
365 LPCSTR szFuncName, HMODULE *lib)
366 {
367 void *ret = NULL;
368 char *szKey = CRYPT_GetKeyName(dwCertEncodingType, szFuncName,
369 lpszStructType);
370 const char *funcName;
371 long r;
372 HKEY hKey;
373 DWORD type, size = 0;
374
375 TRACE("(%08lx %s %s %p)\n", dwCertEncodingType, debugstr_a(lpszStructType),
376 debugstr_a(szFuncName), lib);
377
378 *lib = NULL;
379 r = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
380 CryptMemFree(szKey);
381 if(r != ERROR_SUCCESS)
382 return NULL;
383
384 RegQueryValueExA(hKey, "FuncName", NULL, &type, NULL, &size);
385 if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ)
386 {
387 funcName = CryptMemAlloc(size);
388 RegQueryValueExA(hKey, "FuncName", NULL, &type, (LPBYTE)funcName,
389 &size);
390 }
391 else
392 funcName = szFuncName;
393 RegQueryValueExW(hKey, szDllName, NULL, &type, NULL, &size);
394 if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ)
395 {
396 LPWSTR dllName = CryptMemAlloc(size);
397
398 RegQueryValueExW(hKey, szDllName, NULL, &type, (LPBYTE)dllName,
399 &size);
400 *lib = LoadLibraryW(dllName);
401 if (*lib)
402 {
403 ret = GetProcAddress(*lib, funcName);
404 if (!ret)
405 {
406 /* Unload the library, the caller doesn't want to unload it
407 * when the return value is NULL.
408 */
409 FreeLibrary(*lib);
410 *lib = NULL;
411 }
412 }
413 CryptMemFree(dllName);
414 }
415 if (funcName != szFuncName)
416 CryptMemFree((char *)funcName);
417 TRACE("returning %p\n", ret);
418 return ret;
419 }
420
421 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
422 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
423 {
424 BOOL ret = FALSE;
425 HMODULE lib;
426 CryptEncodeObjectFunc pCryptEncodeObject;
427
428 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType,
429 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
430 pcbEncoded);
431
432 if (!pbEncoded && !pcbEncoded)
433 {
434 SetLastError(ERROR_INVALID_PARAMETER);
435 return FALSE;
436 }
437
438 /* Try registered DLL first.. */
439 pCryptEncodeObject =
440 (CryptEncodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType,
441 lpszStructType, CRYPT_OID_ENCODE_OBJECT_FUNC, &lib);
442 if (pCryptEncodeObject)
443 {
444 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
445 pvStructInfo, pbEncoded, pcbEncoded);
446 FreeLibrary(lib);
447 }
448 else
449 {
450 /* If not, use CryptEncodeObjectEx */
451 ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
452 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
453 }
454 return ret;
455 }
456
457 /* Helper function to check *pcbEncoded, set it to the required size, and
458 * optionally to allocate memory. Assumes pbEncoded is not NULL.
459 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
460 * pointer to the newly allocated memory.
461 */
462 static BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags,
463 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded,
464 DWORD bytesNeeded)
465 {
466 BOOL ret = TRUE;
467
468 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
469 {
470 if (pEncodePara && pEncodePara->pfnAlloc)
471 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
472 else
473 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
474 if (!*(BYTE **)pbEncoded)
475 ret = FALSE;
476 else
477 *pcbEncoded = bytesNeeded;
478 }
479 else if (bytesNeeded > *pcbEncoded)
480 {
481 *pcbEncoded = bytesNeeded;
482 SetLastError(ERROR_MORE_DATA);
483 ret = FALSE;
484 }
485 return ret;
486 }
487
488 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
489 {
490 DWORD bytesNeeded, significantBytes = 0;
491
492 if (len <= 0x7f)
493 bytesNeeded = 1;
494 else
495 {
496 DWORD temp;
497
498 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
499 temp <<= 8, significantBytes--)
500 ;
501 bytesNeeded = significantBytes + 1;
502 }
503 if (!pbEncoded)
504 {
505 *pcbEncoded = bytesNeeded;
506 return TRUE;
507 }
508 if (*pcbEncoded < bytesNeeded)
509 {
510 SetLastError(ERROR_MORE_DATA);
511 return FALSE;
512 }
513 if (len <= 0x7f)
514 *pbEncoded = (BYTE)len;
515 else
516 {
517 DWORD i;
518
519 *pbEncoded++ = significantBytes | 0x80;
520 for (i = 0; i < significantBytes; i++)
521 {
522 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
523 len >>= 8;
524 }
525 }
526 *pcbEncoded = bytesNeeded;
527 return TRUE;
528 }
529
530 struct AsnEncodeSequenceItem
531 {
532 const void *pvStructInfo;
533 CryptEncodeObjectExFunc encodeFunc;
534 DWORD size; /* used during encoding, not for your use */
535 };
536
537 static BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
538 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
539 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
540 {
541 BOOL ret;
542 DWORD i, dataLen = 0;
543
544 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items, cItem, dwFlags, pEncodePara,
545 pbEncoded, *pcbEncoded);
546 for (i = 0, ret = TRUE; ret && i < cItem; i++)
547 {
548 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
549 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
550 NULL, &items[i].size);
551 dataLen += items[i].size;
552 }
553 if (ret)
554 {
555 DWORD lenBytes, bytesNeeded;
556
557 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
558 bytesNeeded = 1 + lenBytes + dataLen;
559 if (!pbEncoded)
560 *pcbEncoded = bytesNeeded;
561 else
562 {
563 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
564 pcbEncoded, bytesNeeded)))
565 {
566 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
567 pbEncoded = *(BYTE **)pbEncoded;
568 *pbEncoded++ = ASN_SEQUENCE;
569 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
570 pbEncoded += lenBytes;
571 for (i = 0; ret && i < cItem; i++)
572 {
573 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
574 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
575 NULL, pbEncoded, &items[i].size);
576 pbEncoded += items[i].size;
577 }
578 }
579 }
580 }
581 TRACE("returning %d (%08lx)\n", ret, GetLastError());
582 return ret;
583 }
584
585 struct AsnConstructedItem
586 {
587 BYTE tag;
588 const void *pvStructInfo;
589 CryptEncodeObjectExFunc encodeFunc;
590 };
591
592 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
593 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
594 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
595 {
596 BOOL ret;
597 const struct AsnConstructedItem *item =
598 (const struct AsnConstructedItem *)pvStructInfo;
599 DWORD len;
600
601 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
602 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
603 {
604 DWORD dataLen, bytesNeeded;
605
606 CRYPT_EncodeLen(len, NULL, &dataLen);
607 bytesNeeded = 1 + dataLen + len;
608 if (!pbEncoded)
609 *pcbEncoded = bytesNeeded;
610 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
611 pbEncoded, pcbEncoded, bytesNeeded)))
612 {
613 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
614 pbEncoded = *(BYTE **)pbEncoded;
615 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
616 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
617 pbEncoded += dataLen;
618 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
619 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
620 pbEncoded, &len);
621 }
622 }
623 return ret;
624 }
625
626 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
627 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
628 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
629 {
630 const DWORD *ver = (const DWORD *)pvStructInfo;
631 BOOL ret;
632
633 /* CERT_V1 is not encoded */
634 if (*ver == CERT_V1)
635 {
636 *pcbEncoded = 0;
637 ret = TRUE;
638 }
639 else
640 {
641 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
642
643 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
644 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
645 }
646 return ret;
647 }
648
649 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
650 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
651 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
652 {
653 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
654 BOOL ret;
655
656 if (!pbEncoded)
657 {
658 *pcbEncoded = blob->cbData;
659 ret = TRUE;
660 }
661 else if (*pcbEncoded < blob->cbData)
662 {
663 *pcbEncoded = blob->cbData;
664 SetLastError(ERROR_MORE_DATA);
665 ret = FALSE;
666 }
667 else
668 {
669 if (blob->cbData)
670 memcpy(pbEncoded, blob->pbData, blob->cbData);
671 *pcbEncoded = blob->cbData;
672 ret = TRUE;
673 }
674 return ret;
675 }
676
677 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
678 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
679 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
680 {
681 BOOL ret;
682 /* This has two filetimes in a row, a NotBefore and a NotAfter */
683 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
684 struct AsnEncodeSequenceItem items[] = {
685 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
686 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
687 };
688
689 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
690 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
691 pcbEncoded);
692 return ret;
693 }
694
695 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(
696 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
697 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
698 DWORD *pcbEncoded)
699 {
700 const CRYPT_ALGORITHM_IDENTIFIER *algo =
701 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
702 BOOL ret;
703 struct AsnEncodeSequenceItem items[] = {
704 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
705 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
706 };
707
708 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
709 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
710 pcbEncoded);
711 return ret;
712 }
713
714 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
715 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
716 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
717 {
718 BOOL ret;
719
720 _SEH_TRY
721 {
722 const CERT_PUBLIC_KEY_INFO *info =
723 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
724 struct AsnEncodeSequenceItem items[] = {
725 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
726 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
727 };
728
729 TRACE("Encoding public key with OID %s\n",
730 debugstr_a(info->Algorithm.pszObjId));
731 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
732 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
733 pcbEncoded);
734 }
735 _SEH_EXCEPT(page_fault)
736 {
737 SetLastError(STATUS_ACCESS_VIOLATION);
738 ret = FALSE;
739 }
740 _SEH_END
741 return ret;
742 }
743
744 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
745 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
746 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
747 {
748 BOOL ret;
749
750 _SEH_TRY
751 {
752 const CERT_SIGNED_CONTENT_INFO *info =
753 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
754 struct AsnEncodeSequenceItem items[] = {
755 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
756 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
757 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
758 };
759
760 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
761 items[2].encodeFunc = CRYPT_AsnEncodeBits;
762 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
763 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
764 pcbEncoded);
765 }
766 _SEH_EXCEPT(page_fault)
767 {
768 SetLastError(STATUS_ACCESS_VIOLATION);
769 ret = FALSE;
770 }
771 _SEH_END
772 return ret;
773 }
774
775 /* Like in Windows, this blithely ignores the validity of the passed-in
776 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
777 * decode properly, see CRYPT_AsnDecodeCertInfo.
778 */
779 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
780 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
781 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
782 {
783 BOOL ret;
784
785 _SEH_TRY
786 {
787 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
788 struct AsnEncodeSequenceItem items[10] = {
789 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
790 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
791 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
792 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
793 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
794 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
795 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
796 { 0 }
797 };
798 struct AsnConstructedItem constructed[3] = { { 0 } };
799 DWORD cItem = 7, cConstructed = 0;
800
801 if (info->IssuerUniqueId.cbData)
802 {
803 constructed[cConstructed].tag = 1;
804 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
805 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
806 items[cItem].pvStructInfo = &constructed[cConstructed];
807 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
808 cConstructed++;
809 cItem++;
810 }
811 if (info->SubjectUniqueId.cbData)
812 {
813 constructed[cConstructed].tag = 2;
814 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
815 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
816 items[cItem].pvStructInfo = &constructed[cConstructed];
817 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
818 cConstructed++;
819 cItem++;
820 }
821 if (info->cExtension)
822 {
823 constructed[cConstructed].tag = 3;
824 constructed[cConstructed].pvStructInfo = &info->cExtension;
825 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
826 items[cItem].pvStructInfo = &constructed[cConstructed];
827 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
828 cConstructed++;
829 cItem++;
830 }
831
832 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
833 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
834 }
835 _SEH_EXCEPT(page_fault)
836 {
837 SetLastError(STATUS_ACCESS_VIOLATION);
838 ret = FALSE;
839 }
840 _SEH_END
841 return ret;
842 }
843
844 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
845 BYTE *pbEncoded, DWORD *pcbEncoded)
846 {
847 struct AsnEncodeSequenceItem items[3] = {
848 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
849 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
850 { 0 }
851 };
852 DWORD cItem = 2;
853 BOOL ret;
854
855 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
856
857 if (entry->cExtension)
858 {
859 items[cItem].pvStructInfo = &entry->cExtension;
860 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
861 cItem++;
862 }
863
864 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
865 pbEncoded, pcbEncoded);
866
867 TRACE("returning %d (%08lx)\n", ret, GetLastError());
868 return ret;
869 }
870
871 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
872 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
873 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
874 {
875 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
876 DWORD bytesNeeded, dataLen, lenBytes, i;
877 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY **)
878 ((const BYTE *)pvStructInfo + sizeof(DWORD));
879 BOOL ret = TRUE;
880
881 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
882 {
883 DWORD size;
884
885 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
886 if (ret)
887 dataLen += size;
888 }
889 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
890 bytesNeeded = 1 + lenBytes + dataLen;
891 if (!pbEncoded)
892 *pcbEncoded = bytesNeeded;
893 else
894 {
895 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
896 pcbEncoded, bytesNeeded)))
897 {
898 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
899 pbEncoded = *(BYTE **)pbEncoded;
900 *pbEncoded++ = ASN_SEQUENCEOF;
901 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
902 pbEncoded += lenBytes;
903 for (i = 0; i < cCRLEntry; i++)
904 {
905 DWORD size = dataLen;
906
907 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
908 pbEncoded += size;
909 dataLen -= size;
910 }
911 }
912 }
913 return ret;
914 }
915
916 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
917 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
918 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
919 {
920 const DWORD *ver = (const DWORD *)pvStructInfo;
921 BOOL ret;
922
923 /* CRL_V1 is not encoded */
924 if (*ver == CRL_V1)
925 {
926 *pcbEncoded = 0;
927 ret = TRUE;
928 }
929 else
930 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
931 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
932 return ret;
933 }
934
935 /* Like in Windows, this blithely ignores the validity of the passed-in
936 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
937 * decode properly, see CRYPT_AsnDecodeCRLInfo.
938 */
939 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
940 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
941 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
942 {
943 BOOL ret;
944
945 _SEH_TRY
946 {
947 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
948 struct AsnEncodeSequenceItem items[7] = {
949 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
950 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
951 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
952 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
953 { 0 }
954 };
955 DWORD cItem = 4;
956
957 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
958 {
959 items[cItem].pvStructInfo = &info->NextUpdate;
960 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
961 cItem++;
962 }
963 if (info->cCRLEntry)
964 {
965 items[cItem].pvStructInfo = &info->cCRLEntry;
966 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
967 cItem++;
968 }
969 if (info->cExtension)
970 {
971 items[cItem].pvStructInfo = &info->cExtension;
972 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
973 cItem++;
974 }
975
976 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
977 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
978 }
979 _SEH_EXCEPT(page_fault)
980 {
981 SetLastError(STATUS_ACCESS_VIOLATION);
982 ret = FALSE;
983 }
984 _SEH_END
985 return ret;
986 }
987
988 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
989 DWORD *pcbEncoded)
990 {
991 BOOL ret;
992 struct AsnEncodeSequenceItem items[3] = {
993 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
994 { NULL, NULL, 0 },
995 { NULL, NULL, 0 },
996 };
997 DWORD cItem = 1;
998
999 TRACE("%p, %p, %ld\n", ext, pbEncoded, *pcbEncoded);
1000
1001 if (ext->fCritical)
1002 {
1003 items[cItem].pvStructInfo = &ext->fCritical;
1004 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
1005 cItem++;
1006 }
1007 items[cItem].pvStructInfo = &ext->Value;
1008 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1009 cItem++;
1010
1011 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
1012 pbEncoded, pcbEncoded);
1013 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1014 return ret;
1015 }
1016
1017 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
1018 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1019 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1020 {
1021 BOOL ret;
1022
1023 _SEH_TRY
1024 {
1025 DWORD bytesNeeded, dataLen, lenBytes, i;
1026 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
1027
1028 ret = TRUE;
1029 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
1030 {
1031 DWORD size;
1032
1033 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
1034 if (ret)
1035 dataLen += size;
1036 }
1037 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1038 bytesNeeded = 1 + lenBytes + dataLen;
1039 if (!pbEncoded)
1040 *pcbEncoded = bytesNeeded;
1041 else
1042 {
1043 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1044 pcbEncoded, bytesNeeded)))
1045 {
1046 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1047 pbEncoded = *(BYTE **)pbEncoded;
1048 *pbEncoded++ = ASN_SEQUENCEOF;
1049 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1050 pbEncoded += lenBytes;
1051 for (i = 0; i < exts->cExtension; i++)
1052 {
1053 DWORD size = dataLen;
1054
1055 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
1056 pbEncoded, &size);
1057 pbEncoded += size;
1058 dataLen -= size;
1059 }
1060 }
1061 }
1062 }
1063 _SEH_EXCEPT(page_fault)
1064 {
1065 SetLastError(STATUS_ACCESS_VIOLATION);
1066 ret = FALSE;
1067 }
1068 _SEH_END
1069 return ret;
1070 }
1071
1072 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
1073 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1074 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1075 {
1076 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
1077 DWORD bytesNeeded = 0, lenBytes;
1078 BOOL ret = TRUE;
1079 int firstPos = 0;
1080 BYTE firstByte = 0;
1081
1082 TRACE("%s\n", debugstr_a(pszObjId));
1083
1084 if (pszObjId)
1085 {
1086 const char *ptr;
1087 int val1, val2;
1088
1089 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
1090 {
1091 SetLastError(CRYPT_E_ASN1_ERROR);
1092 return FALSE;
1093 }
1094 bytesNeeded++;
1095 firstByte = val1 * 40 + val2;
1096 ptr = pszObjId + firstPos;
1097 while (ret && *ptr)
1098 {
1099 int pos;
1100
1101 /* note I assume each component is at most 32-bits long in base 2 */
1102 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
1103 {
1104 if (val1 >= 0x10000000)
1105 bytesNeeded += 5;
1106 else if (val1 >= 0x200000)
1107 bytesNeeded += 4;
1108 else if (val1 >= 0x4000)
1109 bytesNeeded += 3;
1110 else if (val1 >= 0x80)
1111 bytesNeeded += 2;
1112 else
1113 bytesNeeded += 1;
1114 ptr += pos;
1115 if (*ptr == '.')
1116 ptr++;
1117 }
1118 else
1119 {
1120 SetLastError(CRYPT_E_ASN1_ERROR);
1121 return FALSE;
1122 }
1123 }
1124 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1125 }
1126 else
1127 lenBytes = 1;
1128 bytesNeeded += 1 + lenBytes;
1129 if (pbEncoded)
1130 {
1131 if (*pcbEncoded < bytesNeeded)
1132 {
1133 SetLastError(ERROR_MORE_DATA);
1134 ret = FALSE;
1135 }
1136 else
1137 {
1138 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
1139 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
1140 pbEncoded += lenBytes;
1141 if (pszObjId)
1142 {
1143 const char *ptr;
1144 int val, pos;
1145
1146 *pbEncoded++ = firstByte;
1147 ptr = pszObjId + firstPos;
1148 while (ret && *ptr)
1149 {
1150 sscanf(ptr, "%d%n", &val, &pos);
1151 {
1152 unsigned char outBytes[5];
1153 int numBytes, i;
1154
1155 if (val >= 0x10000000)
1156 numBytes = 5;
1157 else if (val >= 0x200000)
1158 numBytes = 4;
1159 else if (val >= 0x4000)
1160 numBytes = 3;
1161 else if (val >= 0x80)
1162 numBytes = 2;
1163 else
1164 numBytes = 1;
1165 for (i = numBytes; i > 0; i--)
1166 {
1167 outBytes[i - 1] = val & 0x7f;
1168 val >>= 7;
1169 }
1170 for (i = 0; i < numBytes - 1; i++)
1171 *pbEncoded++ = outBytes[i] | 0x80;
1172 *pbEncoded++ = outBytes[i];
1173 ptr += pos;
1174 if (*ptr == '.')
1175 ptr++;
1176 }
1177 }
1178 }
1179 }
1180 }
1181 *pcbEncoded = bytesNeeded;
1182 return ret;
1183 }
1184
1185 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1186 CERT_NAME_VALUE *value, BYTE *pbEncoded, DWORD *pcbEncoded)
1187 {
1188 BYTE tag;
1189 DWORD bytesNeeded, lenBytes, encodedLen;
1190 BOOL ret = TRUE;
1191
1192 switch (value->dwValueType)
1193 {
1194 case CERT_RDN_NUMERIC_STRING:
1195 tag = ASN_NUMERICSTRING;
1196 encodedLen = value->Value.cbData;
1197 break;
1198 case CERT_RDN_PRINTABLE_STRING:
1199 tag = ASN_PRINTABLESTRING;
1200 encodedLen = value->Value.cbData;
1201 break;
1202 case CERT_RDN_IA5_STRING:
1203 tag = ASN_IA5STRING;
1204 encodedLen = value->Value.cbData;
1205 break;
1206 case CERT_RDN_ANY_TYPE:
1207 /* explicitly disallowed */
1208 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1209 return FALSE;
1210 default:
1211 FIXME("String type %ld unimplemented\n", value->dwValueType);
1212 return FALSE;
1213 }
1214 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1215 bytesNeeded = 1 + lenBytes + encodedLen;
1216 if (pbEncoded)
1217 {
1218 if (*pcbEncoded < bytesNeeded)
1219 {
1220 SetLastError(ERROR_MORE_DATA);
1221 ret = FALSE;
1222 }
1223 else
1224 {
1225 *pbEncoded++ = tag;
1226 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1227 pbEncoded += lenBytes;
1228 switch (value->dwValueType)
1229 {
1230 case CERT_RDN_NUMERIC_STRING:
1231 case CERT_RDN_PRINTABLE_STRING:
1232 case CERT_RDN_IA5_STRING:
1233 memcpy(pbEncoded, value->Value.pbData, value->Value.cbData);
1234 }
1235 }
1236 }
1237 *pcbEncoded = bytesNeeded;
1238 return ret;
1239 }
1240
1241 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1242 CERT_RDN_ATTR *attr, BYTE *pbEncoded, DWORD *pcbEncoded)
1243 {
1244 DWORD bytesNeeded = 0, lenBytes, size;
1245 BOOL ret;
1246
1247 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1248 0, NULL, NULL, &size);
1249 if (ret)
1250 {
1251 bytesNeeded += size;
1252 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1253 * with dwValueType, so "cast" it to get its encoded size
1254 */
1255 ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType,
1256 (CERT_NAME_VALUE *)&attr->dwValueType, NULL, &size);
1257 if (ret)
1258 {
1259 bytesNeeded += size;
1260 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1261 bytesNeeded += 1 + lenBytes;
1262 if (pbEncoded)
1263 {
1264 if (*pcbEncoded < bytesNeeded)
1265 {
1266 SetLastError(ERROR_MORE_DATA);
1267 ret = FALSE;
1268 }
1269 else
1270 {
1271 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SEQUENCE;
1272 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1273 &lenBytes);
1274 pbEncoded += lenBytes;
1275 size = bytesNeeded - 1 - lenBytes;
1276 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1277 attr->pszObjId, 0, NULL, pbEncoded, &size);
1278 if (ret)
1279 {
1280 pbEncoded += size;
1281 size = bytesNeeded - 1 - lenBytes - size;
1282 ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType,
1283 (CERT_NAME_VALUE *)&attr->dwValueType, pbEncoded,
1284 &size);
1285 }
1286 }
1287 }
1288 *pcbEncoded = bytesNeeded;
1289 }
1290 }
1291 return ret;
1292 }
1293
1294 static int BLOBComp(const void *l, const void *r)
1295 {
1296 CRYPT_DER_BLOB *a = (CRYPT_DER_BLOB *)l, *b = (CRYPT_DER_BLOB *)r;
1297 int ret;
1298
1299 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1300 ret = a->cbData - b->cbData;
1301 return ret;
1302 }
1303
1304 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1305 */
1306 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1307 BYTE *pbEncoded, DWORD *pcbEncoded)
1308 {
1309 BOOL ret;
1310 CRYPT_DER_BLOB *blobs = NULL;
1311
1312 _SEH_TRY
1313 {
1314 DWORD bytesNeeded = 0, lenBytes, i;
1315
1316 blobs = NULL;
1317 ret = TRUE;
1318 if (rdn->cRDNAttr)
1319 {
1320 blobs = CryptMemAlloc(rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
1321 if (!blobs)
1322 ret = FALSE;
1323 else
1324 memset(blobs, 0, rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
1325 }
1326 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1327 {
1328 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1329 NULL, &blobs[i].cbData);
1330 if (ret)
1331 bytesNeeded += blobs[i].cbData;
1332 }
1333 if (ret)
1334 {
1335 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1336 bytesNeeded += 1 + lenBytes;
1337 if (pbEncoded)
1338 {
1339 if (*pcbEncoded < bytesNeeded)
1340 {
1341 SetLastError(ERROR_MORE_DATA);
1342 ret = FALSE;
1343 }
1344 else
1345 {
1346 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1347 {
1348 blobs[i].pbData = CryptMemAlloc(blobs[i].cbData);
1349 if (!blobs[i].pbData)
1350 ret = FALSE;
1351 else
1352 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1353 &rdn->rgRDNAttr[i], blobs[i].pbData,
1354 &blobs[i].cbData);
1355 }
1356 if (ret)
1357 {
1358 qsort(blobs, rdn->cRDNAttr, sizeof(CRYPT_DER_BLOB),
1359 BLOBComp);
1360 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1361 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1362 &lenBytes);
1363 pbEncoded += lenBytes;
1364 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1365 {
1366 memcpy(pbEncoded, blobs[i].pbData, blobs[i].cbData);
1367 pbEncoded += blobs[i].cbData;
1368 }
1369 }
1370 }
1371 }
1372 *pcbEncoded = bytesNeeded;
1373 }
1374 if (blobs)
1375 {
1376 for (i = 0; i < rdn->cRDNAttr; i++)
1377 CryptMemFree(blobs[i].pbData);
1378 }
1379 }
1380 _SEH_EXCEPT(page_fault)
1381 {
1382 SetLastError(STATUS_ACCESS_VIOLATION);
1383 return FALSE;
1384 }
1385 _SEH_END
1386 CryptMemFree(blobs);
1387 return ret;
1388 }
1389
1390 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1391 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1392 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1393 {
1394 BOOL ret;
1395
1396 _SEH_TRY
1397 {
1398 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1399 DWORD bytesNeeded = 0, lenBytes, size, i;
1400
1401 TRACE("encoding name with %ld RDNs\n", info->cRDN);
1402 ret = TRUE;
1403 for (i = 0; ret && i < info->cRDN; i++)
1404 {
1405 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], NULL,
1406 &size);
1407 if (ret)
1408 bytesNeeded += size;
1409 }
1410 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1411 bytesNeeded += 1 + lenBytes;
1412 if (ret)
1413 {
1414 if (!pbEncoded)
1415 *pcbEncoded = bytesNeeded;
1416 else
1417 {
1418 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1419 pbEncoded, pcbEncoded, bytesNeeded)))
1420 {
1421 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1422 pbEncoded = *(BYTE **)pbEncoded;
1423 *pbEncoded++ = ASN_SEQUENCEOF;
1424 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1425 &lenBytes);
1426 pbEncoded += lenBytes;
1427 for (i = 0; ret && i < info->cRDN; i++)
1428 {
1429 size = bytesNeeded;
1430 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1431 &info->rgRDN[i], pbEncoded, &size);
1432 if (ret)
1433 {
1434 pbEncoded += size;
1435 bytesNeeded -= size;
1436 }
1437 }
1438 }
1439 }
1440 }
1441 }
1442 _SEH_EXCEPT(page_fault)
1443 {
1444 SetLastError(STATUS_ACCESS_VIOLATION);
1445 ret = FALSE;
1446 }
1447 _SEH_END
1448 return ret;
1449 }
1450
1451 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1452 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1453 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1454 {
1455 BOOL val = *(const BOOL *)pvStructInfo, ret;
1456
1457 TRACE("%d\n", val);
1458
1459 if (!pbEncoded)
1460 {
1461 *pcbEncoded = 3;
1462 ret = TRUE;
1463 }
1464 else if (*pcbEncoded < 3)
1465 {
1466 *pcbEncoded = 3;
1467 SetLastError(ERROR_MORE_DATA);
1468 ret = FALSE;
1469 }
1470 else
1471 {
1472 *pcbEncoded = 3;
1473 *pbEncoded++ = ASN_BOOL;
1474 *pbEncoded++ = 1;
1475 *pbEncoded++ = val ? 0xff : 0;
1476 ret = TRUE;
1477 }
1478 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1479 return ret;
1480 }
1481
1482 static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry,
1483 BYTE *pbEncoded, DWORD *pcbEncoded)
1484 {
1485 BOOL ret;
1486 DWORD dataLen;
1487
1488 ret = TRUE;
1489 switch (entry->dwAltNameChoice)
1490 {
1491 case CERT_ALT_NAME_RFC822_NAME:
1492 case CERT_ALT_NAME_DNS_NAME:
1493 case CERT_ALT_NAME_URL:
1494 if (entry->u.pwszURL)
1495 {
1496 DWORD i;
1497
1498 /* Not + 1: don't encode the NULL-terminator */
1499 dataLen = lstrlenW(entry->u.pwszURL);
1500 for (i = 0; ret && i < dataLen; i++)
1501 {
1502 if (entry->u.pwszURL[i] > 0x7f)
1503 {
1504 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1505 ret = FALSE;
1506 *pcbEncoded = i;
1507 }
1508 }
1509 }
1510 else
1511 dataLen = 0;
1512 break;
1513 case CERT_ALT_NAME_IP_ADDRESS:
1514 dataLen = entry->u.IPAddress.cbData;
1515 break;
1516 case CERT_ALT_NAME_REGISTERED_ID:
1517 /* FIXME: encode OID */
1518 case CERT_ALT_NAME_OTHER_NAME:
1519 case CERT_ALT_NAME_DIRECTORY_NAME:
1520 FIXME("name type %ld unimplemented\n", entry->dwAltNameChoice);
1521 return FALSE;
1522 default:
1523 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1524 return FALSE;
1525 }
1526 if (ret)
1527 {
1528 DWORD bytesNeeded, lenBytes;
1529
1530 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1531 bytesNeeded = 1 + dataLen + lenBytes;
1532 if (!pbEncoded)
1533 *pcbEncoded = bytesNeeded;
1534 else if (*pcbEncoded < bytesNeeded)
1535 {
1536 SetLastError(ERROR_MORE_DATA);
1537 *pcbEncoded = bytesNeeded;
1538 ret = FALSE;
1539 }
1540 else
1541 {
1542 *pbEncoded++ = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1543 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1544 pbEncoded += lenBytes;
1545 switch (entry->dwAltNameChoice)
1546 {
1547 case CERT_ALT_NAME_RFC822_NAME:
1548 case CERT_ALT_NAME_DNS_NAME:
1549 case CERT_ALT_NAME_URL:
1550 {
1551 DWORD i;
1552
1553 for (i = 0; i < dataLen; i++)
1554 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
1555 break;
1556 }
1557 case CERT_ALT_NAME_IP_ADDRESS:
1558 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
1559 break;
1560 }
1561 if (ret)
1562 *pcbEncoded = bytesNeeded;
1563 }
1564 }
1565 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1566 return ret;
1567 }
1568
1569 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
1570 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1571 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1572 {
1573 BOOL ret;
1574
1575 _SEH_TRY
1576 {
1577 const CERT_ALT_NAME_INFO *info =
1578 (const CERT_ALT_NAME_INFO *)pvStructInfo;
1579
1580 DWORD bytesNeeded, dataLen, lenBytes, i;
1581
1582 ret = TRUE;
1583 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1584 * can't encode an erroneous entry index if it's bigger than this.
1585 */
1586 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
1587 {
1588 DWORD len;
1589
1590 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], NULL,
1591 &len);
1592 if (ret)
1593 dataLen += len;
1594 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
1595 {
1596 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1597 * the bad character, now set the index of the bad
1598 * entry
1599 */
1600 *pcbEncoded = (BYTE)i <<
1601 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
1602 }
1603 }
1604 if (ret)
1605 {
1606 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1607 bytesNeeded = 1 + lenBytes + dataLen;
1608 if (!pbEncoded)
1609 {
1610 *pcbEncoded = bytesNeeded;
1611 ret = TRUE;
1612 }
1613 else
1614 {
1615 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1616 pbEncoded, pcbEncoded, bytesNeeded)))
1617 {
1618 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1619 pbEncoded = *(BYTE **)pbEncoded;
1620 *pbEncoded++ = ASN_SEQUENCEOF;
1621 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1622 pbEncoded += lenBytes;
1623 for (i = 0; ret && i < info->cAltEntry; i++)
1624 {
1625 DWORD len = dataLen;
1626
1627 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i],
1628 pbEncoded, &len);
1629 if (ret)
1630 {
1631 pbEncoded += len;
1632 dataLen -= len;
1633 }
1634 }
1635 }
1636 }
1637 }
1638 }
1639 _SEH_EXCEPT(page_fault)
1640 {
1641 SetLastError(STATUS_ACCESS_VIOLATION);
1642 ret = FALSE;
1643 }
1644 _SEH_END
1645 return ret;
1646 }
1647
1648 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
1649 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1650 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1651 {
1652 BOOL ret;
1653
1654 _SEH_TRY
1655 {
1656 const CERT_BASIC_CONSTRAINTS2_INFO *info =
1657 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
1658 struct AsnEncodeSequenceItem items[2] = { { 0 } };
1659 DWORD cItem = 0;
1660
1661 if (info->fCA)
1662 {
1663 items[cItem].pvStructInfo = &info->fCA;
1664 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
1665 cItem++;
1666 }
1667 if (info->fPathLenConstraint)
1668 {
1669 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
1670 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
1671 cItem++;
1672 }
1673 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1674 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1675 }
1676 _SEH_EXCEPT(page_fault)
1677 {
1678 SetLastError(STATUS_ACCESS_VIOLATION);
1679 ret = FALSE;
1680 }
1681 _SEH_END
1682 return ret;
1683 }
1684
1685 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
1686 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1687 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1688 {
1689 BOOL ret;
1690
1691 _SEH_TRY
1692 {
1693 const BLOBHEADER *hdr =
1694 (const BLOBHEADER *)pvStructInfo;
1695
1696 if (hdr->bType != PUBLICKEYBLOB)
1697 {
1698 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1699 ret = FALSE;
1700 }
1701 else
1702 {
1703 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
1704 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
1705 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
1706 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
1707 struct AsnEncodeSequenceItem items[] = {
1708 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
1709 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
1710 };
1711
1712 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1713 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1714 pcbEncoded);
1715 }
1716 }
1717 _SEH_EXCEPT(page_fault)
1718 {
1719 SetLastError(STATUS_ACCESS_VIOLATION);
1720 ret = FALSE;
1721 }
1722 _SEH_END
1723 return ret;
1724 }
1725
1726 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
1727 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1728 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1729 {
1730 BOOL ret;
1731
1732 _SEH_TRY
1733 {
1734 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
1735 DWORD bytesNeeded, lenBytes;
1736
1737 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob->cbData, blob->pbData,
1738 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
1739
1740 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
1741 bytesNeeded = 1 + lenBytes + blob->cbData;
1742 if (!pbEncoded)
1743 {
1744 *pcbEncoded = bytesNeeded;
1745 ret = TRUE;
1746 }
1747 else
1748 {
1749 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1750 pcbEncoded, bytesNeeded)))
1751 {
1752 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1753 pbEncoded = *(BYTE **)pbEncoded;
1754 *pbEncoded++ = ASN_OCTETSTRING;
1755 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
1756 pbEncoded += lenBytes;
1757 if (blob->cbData)
1758 memcpy(pbEncoded, blob->pbData, blob->cbData);
1759 }
1760 }
1761 }
1762 _SEH_EXCEPT(page_fault)
1763 {
1764 SetLastError(STATUS_ACCESS_VIOLATION);
1765 ret = FALSE;
1766 }
1767 _SEH_END
1768 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1769 return ret;
1770 }
1771
1772 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
1773 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1774 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1775 {
1776 BOOL ret;
1777
1778 _SEH_TRY
1779 {
1780 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
1781 DWORD bytesNeeded, lenBytes, dataBytes;
1782 BYTE unusedBits;
1783
1784 /* yep, MS allows cUnusedBits to be >= 8 */
1785 if (!blob->cUnusedBits)
1786 {
1787 dataBytes = blob->cbData;
1788 unusedBits = 0;
1789 }
1790 else if (blob->cbData * 8 > blob->cUnusedBits)
1791 {
1792 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
1793 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
1794 blob->cUnusedBits;
1795 }
1796 else
1797 {
1798 dataBytes = 0;
1799 unusedBits = 0;
1800 }
1801 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
1802 bytesNeeded = 1 + lenBytes + dataBytes + 1;
1803 if (!pbEncoded)
1804 {
1805 *pcbEncoded = bytesNeeded;
1806 ret = TRUE;
1807 }
1808 else
1809 {
1810 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1811 pcbEncoded, bytesNeeded)))
1812 {
1813 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1814 pbEncoded = *(BYTE **)pbEncoded;
1815 *pbEncoded++ = ASN_BITSTRING;
1816 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
1817 pbEncoded += lenBytes;
1818 *pbEncoded++ = unusedBits;
1819 if (dataBytes)
1820 {
1821 BYTE mask = 0xff << unusedBits;
1822
1823 if (dataBytes > 1)
1824 {
1825 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
1826 pbEncoded += dataBytes - 1;
1827 }
1828 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
1829 }
1830 }
1831 }
1832 }
1833 _SEH_EXCEPT(page_fault)
1834 {
1835 SetLastError(STATUS_ACCESS_VIOLATION);
1836 ret = FALSE;
1837 }
1838 _SEH_END
1839 return ret;
1840 }
1841
1842 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
1843 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1844 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1845 {
1846 BOOL ret;
1847
1848 _SEH_TRY
1849 {
1850 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
1851 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
1852
1853 ret = TRUE;
1854 if (newBlob.cbData)
1855 {
1856 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
1857 if (newBlob.pbData)
1858 {
1859 DWORD i;
1860
1861 for (i = 0; i < newBlob.cbData; i++)
1862 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
1863 }
1864 else
1865 ret = FALSE;
1866 }
1867 if (ret)
1868 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
1869 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1870 CryptMemFree(newBlob.pbData);
1871 }
1872 _SEH_EXCEPT(page_fault)
1873 {
1874 SetLastError(STATUS_ACCESS_VIOLATION);
1875 ret = FALSE;
1876 }
1877 _SEH_END
1878 return ret;
1879 }
1880
1881 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
1882 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1883 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1884 {
1885 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
1886
1887 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
1888 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1889 }
1890
1891 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
1892 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1893 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1894 {
1895 BOOL ret;
1896
1897 _SEH_TRY
1898 {
1899 DWORD significantBytes, lenBytes;
1900 BYTE padByte = 0, bytesNeeded;
1901 BOOL pad = FALSE;
1902 const CRYPT_INTEGER_BLOB *blob =
1903 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
1904
1905 significantBytes = blob->cbData;
1906 if (significantBytes)
1907 {
1908 if (blob->pbData[significantBytes - 1] & 0x80)
1909 {
1910 /* negative, lop off leading (little-endian) 0xffs */
1911 for (; significantBytes > 0 &&
1912 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
1913 ;
1914 if (blob->pbData[significantBytes - 1] < 0x80)
1915 {
1916 padByte = 0xff;
1917 pad = TRUE;
1918 }
1919 }
1920 else
1921 {
1922 /* positive, lop off leading (little-endian) zeroes */
1923 for (; significantBytes > 0 &&
1924 !blob->pbData[significantBytes - 1]; significantBytes--)
1925 ;
1926 if (significantBytes == 0)
1927 significantBytes = 1;
1928 if (blob->pbData[significantBytes - 1] > 0x7f)
1929 {
1930 padByte = 0;
1931 pad = TRUE;
1932 }
1933 }
1934 }
1935 if (pad)
1936 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
1937 else
1938 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
1939 bytesNeeded = 1 + lenBytes + significantBytes;
1940 if (pad)
1941 bytesNeeded++;
1942 if (!pbEncoded)
1943 {
1944 *pcbEncoded = bytesNeeded;
1945 ret = TRUE;
1946 }
1947 else
1948 {
1949 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1950 pcbEncoded, bytesNeeded)))
1951 {
1952 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1953 pbEncoded = *(BYTE **)pbEncoded;
1954 *pbEncoded++ = ASN_INTEGER;
1955 if (pad)
1956 {
1957 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
1958 pbEncoded += lenBytes;
1959 *pbEncoded++ = padByte;
1960 }
1961 else
1962 {
1963 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
1964 pbEncoded += lenBytes;
1965 }
1966 for (; significantBytes > 0; significantBytes--)
1967 *(pbEncoded++) = blob->pbData[significantBytes - 1];
1968 }
1969 }
1970 }
1971 _SEH_EXCEPT(page_fault)
1972 {
1973 SetLastError(STATUS_ACCESS_VIOLATION);
1974 ret = FALSE;
1975 }
1976 _SEH_END
1977 return ret;
1978 }
1979
1980 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
1981 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1982 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1983 {
1984 BOOL ret;
1985
1986 _SEH_TRY
1987 {
1988 DWORD significantBytes, lenBytes;
1989 BYTE bytesNeeded;
1990 BOOL pad = FALSE;
1991 const CRYPT_INTEGER_BLOB *blob =
1992 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
1993
1994 significantBytes = blob->cbData;
1995 if (significantBytes)
1996 {
1997 /* positive, lop off leading (little-endian) zeroes */
1998 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
1999 significantBytes--)
2000 ;
2001 if (significantBytes == 0)
2002 significantBytes = 1;
2003 if (blob->pbData[significantBytes - 1] > 0x7f)
2004 pad = TRUE;
2005 }
2006 if (pad)
2007 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2008 else
2009 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2010 bytesNeeded = 1 + lenBytes + significantBytes;
2011 if (pad)
2012 bytesNeeded++;
2013 if (!pbEncoded)
2014 {
2015 *pcbEncoded = bytesNeeded;
2016 ret = TRUE;
2017 }
2018 else
2019 {
2020 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2021 pcbEncoded, bytesNeeded)))
2022 {
2023 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2024 pbEncoded = *(BYTE **)pbEncoded;
2025 *pbEncoded++ = ASN_INTEGER;
2026 if (pad)
2027 {
2028 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2029 pbEncoded += lenBytes;
2030 *pbEncoded++ = 0;
2031 }
2032 else
2033 {
2034 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2035 pbEncoded += lenBytes;
2036 }
2037 for (; significantBytes > 0; significantBytes--)
2038 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2039 }
2040 }
2041 }
2042 _SEH_EXCEPT(page_fault)
2043 {
2044 SetLastError(STATUS_ACCESS_VIOLATION);
2045 ret = FALSE;
2046 }
2047 _SEH_END
2048 return ret;
2049 }
2050
2051 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2052 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2053 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2054 {
2055 CRYPT_INTEGER_BLOB blob;
2056 BOOL ret;
2057
2058 /* Encode as an unsigned integer, then change the tag to enumerated */
2059 blob.cbData = sizeof(DWORD);
2060 blob.pbData = (BYTE *)pvStructInfo;
2061 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2062 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2063 if (ret && pbEncoded)
2064 {
2065 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2066 pbEncoded = *(BYTE **)pbEncoded;
2067 pbEncoded[0] = ASN_ENUMERATED;
2068 }
2069 return ret;
2070 }
2071
2072 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2073 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2074 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2075 {
2076 BOOL ret;
2077
2078 _SEH_TRY
2079 {
2080 SYSTEMTIME sysTime;
2081 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2082 * temporary buffer because the output buffer is not NULL-terminated.
2083 */
2084 char buf[16];
2085 static const DWORD bytesNeeded = sizeof(buf) - 1;
2086
2087 if (!pbEncoded)
2088 {
2089 *pcbEncoded = bytesNeeded;
2090 ret = TRUE;
2091 }
2092 else
2093 {
2094 /* Sanity check the year, this is a two-digit year format */
2095 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2096 &sysTime);
2097 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2098 {
2099 SetLastError(CRYPT_E_BAD_ENCODE);
2100 ret = FALSE;
2101 }
2102 if (ret)
2103 {
2104 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2105 pbEncoded, pcbEncoded, bytesNeeded)))
2106 {
2107 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2108 pbEncoded = *(BYTE **)pbEncoded;
2109 buf[0] = ASN_UTCTIME;
2110 buf[1] = bytesNeeded - 2;
2111 snprintf(buf + 2, sizeof(buf) - 2,
2112 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2113 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2114 sysTime.wDay, sysTime.wMonth, sysTime.wHour,
2115 sysTime.wMinute, sysTime.wSecond);
2116 memcpy(pbEncoded, buf, bytesNeeded);
2117 }
2118 }
2119 }
2120 }
2121 _SEH_EXCEPT(page_fault)
2122 {
2123 SetLastError(STATUS_ACCESS_VIOLATION);
2124 ret = FALSE;
2125 }
2126 _SEH_END
2127 return ret;
2128 }
2129
2130 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2131 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2132 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2133 {
2134 BOOL ret;
2135
2136 _SEH_TRY
2137 {
2138 SYSTEMTIME sysTime;
2139 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2140 * temporary buffer because the output buffer is not NULL-terminated.
2141 */
2142 char buf[18];
2143 static const DWORD bytesNeeded = sizeof(buf) - 1;
2144
2145 if (!pbEncoded)
2146 {
2147 *pcbEncoded = bytesNeeded;
2148 ret = TRUE;
2149 }
2150 else
2151 {
2152 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2153 &sysTime);
2154 if (ret)
2155 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2156 pcbEncoded, bytesNeeded);
2157 if (ret)
2158 {
2159 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2160 pbEncoded = *(BYTE **)pbEncoded;
2161 buf[0] = ASN_GENERALTIME;
2162 buf[1] = bytesNeeded - 2;
2163 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2164 sysTime.wYear, sysTime.wDay, sysTime.wMonth, sysTime.wHour,
2165 sysTime.wMinute, sysTime.wSecond);
2166 memcpy(pbEncoded, buf, bytesNeeded);
2167 }
2168 }
2169 }
2170 _SEH_EXCEPT(page_fault)
2171 {
2172 SetLastError(STATUS_ACCESS_VIOLATION);
2173 ret = FALSE;
2174 }
2175 _SEH_END
2176 return ret;
2177 }
2178
2179 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2180 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2181 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2182 {
2183 BOOL ret;
2184
2185 _SEH_TRY
2186 {
2187 SYSTEMTIME sysTime;
2188
2189 /* Check the year, if it's in the UTCTime range call that encode func */
2190 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2191 return FALSE;
2192 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2193 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2194 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2195 else
2196 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2197 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2198 pcbEncoded);
2199 }
2200 _SEH_EXCEPT(page_fault)
2201 {
2202 SetLastError(STATUS_ACCESS_VIOLATION);
2203 ret = FALSE;
2204 }
2205 _SEH_END
2206 return ret;
2207 }
2208
2209 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2210 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2211 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2212 {
2213 BOOL ret;
2214
2215 _SEH_TRY
2216 {
2217 DWORD bytesNeeded, dataLen, lenBytes, i;
2218 const CRYPT_SEQUENCE_OF_ANY *seq =
2219 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2220
2221 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2222 dataLen += seq->rgValue[i].cbData;
2223 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2224 bytesNeeded = 1 + lenBytes + dataLen;
2225 if (!pbEncoded)
2226 {
2227 *pcbEncoded = bytesNeeded;
2228 ret = TRUE;
2229 }
2230 else
2231 {
2232 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2233 pcbEncoded, bytesNeeded)))
2234 {
2235 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2236 pbEncoded = *(BYTE **)pbEncoded;
2237 *pbEncoded++ = ASN_SEQUENCEOF;
2238 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2239 pbEncoded += lenBytes;
2240 for (i = 0; i < seq->cValue; i++)
2241 {
2242 memcpy(pbEncoded, seq->rgValue[i].pbData,
2243 seq->rgValue[i].cbData);
2244 pbEncoded += seq->rgValue[i].cbData;
2245 }
2246 }
2247 }
2248 }
2249 _SEH_EXCEPT(page_fault)
2250 {
2251 SetLastError(STATUS_ACCESS_VIOLATION);
2252 ret = FALSE;
2253 }
2254 _SEH_END
2255 return ret;
2256 }
2257
2258 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
2259 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
2260 void *pvEncoded, DWORD *pcbEncoded)
2261 {
2262 BOOL ret = FALSE;
2263 HMODULE lib = NULL;
2264 CryptEncodeObjectExFunc encodeFunc = NULL;
2265
2266 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType,
2267 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
2268 pvEncoded, pcbEncoded);
2269
2270 if (!pvEncoded && !pcbEncoded)
2271 {
2272 SetLastError(ERROR_INVALID_PARAMETER);
2273 return FALSE;
2274 }
2275 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
2276 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
2277 {
2278 SetLastError(ERROR_FILE_NOT_FOUND);
2279 return FALSE;
2280 }
2281
2282 SetLastError(NOERROR);
2283 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
2284 *(BYTE **)pvEncoded = NULL;
2285 if (!HIWORD(lpszStructType))
2286 {
2287 switch (LOWORD(lpszStructType))
2288 {
2289 case (WORD)X509_CERT:
2290 encodeFunc = CRYPT_AsnEncodeCert;
2291 break;
2292 case (WORD)X509_CERT_TO_BE_SIGNED:
2293 encodeFunc = CRYPT_AsnEncodeCertInfo;
2294 break;
2295 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
2296 encodeFunc = CRYPT_AsnEncodeCRLInfo;
2297 break;
2298 case (WORD)X509_EXTENSIONS:
2299 encodeFunc = CRYPT_AsnEncodeExtensions;
2300 break;
2301 case (WORD)X509_NAME:
2302 encodeFunc = CRYPT_AsnEncodeName;
2303 break;
2304 case (WORD)X509_PUBLIC_KEY_INFO:
2305 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
2306 break;
2307 case (WORD)X509_ALTERNATE_NAME:
2308 encodeFunc = CRYPT_AsnEncodeAltName;
2309 break;
2310 case (WORD)X509_BASIC_CONSTRAINTS2:
2311 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
2312 break;
2313 case (WORD)RSA_CSP_PUBLICKEYBLOB:
2314 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
2315 break;
2316 case (WORD)X509_OCTET_STRING:
2317 encodeFunc = CRYPT_AsnEncodeOctets;
2318 break;
2319 case (WORD)X509_BITS:
2320 case (WORD)X509_KEY_USAGE:
2321 encodeFunc = CRYPT_AsnEncodeBits;
2322 break;
2323 case (WORD)X509_INTEGER:
2324 encodeFunc = CRYPT_AsnEncodeInt;
2325 break;
2326 case (WORD)X509_MULTI_BYTE_INTEGER:
2327 encodeFunc = CRYPT_AsnEncodeInteger;
2328 break;
2329 case (WORD)X509_MULTI_BYTE_UINT:
2330 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
2331 break;
2332 case (WORD)X509_ENUMERATED:
2333 encodeFunc = CRYPT_AsnEncodeEnumerated;
2334 break;
2335 case (WORD)X509_CHOICE_OF_TIME:
2336 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
2337 break;
2338 case (WORD)X509_SEQUENCE_OF_ANY:
2339 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2340 break;
2341 case (WORD)PKCS_UTC_TIME:
2342 encodeFunc = CRYPT_AsnEncodeUtcTime;
2343 break;
2344 default:
2345 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
2346 }
2347 }
2348 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
2349 encodeFunc = CRYPT_AsnEncodeExtensions;
2350 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
2351 encodeFunc = CRYPT_AsnEncodeUtcTime;
2352 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
2353 encodeFunc = CRYPT_AsnEncodeEnumerated;
2354 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
2355 encodeFunc = CRYPT_AsnEncodeBits;
2356 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
2357 encodeFunc = CRYPT_AsnEncodeOctets;
2358 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
2359 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
2360 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
2361 encodeFunc = CRYPT_AsnEncodeAltName;
2362 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
2363 encodeFunc = CRYPT_AsnEncodeAltName;
2364 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
2365 encodeFunc = CRYPT_AsnEncodeAltName;
2366 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
2367 encodeFunc = CRYPT_AsnEncodeAltName;
2368 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
2369 encodeFunc = CRYPT_AsnEncodeAltName;
2370 else
2371 TRACE("OID %s not found or unimplemented, looking for DLL\n",
2372 debugstr_a(lpszStructType));
2373 if (!encodeFunc)
2374 encodeFunc = (CryptEncodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType,
2375 lpszStructType, CRYPT_OID_ENCODE_OBJECT_EX_FUNC, &lib);
2376 if (encodeFunc)
2377 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
2378 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
2379 else
2380 SetLastError(ERROR_FILE_NOT_FOUND);
2381 if (lib)
2382 FreeLibrary(lib);
2383 return ret;
2384 }
2385
2386 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
2387 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2388 DWORD *pcbStructInfo)
2389 {
2390 BOOL ret = FALSE;
2391 HMODULE lib;
2392 CryptDecodeObjectFunc pCryptDecodeObject;
2393
2394 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType,
2395 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
2396 pvStructInfo, pcbStructInfo);
2397
2398 if (!pvStructInfo && !pcbStructInfo)
2399 {
2400 SetLastError(ERROR_INVALID_PARAMETER);
2401 return FALSE;
2402 }
2403
2404 /* Try registered DLL first.. */
2405 pCryptDecodeObject =
2406 (CryptDecodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType,
2407 lpszStructType, CRYPT_OID_DECODE_OBJECT_FUNC, &lib);
2408 if (pCryptDecodeObject)
2409 {
2410 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
2411 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
2412 FreeLibrary(lib);
2413 }
2414 else
2415 {
2416 /* If not, use CryptDecodeObjectEx */
2417 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
2418 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
2419 }
2420 return ret;
2421 }
2422
2423 /* Gets the number of length bytes from the given (leading) length byte */
2424 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
2425
2426 /* Helper function to get the encoded length of the data starting at pbEncoded,
2427 * where pbEncoded[0] is the tag. If the data are too short to contain a
2428 * length or if the length is too large for cbEncoded, sets an appropriate
2429 * error code and returns FALSE.
2430 */
2431 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
2432 DWORD *len)
2433 {
2434 BOOL ret;
2435
2436 if (cbEncoded <= 1)
2437 {
2438 SetLastError(CRYPT_E_ASN1_CORRUPT);
2439 ret = FALSE;
2440 }
2441 else if (pbEncoded[1] <= 0x7f)
2442 {
2443 if (pbEncoded[1] + 1 > cbEncoded)
2444 {
2445 SetLastError(CRYPT_E_ASN1_EOD);
2446 ret = FALSE;
2447 }
2448 else
2449 {
2450 *len = pbEncoded[1];
2451 ret = TRUE;
2452 }
2453 }
2454 else
2455 {
2456 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
2457
2458 if (lenLen > sizeof(DWORD) + 1)
2459 {
2460 SetLastError(CRYPT_E_ASN1_LARGE);
2461 ret = FALSE;
2462 }
2463 else if (lenLen + 2 > cbEncoded)
2464 {
2465 SetLastError(CRYPT_E_ASN1_CORRUPT);
2466 ret = FALSE;
2467 }
2468 else
2469 {
2470 DWORD out = 0;
2471
2472 pbEncoded += 2;
2473 while (--lenLen)
2474 {
2475 out <<= 8;
2476 out |= *pbEncoded++;
2477 }
2478 if (out + lenLen + 1 > cbEncoded)
2479 {
2480 SetLastError(CRYPT_E_ASN1_EOD);
2481 ret = FALSE;
2482 }
2483 else
2484 {
2485 *len = out;
2486 ret = TRUE;
2487 }
2488 }
2489 }
2490 return ret;
2491 }
2492
2493 /* Helper function to check *pcbStructInfo, set it to the required size, and
2494 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
2495 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
2496 * pointer to the newly allocated memory.
2497 */
2498 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
2499 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
2500 DWORD bytesNeeded)
2501 {
2502 BOOL ret = TRUE;
2503
2504 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2505 {
2506 if (pDecodePara && pDecodePara->pfnAlloc)
2507 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
2508 else
2509 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
2510 if (!*(BYTE **)pvStructInfo)
2511 ret = FALSE;
2512 else
2513 *pcbStructInfo = bytesNeeded;
2514 }
2515 else if (*pcbStructInfo < bytesNeeded)
2516 {
2517 *pcbStructInfo = bytesNeeded;
2518 SetLastError(ERROR_MORE_DATA);
2519 ret = FALSE;
2520 }
2521 return ret;
2522 }
2523
2524 /* A few of the members need explanation:
2525 * offset:
2526 * A sequence is decoded into a struct. The offset member is the
2527 * offset of this item within that struct.
2528 * decodeFunc:
2529 * The decoder function to use. If this is NULL, then the member isn't
2530 * decoded, but minSize space is reserved for it.
2531 * minSize:
2532 * The minimum amount of space occupied after decoding. You must set this.
2533 * optional:
2534 * If true, and a decoding function fails with CRYPT_E_ASN1_BADTAG, then
2535 * minSize space is filled with 0 for this member. (Any other failure
2536 * results in CRYPT_AsnDecodeSequence failing.)
2537 * hasPointer, pointerOffset, minSize:
2538 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
2539 * the offset within the (outer) struct of the data pointer (or to the
2540 * first data pointer, if more than one exist).
2541 * size:
2542 * Used by CRYPT_AsnDecodeSequence, not for your use.
2543 */
2544 struct AsnDecodeSequenceItem
2545 {
2546 DWORD offset;
2547 CryptDecodeObjectExFunc decodeFunc;
2548 DWORD minSize;
2549 BOOL optional;
2550 BOOL hasPointer;
2551 DWORD pointerOffset;
2552 DWORD size;
2553 };
2554
2555 /* This decodes an arbitrary sequence into a contiguous block of memory
2556 * (basically, a struct.) Each element being decoded is described by a struct
2557 * AsnDecodeSequenceItem, see above.
2558 * startingPointer is an optional pointer to the first place where dynamic
2559 * data will be stored. If you know the starting offset, you may pass it
2560 * here. Otherwise, pass NULL, and one will be inferred from the items.
2561 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
2562 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
2563 */
2564 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
2565 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
2566 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2567 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
2568 {
2569 BOOL ret;
2570
2571 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items, cItem, pbEncoded,
2572 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
2573 startingPointer);
2574
2575 if (pbEncoded[0] == ASN_SEQUENCE)
2576 {
2577 DWORD dataLen;
2578
2579 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2580 {
2581 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2582 DWORD i, bytesNeeded = 0, minSize = 0;
2583 const BYTE *ptr;
2584
2585 ptr = pbEncoded + 1 + lenBytes;
2586 for (i = 0; ret && i < cItem; i++)
2587 {
2588 DWORD nextItemLen;
2589
2590 minSize += items[i].minSize;
2591 if (cbEncoded - (ptr - pbEncoded) != 0)
2592 {
2593 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
2594 &nextItemLen)))
2595 {
2596 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
2597
2598 if (items[i].decodeFunc)
2599 {
2600 TRACE("sizing item %ld\n", i);
2601 ret = items[i].decodeFunc(dwCertEncodingType, NULL,
2602 ptr, 1 + nextItemLenBytes + nextItemLen,
2603 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
2604 &items[i].size);
2605 if (ret)
2606 {
2607 /* Account for alignment padding */
2608 bytesNeeded += items[i].size;
2609 if (items[i].size % sizeof(DWORD))
2610 bytesNeeded += sizeof(DWORD) -
2611 items[i].size % sizeof(DWORD);
2612 ptr += 1 + nextItemLenBytes + nextItemLen;
2613 }
2614 else if (items[i].optional &&
2615 GetLastError() == CRYPT_E_ASN1_BADTAG)
2616 {
2617 TRACE("skipping optional item %ld\n", i);
2618 bytesNeeded += items[i].minSize;
2619 SetLastError(NOERROR);
2620 ret = TRUE;
2621 }
2622 else
2623 TRACE("item %ld failed: %08lx\n", i,
2624 GetLastError());
2625 }
2626 else
2627 bytesNeeded += items[i].minSize;
2628 }
2629 }
2630 else if (items[i].optional)
2631 bytesNeeded += items[i].minSize;
2632 else
2633 {
2634 SetLastError(CRYPT_E_ASN1_CORRUPT);
2635 ret = FALSE;
2636 }
2637 }
2638 if (cbEncoded - (ptr - pbEncoded) != 0)
2639 {
2640 TRACE("%ld remaining bytes, failing\n", cbEncoded -
2641 (ptr - pbEncoded));
2642 SetLastError(CRYPT_E_ASN1_CORRUPT);
2643 ret = FALSE;
2644 }
2645 if (ret)
2646 {
2647 if (!pvStructInfo)
2648 *pcbStructInfo = bytesNeeded;
2649 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
2650 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
2651 {
2652 BYTE *nextData;
2653
2654 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2655 pvStructInfo = *(BYTE **)pvStructInfo;
2656 if (startingPointer)
2657 nextData = (BYTE *)startingPointer;
2658 else
2659 nextData = (BYTE *)pvStructInfo + minSize;
2660 memset(pvStructInfo, 0, minSize);
2661 ptr = pbEncoded + 1 + lenBytes;
2662 for (i = 0; ret && i < cItem; i++)
2663 {
2664 if (cbEncoded - (ptr - pbEncoded) != 0)
2665 {
2666 DWORD nextItemLen;
2667 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
2668
2669 CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
2670 &nextItemLen);
2671 if (items[i].hasPointer)
2672 {
2673 *(BYTE **)((BYTE *)pvStructInfo +
2674 items[i].pointerOffset) = nextData;
2675 }
2676 if (items[i].decodeFunc)
2677 {
2678 TRACE("decoding item %ld\n", i);
2679 ret = items[i].decodeFunc(dwCertEncodingType,
2680 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
2681 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
2682 (BYTE *)pvStructInfo + items[i].offset,
2683 &items[i].size);
2684 if (!ret)
2685 TRACE("item %ld failed: %08lx\n", i,
2686 GetLastError());
2687 }
2688 else
2689 items[i].size = items[i].minSize;
2690 if (ret)
2691 {
2692 if (items[i].hasPointer &&
2693 items[i].size > items[i].minSize)
2694 {
2695 nextData += items[i].size -
2696 items[i].minSize;
2697 /* align nextData to DWORD boundaries */
2698 if (items[i].size % sizeof(DWORD))
2699 {
2700 nextData += sizeof(DWORD) -
2701 items[i].size % sizeof(DWORD);
2702 }
2703 }
2704 ptr += 1 + nextItemLenBytes + nextItemLen;
2705 }
2706 else if (items[i].optional &&
2707 GetLastError() == CRYPT_E_ASN1_BADTAG)
2708 {
2709 SetLastError(NOERROR);
2710 ret = TRUE;
2711 }
2712 }
2713 else if (!items[i].optional)
2714 {
2715 SetLastError(CRYPT_E_ASN1_CORRUPT);
2716 ret = FALSE;
2717 }
2718 }
2719 }
2720 }
2721 }
2722 }
2723 else
2724 {
2725 SetLastError(CRYPT_E_ASN1_BADTAG);
2726 ret = FALSE;
2727 }
2728 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2729 return ret;
2730 }
2731
2732 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
2733 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
2734 * to CRYPT_E_ASN1_CORRUPT.
2735 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
2736 * set!
2737 */
2738 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
2739 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2740 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2741 {
2742 BOOL ret;
2743 DWORD dataLen;
2744
2745 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2746 {
2747 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2748 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
2749
2750 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2751 bytesNeeded += 1 + lenBytes + dataLen;
2752
2753 if (!pvStructInfo)
2754 *pcbStructInfo = bytesNeeded;
2755 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2756 pvStructInfo, pcbStructInfo, bytesNeeded)))
2757 {
2758 CRYPT_DER_BLOB *blob = (CRYPT_DER_BLOB *)pvStructInfo;
2759
2760 blob->cbData = 1 + lenBytes + dataLen;
2761 if (blob->cbData)
2762 {
2763 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2764 blob->pbData = (BYTE *)pbEncoded;
2765 else
2766 {
2767 assert(blob->pbData);
2768 memcpy(blob->pbData, pbEncoded, blob->cbData);
2769 }
2770 }
2771 else
2772 {
2773 SetLastError(CRYPT_E_ASN1_CORRUPT);
2774 ret = FALSE;
2775 }
2776 }
2777 }
2778 return ret;
2779 }
2780
2781 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
2782 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
2783 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2784 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2785 {
2786 BOOL ret;
2787
2788 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2789 pDecodePara, pvStructInfo, *pcbStructInfo);
2790
2791 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2792 * place.
2793 */
2794 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
2795 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
2796 pvStructInfo, pcbStructInfo);
2797 if (ret && pvStructInfo)
2798 {
2799 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2800
2801 if (blob->cbData)
2802 {
2803 DWORD i;
2804 BYTE temp;
2805
2806 for (i = 0; i < blob->cbData / 2; i++)
2807 {
2808 temp = blob->pbData[i];
2809 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2810 blob->pbData[blob->cbData - i - 1] = temp;
2811 }
2812 }
2813 }
2814 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2815 return ret;
2816 }
2817
2818 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
2819 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2820 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2821 {
2822 BOOL ret = TRUE;
2823
2824 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2825 pDecodePara, pvStructInfo, *pcbStructInfo);
2826
2827 _SEH_TRY
2828 {
2829 struct AsnDecodeSequenceItem items[] = {
2830 { offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
2831 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
2832 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
2833 { offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm),
2834 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2835 FALSE, TRUE, offsetof(CERT_SIGNED_CONTENT_INFO,
2836 SignatureAlgorithm.pszObjId), 0 },
2837 { offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
2838 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2839 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
2840 };
2841
2842 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
2843 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
2844 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2845 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2846 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2847 }
2848 _SEH_EXCEPT(page_fault)
2849 {
2850 SetLastError(STATUS_ACCESS_VIOLATION);
2851 ret = FALSE;
2852 }
2853 _SEH_END
2854 return ret;
2855 }
2856
2857 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
2858 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2859 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2860 {
2861 BOOL ret;
2862
2863 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR))
2864 {
2865 DWORD dataLen;
2866
2867 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2868 {
2869 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2870
2871 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2872 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
2873 pvStructInfo, pcbStructInfo);
2874 }
2875 }
2876 else
2877 {
2878 SetLastError(CRYPT_E_ASN1_BADTAG);
2879 ret = FALSE;
2880 }
2881 return ret;
2882 }
2883
2884 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
2885 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2886 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2887 {
2888 BOOL ret;
2889
2890 struct AsnDecodeSequenceItem items[] = {
2891 { offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
2892 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
2893 { offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
2894 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
2895 };
2896
2897 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2898 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2899 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2900 return ret;
2901 }
2902
2903 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
2904 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2905 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2906 {
2907 BOOL ret;
2908
2909 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 3))
2910 {
2911 DWORD dataLen;
2912
2913 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2914 {
2915 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2916
2917 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
2918 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
2919 pDecodePara, pvStructInfo, pcbStructInfo);
2920 }
2921 }
2922 else
2923 {
2924 SetLastError(CRYPT_E_ASN1_BADTAG);
2925 ret = FALSE;
2926 }
2927 return ret;
2928 }
2929
2930 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
2931 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2932 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2933 {
2934 BOOL ret = TRUE;
2935
2936 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2937 pDecodePara, pvStructInfo, *pcbStructInfo);
2938
2939 _SEH_TRY
2940 {
2941 struct AsnDecodeSequenceItem items[] = {
2942 { offsetof(CERT_INFO, dwVersion), CRYPT_AsnDecodeCertVersion,
2943 sizeof(DWORD), TRUE, FALSE, 0, 0 },
2944 { offsetof(CERT_INFO, SerialNumber), CRYPT_AsnDecodeIntegerInternal,
2945 sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
2946 SerialNumber.pbData), 0 },
2947 { offsetof(CERT_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
2948 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CERT_INFO,
2949 SignatureAlgorithm.pszObjId), 0 },
2950 { offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
2951 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
2952 Issuer.pbData) },
2953 { offsetof(CERT_INFO, NotBefore), CRYPT_AsnDecodeValidity,
2954 sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE, FALSE, 0 },
2955 { offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
2956 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
2957 Subject.pbData) },
2958 { offsetof(CERT_INFO, SubjectPublicKeyInfo), CRYPT_AsnDecodePubKeyInfo,
2959 sizeof(CERT_PUBLIC_KEY_INFO), FALSE, TRUE, offsetof(CERT_INFO,
2960 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
2961 { offsetof(CERT_INFO, IssuerUniqueId), CRYPT_AsnDecodeBitsInternal,
2962 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO,
2963 IssuerUniqueId.pbData), 0 },
2964 { offsetof(CERT_INFO, SubjectUniqueId), CRYPT_AsnDecodeBitsInternal,
2965 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO,
2966 SubjectUniqueId.pbData), 0 },
2967 { offsetof(CERT_INFO, cExtension), CRYPT_AsnDecodeCertExtensions,
2968 sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CERT_INFO,
2969 rgExtension), 0 },
2970 };
2971
2972 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2973 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2974 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2975 }
2976 _SEH_EXCEPT(page_fault)
2977 {
2978 SetLastError(STATUS_ACCESS_VIOLATION);
2979 ret = FALSE;
2980 }
2981 _SEH_END
2982 return ret;
2983 }
2984
2985 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2986 DWORD dwFlags, PCRL_ENTRY entry, DWORD *pcbEntry)
2987 {
2988 BOOL ret;
2989 struct AsnDecodeSequenceItem items[] = {
2990 { offsetof(CRL_ENTRY, SerialNumber), CRYPT_AsnDecodeIntegerInternal,
2991 sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CRL_ENTRY,
2992 SerialNumber.pbData), 0 },
2993 { offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
2994 sizeof(FILETIME), FALSE, FALSE, 0 },
2995 { offsetof(CRL_ENTRY, cExtension), CRYPT_AsnDecodeExtensionsInternal,
2996 sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CRL_ENTRY,
2997 rgExtension), 0 },
2998 };
2999
3000 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
3001 *pcbEntry);
3002
3003 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3004 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
3005 NULL, entry, pcbEntry, entry ? entry->SerialNumber.pbData : NULL);
3006 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
3007 return ret;
3008 }
3009
3010 typedef struct _WINE_CRL_ENTRIES {
3011 DWORD cCRLEntry;
3012 PCRL_ENTRY rgCRLEntry;
3013 } WINE_CRL_ENTRIES, *PWINE_CRL_ENTRIES;
3014
3015 /* Warning: assumes pvStructInfo is a WINE_CRL_ENTRIES whose rgCRLEntry has
3016 * been set prior to calling.
3017 */
3018 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
3019 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3020 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3021 {
3022 BOOL ret;
3023
3024 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3025 pDecodePara, pvStructInfo, *pcbStructInfo);
3026
3027 if (pbEncoded[0] == ASN_SEQUENCEOF)
3028 {
3029 DWORD dataLen, bytesNeeded;
3030
3031 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3032 {
3033 DWORD cCRLEntry = 0;
3034 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3035
3036 bytesNeeded = sizeof(WINE_CRL_ENTRIES);
3037 if (dataLen)
3038 {
3039 const BYTE *ptr;
3040 DWORD size;
3041
3042 for (ptr = pbEncoded + 1 + lenBytes; ret &&
3043 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3044 {
3045 size = 0;
3046 ret = CRYPT_AsnDecodeCRLEntry(ptr,
3047 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
3048 if (ret)
3049 {
3050 DWORD nextLen;
3051
3052 cCRLEntry++;
3053 bytesNeeded += size;
3054 ret = CRYPT_GetLen(ptr,
3055 cbEncoded - (ptr - pbEncoded), &nextLen);
3056 if (ret)
3057 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3058 }
3059 }
3060 }
3061 if (ret)
3062 {
3063 if (!pvStructInfo)
3064 *pcbStructInfo = bytesNeeded;
3065 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3066 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3067 {
3068 DWORD size, i;
3069 BYTE *nextData;
3070 const BYTE *ptr;
3071 PWINE_CRL_ENTRIES entries;
3072
3073 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3074 pvStructInfo = *(BYTE **)pvStructInfo;
3075 *pcbStructInfo = bytesNeeded;
3076 entries = (PWINE_CRL_ENTRIES)pvStructInfo;
3077 entries->cCRLEntry = cCRLEntry;
3078 assert(entries->rgCRLEntry);
3079 nextData = (BYTE *)entries->rgCRLEntry +
3080 entries->cCRLEntry * sizeof(CRL_ENTRY);
3081 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
3082 i < cCRLEntry && ptr - pbEncoded - 1 - lenBytes <
3083 dataLen; i++)
3084 {
3085 entries->rgCRLEntry[i].SerialNumber.pbData = nextData;
3086 size = bytesNeeded;
3087 ret = CRYPT_AsnDecodeCRLEntry(ptr,
3088 cbEncoded - (ptr - pbEncoded), dwFlags,
3089 &entries->rgCRLEntry[i], &size);
3090 if (ret)
3091 {
3092 DWORD nextLen;
3093
3094 bytesNeeded -= size;
3095 /* Increment nextData by the difference of the
3096 * minimum size and the actual size.
3097 */
3098 if (size > sizeof(CRL_ENTRY))
3099 nextData += size - sizeof(CRL_ENTRY);
3100 ret = CRYPT_GetLen(ptr,
3101 cbEncoded - (ptr - pbEncoded), &nextLen);
3102 if (ret)
3103 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3104 }
3105 }
3106 }
3107 }
3108 }
3109 }
3110 else
3111 {
3112 SetLastError(CRYPT_E_ASN1_BADTAG);
3113 ret = FALSE;
3114 }
3115 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
3116 return ret;
3117 }
3118
3119 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
3120 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3121 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3122 {
3123 BOOL ret = TRUE;
3124
3125 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3126 pDecodePara, pvStructInfo, *pcbStructInfo);
3127
3128 _SEH_TRY
3129 {
3130 struct AsnDecodeSequenceItem items[] = {
3131 { offsetof(CRL_INFO, dwVersion), CRYPT_AsnDecodeCertVersion,
3132 sizeof(DWORD), TRUE, FALSE, 0, 0 },
3133 { offsetof(CRL_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
3134 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CRL_INFO,
3135 SignatureAlgorithm.pszObjId), 0 },
3136 { offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
3137 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
3138 Issuer.pbData) },
3139 { offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
3140 sizeof(FILETIME), FALSE, FALSE, 0 },
3141 { offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
3142 sizeof(FILETIME), TRUE, FALSE, 0 },
3143 { offsetof(CRL_INFO, cCRLEntry), CRYPT_AsnDecodeCRLEntries,
3144 sizeof(WINE_CRL_ENTRIES), TRUE, TRUE, offsetof(CRL_INFO,
3145 rgCRLEntry), 0 },
3146 /* Note that the extensions are ignored by MS, so I'll ignore them too
3147 */
3148 { offsetof(CRL_INFO, cExtension), NULL,
3149 sizeof(CERT_EXTENSIONS), TRUE, FALSE, 0 },
3150 };
3151
3152 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3153 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
3154 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3155 }
3156 _SEH_EXCEPT(page_fault)
3157 {
3158 SetLastError(STATUS_ACCESS_VIOLATION);
3159 ret = FALSE;
3160 }
3161 _SEH_END
3162
3163 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
3164 return ret;
3165 }
3166
3167 /* Differences between this and CRYPT_AsnDecodeOid:
3168 * - pvStructInfo is a LPSTR *, not an LPSTR
3169 * - CRYPT_AsnDecodeOid doesn't account for the size of an LPSTR in its byte
3170 * count, whereas our callers (typically CRYPT_AsnDecodeSequence) expect this
3171 * to
3172 */
3173 static BOOL WINAPI CRYPT_AsnDecodeOidWrapper(DWORD dwCertEncodingType,
3174 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3175 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3176 {
3177 BOOL ret;
3178
3179 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3180 pDecodePara, pvStructInfo, *pcbStructInfo);
3181
3182 ret = CRYPT_AsnDecodeOid(pbEncoded, cbEncoded, dwFlags,
3183 pvStructInfo ? *(LPSTR *)pvStructInfo : NULL, pcbStructInfo);
3184 if (ret || GetLastError() == ERROR_MORE_DATA)
3185 *pcbStructInfo += sizeof(LPSTR);
3186 if (ret && pvStructInfo)
3187 TRACE("returning %s\n", debugstr_a(*(LPSTR *)pvStructInfo));
3188 return ret;
3189 }
3190
3191 /* Warning: assumes ext->pszObjId is set ahead of time! */
3192 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
3193 DWORD dwFlags, CERT_EXTENSION *ext, DWORD *pcbExt)
3194 {
3195 struct AsnDecodeSequenceItem items[] = {
3196 { offsetof(CERT_EXTENSION, pszObjId), CRYPT_AsnDecodeOidWrapper,
3197 sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_EXTENSION, pszObjId), 0 },
3198 { offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
3199 sizeof(BOOL), TRUE, FALSE, 0, 0 },
3200 { offsetof(CERT_EXTENSION, Value), CRYPT_AsnDecodeOctetsInternal,
3201 sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE, offsetof(CERT_EXTENSION,
3202 Value.pbData) },
3203 };
3204 BOOL ret = TRUE;
3205
3206 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
3207 *pcbExt);
3208
3209 if (ext)
3210 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
3211 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3212 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
3213 ext, pcbExt, ext ? ext->pszObjId : NULL);
3214 if (ext)
3215 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
3216 debugstr_a(ext->pszObjId));
3217 TRACE("returning %d (%08lx)\n", ret, GetLastError());
3218 return ret;
3219 }
3220
3221 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
3222 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3223 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3224 {
3225 BOOL ret = TRUE;
3226
3227 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3228 pDecodePara, pvStructInfo, *pcbStructInfo);
3229
3230 if (pbEncoded[0] == ASN_SEQUENCEOF)
3231 {
3232 DWORD dataLen, bytesNeeded;
3233
3234 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3235 {
3236 DWORD cExtension = 0;
3237 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3238
3239 bytesNeeded = sizeof(CERT_EXTENSIONS);
3240 if (dataLen)
3241 {
3242 const BYTE *ptr;
3243 DWORD size;
3244
3245 for (ptr = pbEncoded + 1 + lenBytes; ret &&
3246 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3247 {
3248 size = 0;
3249 ret = CRYPT_AsnDecodeExtension(ptr,
3250 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
3251 if (ret)
3252 {
3253 DWORD nextLen;
3254
3255 cExtension++;
3256 bytesNeeded += size;
3257 ret = CRYPT_GetLen(ptr,
3258 cbEncoded - (ptr - pbEncoded), &nextLen);
3259 if (ret)
3260 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3261 }
3262 }
3263 }
3264 if (ret)
3265 {
3266 if (!pvStructInfo)
3267 *pcbStructInfo = bytesNeeded;
3268 else if (*pcbStructInfo < bytesNeeded)
3269 {
3270 SetLastError(ERROR_MORE_DATA);
3271 *pcbStructInfo = bytesNeeded;
3272 ret = FALSE;
3273 }
3274 else
3275 {
3276 DWORD size, i;
3277 BYTE *nextData;
3278 const BYTE *ptr;
3279 CERT_EXTENSIONS *exts;
3280
3281 *pcbStructInfo = bytesNeeded;
3282 exts = (CERT_EXTENSIONS *)pvStructInfo;
3283 exts->cExtension = cExtension;
3284 assert(exts->rgExtension);
3285 nextData = (BYTE *)exts->rgExtension +
3286 exts->cExtension * sizeof(CERT_EXTENSION);
3287 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
3288 i < cExtension && ptr - pbEncoded - 1 - lenBytes <
3289 dataLen; i++)
3290 {
3291 exts->rgExtension[i].pszObjId = (LPSTR)nextData;
3292 size = bytesNeeded;
3293 ret = CRYPT_AsnDecodeExtension(ptr,
3294 cbEncoded - (ptr - pbEncoded), dwFlags,
3295 &exts->rgExtension[i], &size);
3296 if (ret)
3297 {
3298 DWORD nextLen;
3299
3300 bytesNeeded -= size;
3301 if (size > sizeof(CERT_EXTENSION))
3302 nextData += size - sizeof(CERT_EXTENSION);
3303 ret = CRYPT_GetLen(ptr,
3304 cbEncoded - (ptr - pbEncoded), &nextLen);
3305 if (ret)
3306 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3307 }
3308 }
3309 }
3310 }
3311 }
3312 }
3313 else
3314 {
3315 SetLastError(CRYPT_E_ASN1_BADTAG);
3316 ret = FALSE;
3317 }
3318 return ret;
3319 }
3320
3321 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
3322 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3323 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3324 {
3325 BOOL ret = TRUE;
3326
3327 _SEH_TRY
3328 {
3329 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
3330 lpszStructType, pbEncoded, cbEncoded,
3331 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
3332 if (ret && pvStructInfo)
3333 {
3334 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3335 pcbStructInfo, *pcbStructInfo);
3336 if (ret)
3337 {
3338 CERT_EXTENSIONS *exts;
3339
3340 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3341 pvStructInfo = *(BYTE **)pvStructInfo;
3342 exts = (CERT_EXTENSIONS *)pvStructInfo;
3343 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
3344 sizeof(CERT_EXTENSIONS));
3345 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
3346 lpszStructType, pbEncoded, cbEncoded,
3347 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
3348 pcbStructInfo);
3349 }
3350 }
3351 }
3352 _SEH_EXCEPT(page_fault)
3353 {
3354 SetLastError(STATUS_ACCESS_VIOLATION);
3355 ret = FALSE;
3356 }
3357 _SEH_END
3358 return ret;
3359 }
3360
3361 /* FIXME: honor the CRYPT_DECODE_SHARE_OID_STRING_FLAG. */
3362 static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded,
3363 DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId)
3364 {
3365 BOOL ret = TRUE;
3366
3367 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, pszObjId,
3368 *pcbObjId);
3369
3370 _SEH_TRY
3371 {
3372 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
3373 {
3374 DWORD dataLen;
3375
3376 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3377 {
3378 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3379 DWORD bytesNeeded;
3380
3381 if (dataLen)
3382 {
3383 /* The largest possible string for the first two components
3384 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
3385 */
3386 char firstTwo[6];
3387 const BYTE *ptr;
3388
3389 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
3390 pbEncoded[1 + lenBytes] / 40,
3391 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
3392 * 40);
3393 bytesNeeded = strlen(firstTwo) + 1;
3394 for (ptr = pbEncoded + 2 + lenBytes; ret &&
3395 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3396 {
3397 /* large enough for ".4000000" */
3398 char str[9];
3399 int val = 0;
3400
3401 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
3402 (*ptr & 0x80))
3403 {
3404 val <<= 7;
3405 val |= *ptr & 0x7f;
3406 ptr++;
3407 }
3408 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
3409 (*ptr & 0x80))
3410 {
3411 SetLastError(CRYPT_E_ASN1_CORRUPT);
3412 ret = FALSE;
3413 }
3414 else
3415 {
3416 val <<= 7;
3417 val |= *ptr++;
3418 snprintf(str, sizeof(str), ".%d", val);
3419 bytesNeeded += strlen(str);
3420 }
3421 }
3422 if (!pszObjId)
3423 *pcbObjId = bytesNeeded;
3424 else if (*pcbObjId < bytesNeeded)
3425 {
3426 *pcbObjId = bytesNeeded;
3427 SetLastError(ERROR_MORE_DATA);
3428 ret = FALSE;
3429 }
3430 else
3431 {
3432 *pszObjId = 0;
3433 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
3434 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
3435 40) * 40);
3436 pszObjId += strlen(pszObjId);
3437 for (ptr = pbEncoded + 2 + lenBytes; ret &&
3438 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3439 {
3440 int val = 0;
3441
3442 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
3443 (*ptr & 0x80))
3444 {
3445 val <<= 7;
3446 val |= *ptr & 0x7f;
3447 ptr++;
3448 }
3449 val <<= 7;
3450 val |= *ptr++;
3451 sprintf(pszObjId, ".%d", val);
3452 pszObjId += strlen(pszObjId);
3453 }
3454 }
3455 }
3456 else
3457 bytesNeeded = 0;
3458 *pcbObjId = bytesNeeded;
3459 }
3460 }
3461 else
3462 {
3463 SetLastError(CRYPT_E_ASN1_BADTAG);
3464 ret = FALSE;
3465 }
3466 }
3467 _SEH_EXCEPT(page_fault)
3468 {
3469 SetLastError(STATUS_ACCESS_VIOLATION);
3470 ret = FALSE;
3471 }
3472 _SEH_END
3473 return ret;
3474 }
3475
3476 /* Warning: this assumes the address of value->Value.pbData is already set, in
3477 * order to avoid overwriting memory. (In some cases, it may change it, if it
3478 * doesn't copy anything to memory.) Be sure to set it correctly!
3479 */
3480 static BOOL WINAPI CRYPT_AsnDecodeNameValue(const BYTE *pbEncoded,
3481 DWORD cbEncoded, DWORD dwFlags, CERT_NAME_VALUE *value, DWORD *pcbValue)
3482 {
3483 BOOL ret = TRUE;
3484
3485 _SEH_TRY
3486 {
3487 DWORD dataLen;
3488
3489 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3490 {
3491 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3492
3493 switch (pbEncoded[0])
3494 {
3495 case ASN_NUMERICSTRING:
3496 case ASN_PRINTABLESTRING:
3497 case ASN_IA5STRING:
3498 break;
3499 default:
3500 FIXME("Unimplemented string type %02x\n", pbEncoded[0]);
3501 SetLastError(OSS_UNIMPLEMENTED);
3502 ret = FALSE;
3503 }
3504 if (ret)
3505 {
3506 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE);
3507
3508 switch (pbEncoded[0])
3509 {
3510 case ASN_NUMERICSTRING:
3511 case ASN_PRINTABLESTRING:
3512 case ASN_IA5STRING:
3513 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3514 bytesNeeded += dataLen;
3515 break;
3516 }
3517 if (!value)
3518 *pcbValue = bytesNeeded;
3519 else if (*pcbValue < bytesNeeded)
3520 {
3521 *pcbValue = bytesNeeded;
3522 SetLastError(ERROR_MORE_DATA);
3523 ret = FALSE;
3524 }
3525 else
3526 {
3527 *pcbValue = bytesNeeded;
3528 switch (pbEncoded[0])
3529 {
3530 case ASN_NUMERICSTRING:
3531 value->dwValueType = CERT_RDN_NUMERIC_STRING;
3532 break;
3533 case ASN_PRINTABLESTRING:
3534 value->dwValueType = CERT_RDN_PRINTABLE_STRING;
3535 break;
3536 case ASN_IA5STRING:
3537 value->dwValueType = CERT_RDN_IA5_STRING;
3538 break;
3539 }
3540 if (dataLen)
3541 {
3542 switch (pbEncoded[0])
3543 {
3544 case ASN_NUMERICSTRING:
3545 case ASN_PRINTABLESTRING:
3546 case ASN_IA5STRING:
3547 value->Value.cbData = dataLen;
3548 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3549 value->Value.pbData = (BYTE *)pbEncoded + 1 +
3550 lenBytes;
3551 else
3552 {
3553 assert(value->Value.pbData);
3554 memcpy(value->Value.pbData,
3555 pbEncoded + 1 + lenBytes, dataLen);
3556 }
3557 break;
3558 }
3559 }
3560 else
3561 {
3562 value->Value.cbData = 0;
3563 value->Value.pbData = NULL;
3564 }
3565 }
3566 }
3567 }
3568 }
3569 _SEH_EXCEPT(page_fault)
3570 {
3571 SetLastError(STATUS_ACCESS_VIOLATION);
3572 ret = FALSE;
3573 }
3574 _SEH_END
3575 return ret;
3576 }
3577
3578 /* FIXME: this should use CRYPT_AsnDecodeSequence (though that won't accept it
3579 * at the moment because of the ASN_CONSTRUCTOR tag.)
3580 */
3581 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded,
3582 DWORD cbEncoded, DWORD dwFlags, CERT_RDN_ATTR *attr, DWORD *pcbAttr)
3583 {
3584 BOOL ret;
3585
3586 _SEH_TRY
3587 {
3588 if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SEQUENCE))
3589 {
3590 DWORD bytesNeeded, dataLen, size;
3591 BYTE lenBytes;
3592
3593 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3594 {
3595 /* The data length must be at least 4, two for the tag and
3596 * length for the OID, and two for the string (assuming both
3597 * have short-form lengths.)
3598 */
3599 if (dataLen < 4)
3600 {
3601 SetLastError(CRYPT_E_ASN1_EOD);
3602 ret = FALSE;
3603 }
3604 else
3605 {
3606 bytesNeeded = sizeof(CERT_RDN_ATTR);
3607 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3608 ret = CRYPT_AsnDecodeOid(pbEncoded + 1 + lenBytes,
3609 cbEncoded - 1 - lenBytes, dwFlags, NULL, &size);
3610 if (ret)
3611 {
3612 /* ugly: need to know the size of the next element of
3613 * the sequence, so get it directly
3614 */
3615 DWORD objIdOfset = 1 + lenBytes, objIdLen,
3616 nameValueOffset = 0;
3617
3618 ret = CRYPT_GetLen(pbEncoded + objIdOfset,
3619 cbEncoded - objIdOfset, &objIdLen);
3620 bytesNeeded += size;
3621 /* hack: like encoding, this takes advantage of the
3622 * fact that the rest of the structure is identical to
3623 * a CERT_NAME_VALUE.
3624 */
3625 if (ret)
3626 {
3627 nameValueOffset = objIdOfset + objIdLen + 1 +
3628 GET_LEN_BYTES(pbEncoded[objIdOfset]);
3629 ret = CRYPT_AsnDecodeNameValue(
3630 pbEncoded + nameValueOffset,
3631 cbEncoded - nameValueOffset, dwFlags, NULL, &size);
3632 }
3633 if (ret)
3634 {
3635 bytesNeeded += size;
3636 if (!attr)
3637 *pcbAttr = bytesNeeded;
3638 else if (*pcbAttr < bytesNeeded)
3639 {
3640 *pcbAttr = bytesNeeded;
3641 SetLastError(ERROR_MORE_DATA);
3642 ret = FALSE;
3643 }
3644 else
3645 {
3646 BYTE *originalData = attr->Value.pbData;
3647
3648 *pcbAttr = bytesNeeded;
3649 /* strange: decode the value first, because it
3650 * has a counted size, and we can store the OID
3651 * after it. Keep track of the original data
3652 * pointer, we'll need to know whether it was
3653 * changed.
3654 */
3655 size = bytesNeeded;
3656 ret = CRYPT_AsnDecodeNameValue(
3657 pbEncoded + nameValueOffset,
3658 cbEncoded - nameValueOffset, dwFlags,
3659 (CERT_NAME_VALUE *)&attr->dwValueType, &size);
3660 if (ret)
3661 {
3662 if (objIdLen)
3663 {
3664 /* if the data were copied to the
3665 * original location, the OID goes
3666 * after. Otherwise it goes in the
3667 * spot originally reserved for the
3668 * data.
3669 */
3670 if (attr->Value.pbData == originalData)
3671 attr->pszObjId =
3672 (LPSTR)(attr->Value.pbData +
3673 attr->Value.cbData);
3674 else
3675 attr->pszObjId =
3676 (LPSTR)originalData;
3677 size = bytesNeeded - size;
3678 ret = CRYPT_AsnDecodeOid(
3679 pbEncoded + objIdOfset,
3680 cbEncoded - objIdOfset,
3681 dwFlags, attr->pszObjId, &size);
3682 }
3683 else
3684 attr->pszObjId = NULL;
3685 }
3686 }
3687 }
3688 }
3689 }
3690 }
3691 }
3692 else
3693 {
3694 SetLastError(CRYPT_E_ASN1_BADTAG);
3695 ret = FALSE;
3696 }
3697 }
3698 _SEH_EXCEPT(page_fault)
3699 {
3700 SetLastError(STATUS_ACCESS_VIOLATION);
3701 ret = FALSE;
3702 }
3703 _SEH_END
3704 return ret;
3705 }
3706
3707 static BOOL WINAPI CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
3708 DWORD dwFlags, CERT_RDN *rdn, DWORD *pcbRdn)
3709 {
3710 BOOL ret = TRUE;
3711
3712 _SEH_TRY
3713 {
3714 if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SETOF))
3715 {
3716 DWORD dataLen;
3717
3718 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3719 {
3720 DWORD bytesNeeded, cRDNAttr = 0;
3721 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3722
3723 bytesNeeded = sizeof(CERT_RDN);
3724 if (dataLen)
3725 {
3726 const BYTE *ptr;
3727 DWORD size;
3728
3729 for (ptr = pbEncoded + 1 + lenBytes; ret &&
3730 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3731 {
3732 ret = CRYPT_AsnDecodeRdnAttr(ptr,
3733 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
3734 if (ret)
3735 {
3736 DWORD nextLen;
3737
3738 cRDNAttr++;
3739 bytesNeeded += size;
3740 ret = CRYPT_GetLen(ptr,
3741 cbEncoded - (ptr - pbEncoded), &nextLen);
3742 if (ret)
3743 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3744 }
3745 }
3746 }
3747 if (ret)
3748 {
3749 if (!rdn)
3750 *pcbRdn = bytesNeeded;
3751 else if (*pcbRdn < bytesNeeded)
3752 {
3753 *pcbRdn = bytesNeeded;
3754 SetLastError(ERROR_MORE_DATA);
3755 ret = FALSE;
3756 }
3757 else
3758 {
3759 DWORD size, i;
3760 BYTE *nextData;
3761 const BYTE *ptr;
3762
3763 *pcbRdn = bytesNeeded;
3764 rdn->cRDNAttr = cRDNAttr;
3765 rdn->rgRDNAttr = (CERT_RDN_ATTR *)((BYTE *)rdn +
3766 sizeof(CERT_RDN));
3767 nextData = (BYTE *)rdn->rgRDNAttr +
3768 rdn->cRDNAttr * sizeof(CERT_RDN_ATTR);
3769 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
3770 i < cRDNAttr && ptr - pbEncoded - 1 - lenBytes <
3771 dataLen; i++)
3772 {
3773 rdn->rgRDNAttr[i].Value.pbData = nextData;
3774 size = bytesNeeded;
3775 ret = CRYPT_AsnDecodeRdnAttr(ptr,
3776 cbEncoded - (ptr - pbEncoded), dwFlags,
3777 &rdn->rgRDNAttr[i], &size);
3778 if (ret)
3779 {
3780 DWORD nextLen;
3781
3782 bytesNeeded -= size;
3783 /* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG, the
3784 * data may not have been copied.
3785 */
3786 if (rdn->rgRDNAttr[i].Value.pbData == nextData)
3787 nextData +=
3788 rdn->rgRDNAttr[i].Value.cbData;
3789 /* Ugly: the OID, if copied, is stored in
3790 * memory after the value, so increment by its
3791 * string length if it's set and points here.
3792 */
3793 if ((const BYTE *)rdn->rgRDNAttr[i].pszObjId
3794 == nextData)
3795 nextData += strlen(
3796 rdn->rgRDNAttr[i].pszObjId) + 1;
3797 ret = CRYPT_GetLen(ptr,
3798 cbEncoded - (ptr - pbEncoded), &nextLen);
3799 if (ret)
3800 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3801 }
3802 }
3803 }
3804 }
3805 }
3806 }
3807 else
3808 {
3809 SetLastError(CRYPT_E_ASN1_BADTAG);
3810 ret = FALSE;
3811 }
3812 }
3813 _SEH_EXCEPT(page_fault)
3814 {
3815 SetLastError(STATUS_ACCESS_VIOLATION);
3816 ret = FALSE;
3817 }
3818 _SEH_END
3819 return ret;
3820 }
3821
3822 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
3823 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3824 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3825 {
3826 BOOL ret = TRUE;
3827
3828 _SEH_TRY
3829 {
3830 if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SEQUENCEOF))
3831 {
3832 DWORD dataLen;
3833
3834 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3835 {
3836 DWORD bytesNeeded, cRDN = 0;
3837 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3838
3839 bytesNeeded = sizeof(CERT_NAME_INFO);
3840 if (dataLen)
3841 {
3842 const BYTE *ptr;
3843
3844 for (ptr = pbEncoded + 1 + lenBytes; ret &&
3845 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3846 {
3847 DWORD size;
3848
3849 ret = CRYPT_AsnDecodeRdn(ptr,
3850 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
3851 if (ret)
3852 {
3853 DWORD nextLen;
3854
3855 cRDN++;
3856 bytesNeeded += size;
3857 ret = CRYPT_GetLen(ptr,
3858 cbEncoded - (ptr - pbEncoded), &nextLen);
3859 if (ret)
3860 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3861 }
3862 }
3863 }
3864 if (ret)
3865 {
3866 if (!pvStructInfo)
3867 *pcbStructInfo = bytesNeeded;
3868 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3869 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3870 {
3871 CERT_NAME_INFO *info;
3872
3873 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3874 pvStructInfo = *(BYTE **)pvStructInfo;
3875 info = (CERT_NAME_INFO *)pvStructInfo;
3876 info->cRDN = cRDN;
3877 if (info->cRDN == 0)
3878 info->rgRDN = NULL;
3879 else
3880 {
3881 DWORD size, i;
3882 BYTE *nextData;
3883 const BYTE *ptr;
3884
3885 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
3886 sizeof(CERT_NAME_INFO));
3887 nextData = (BYTE *)info->rgRDN +
3888 info->cRDN * sizeof(CERT_RDN);
3889 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
3890 i < cRDN && ptr - pbEncoded - 1 - lenBytes <
3891 dataLen; i++)
3892 {
3893 info->rgRDN[i].rgRDNAttr =
3894 (CERT_RDN_ATTR *)nextData;
3895 size = bytesNeeded;
3896 ret = CRYPT_AsnDecodeRdn(ptr,
3897 cbEncoded - (ptr - pbEncoded), dwFlags,
3898 &info->rgRDN[i], &size);
3899 if (ret)
3900 {
3901 DWORD nextLen;
3902
3903 nextData += size;
3904 bytesNeeded -= size;
3905 ret = CRYPT_GetLen(ptr,
3906 cbEncoded - (ptr - pbEncoded), &nextLen);
3907 if (ret)
3908 ptr += nextLen + 1 +
3909 GET_LEN_BYTES(ptr[1]);
3910 }
3911 }
3912 }
3913 }
3914 }
3915 }
3916 }
3917 else
3918 {
3919 SetLastError(CRYPT_E_ASN1_BADTAG);
3920 ret = FALSE;
3921 }
3922 }
3923 _SEH_EXCEPT(page_fault)
3924 {
3925 SetLastError(STATUS_ACCESS_VIOLATION);
3926 ret = FALSE;
3927 }
3928 _SEH_END
3929 return ret;
3930 }
3931
3932 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
3933 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3934 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3935 {
3936 BOOL ret = TRUE;
3937 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
3938
3939 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3940 pDecodePara, pvStructInfo, *pcbStructInfo);
3941
3942 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3943 bytesNeeded += cbEncoded;
3944 if (!pvStructInfo)
3945 *pcbStructInfo = bytesNeeded;
3946 else if (*pcbStructInfo < bytesNeeded)
3947 {
3948 SetLastError(ERROR_MORE_DATA);
3949 *pcbStructInfo = bytesNeeded;
3950 ret = FALSE;
3951 }
3952 else
3953 {
3954 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
3955
3956 *pcbStructInfo = bytesNeeded;
3957 blob->cbData = cbEncoded;
3958 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3959 blob->pbData = (LPBYTE)pbEncoded;
3960 else
3961 {
3962 assert(blob->pbData);
3963 memcpy(blob->pbData, pbEncoded, blob->cbData);
3964 }
3965 }
3966 return ret;
3967 }
3968
3969 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
3970 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3971 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3972 {
3973 CRYPT_ALGORITHM_IDENTIFIER *algo =
3974 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
3975 BOOL ret = TRUE;
3976 struct AsnDecodeSequenceItem items[] = {
3977 { offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
3978 CRYPT_AsnDecodeOidWrapper, sizeof(LPSTR), FALSE, TRUE,
3979 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
3980 { offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
3981 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3982 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
3983 };
3984
3985 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3986 pDecodePara, pvStructInfo, *pcbStructInfo);
3987
3988 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3989 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
3990 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
3991 if (ret && pvStructInfo)
3992 {
3993 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
3994 debugstr_a(algo->pszObjId));
3995 }
3996 return ret;
3997 }
3998
3999 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
4000 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4001 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4002 {
4003 BOOL ret = TRUE;
4004
4005 _SEH_TRY
4006 {
4007 struct AsnDecodeSequenceItem items[] = {
4008 { offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
4009 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4010 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
4011 Algorithm.pszObjId) },
4012 { offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
4013 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
4014 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
4015 };
4016
4017 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
4018 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
4019 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
4020 }
4021 _SEH_EXCEPT(page_fault)
4022 {
4023 SetLastError(STATUS_ACCESS_VIOLATION);
4024 ret = FALSE;
4025 }
4026 _SEH_END
4027 return ret;
4028 }
4029
4030 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
4031 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4032 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4033 {
4034 BOOL ret;
4035
4036 if (cbEncoded < 3)
4037 {
4038 SetLastError(CRYPT_E_ASN1_CORRUPT);
4039 return FALSE;
4040 }
4041 if (pbEncoded[0] != ASN_BOOL)
4042 {
4043 SetLastError(CRYPT_E_ASN1_BADTAG);
4044 return FALSE;
4045 }
4046 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
4047 {
4048 SetLastError(CRYPT_E_ASN1_CORRUPT);
4049 return FALSE;
4050 }
4051 if (pbEncoded[1] > 1)
4052 {
4053 SetLastError(CRYPT_E_ASN1_CORRUPT);
4054 return FALSE;
4055 }
4056 if (!pvStructInfo)
4057 {
4058 *pcbStructInfo = sizeof(BOOL);
4059 ret = TRUE;
4060 }
4061 else if (*pcbStructInfo < sizeof(BOOL))
4062 {
4063 *pcbStructInfo = sizeof(BOOL);
4064 SetLastError(ERROR_MORE_DATA);
4065 ret = FALSE;
4066 }
4067 else
4068 {
4069 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
4070 ret = TRUE;
4071 }
4072 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4073 return ret;
4074 }
4075
4076 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
4077 DWORD dwFlags, CERT_ALT_NAME_ENTRY *entry, DWORD *pcbEntry)
4078 {
4079 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
4080 BOOL ret;
4081
4082 if (cbEncoded < 2)
4083 {
4084 SetLastError(CRYPT_E_ASN1_CORRUPT);
4085 return FALSE;
4086 }
4087 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
4088 {
4089 SetLastError(CRYPT_E_ASN1_BADTAG);
4090 return FALSE;
4091 }
4092 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4093 if (1 + lenBytes > cbEncoded)
4094 {
4095 SetLastError(CRYPT_E_ASN1_CORRUPT);
4096 return FALSE;
4097 }
4098 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4099 {
4100 switch (pbEncoded[0] & ASN_TYPE_MASK)
4101 {
4102 case 1: /* rfc822Name */
4103 case 2: /* dNSName */
4104 case 6: /* uniformResourceIdentifier */
4105 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
4106 break;
4107 case 7: /* iPAddress */
4108 bytesNeeded += dataLen;
4109 break;
4110 case 8: /* registeredID */
4111 /* FIXME: decode as OID */
4112 case 0: /* otherName */
4113 case 4: /* directoryName */
4114 FIXME("stub\n");
4115 SetLastError(CRYPT_E_ASN1_BADTAG);
4116 ret = FALSE;
4117 break;
4118 case 3: /* x400Address, unimplemented */
4119 case 5: /* ediPartyName, unimplemented */
4120 SetLastError(CRYPT_E_ASN1_BADTAG);
4121 ret = FALSE;
4122 break;
4123 default:
4124 SetLastError(CRYPT_E_ASN1_CORRUPT);
4125 ret = FALSE;
4126 }
4127 if (ret)
4128 {
4129 if (!entry)
4130 *pcbEntry = bytesNeeded;
4131 else if (*pcbEntry < bytesNeeded)
4132 {
4133 SetLastError(ERROR_MORE_DATA);
4134 ret = FALSE;
4135 }
4136 else
4137 {
4138 /* MS used values one greater than the asn1 ones.. sigh */
4139 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
4140 switch (pbEncoded[0] & ASN_TYPE_MASK)
4141 {
4142 case 1: /* rfc822Name */
4143 case 2: /* dNSName */
4144 case 6: /* uniformResourceIdentifier */
4145 {
4146 DWORD i;
4147
4148 for (i = 0; i < dataLen; i++)
4149 entry->u.pwszURL[i] =
4150 (WCHAR)pbEncoded[1 + lenBytes + i];
4151 entry->u.pwszURL[i] = 0;
4152 break;
4153 }
4154 case 7: /* iPAddress */
4155 /* The next data pointer is in the pwszURL spot, that is,
4156 * the first 4 bytes. Need to move it to the next spot.
4157 */
4158 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
4159 entry->u.IPAddress.cbData = dataLen;
4160 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
4161 dataLen);
4162 break;
4163 }
4164 }
4165 }
4166 }
4167 return ret;
4168 }
4169
4170 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
4171 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4172 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4173 {
4174 BOOL ret = TRUE;
4175
4176 _SEH_TRY
4177 {
4178 if (pbEncoded[0] == ASN_SEQUENCEOF)
4179 {
4180 DWORD dataLen;
4181
4182 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4183 {
4184 DWORD bytesNeeded, cEntry = 0;
4185 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4186
4187 bytesNeeded = sizeof(CERT_ALT_NAME_INFO);
4188 if (dataLen)
4189 {
4190 const BYTE *ptr;
4191
4192 for (ptr = pbEncoded + 1 + lenBytes; ret &&
4193 ptr - pbEncoded - 1 - lenBytes < dataLen; )
4194 {
4195 DWORD size;
4196
4197 ret = CRYPT_AsnDecodeAltNameEntry(ptr,
4198 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
4199 if (ret)
4200 {
4201 DWORD nextLen;
4202
4203 cEntry++;
4204 bytesNeeded += size;
4205 ret = CRYPT_GetLen(ptr,
4206 cbEncoded - (ptr - pbEncoded), &nextLen);
4207 if (ret)
4208 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
4209 }
4210 }
4211 }
4212 if (ret)
4213 {
4214 if (!pvStructInfo)
4215 *pcbStructInfo = bytesNeeded;
4216 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4217 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4218 {
4219 CERT_ALT_NAME_INFO *info;
4220
4221 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4222 pvStructInfo = *(BYTE **)pvStructInfo;
4223 info = (CERT_ALT_NAME_INFO *)pvStructInfo;
4224 info->cAltEntry = 0;
4225 if (cEntry == 0)
4226 info->rgAltEntry = NULL;
4227 else
4228 {
4229 DWORD size, i;
4230 BYTE *nextData;
4231 const BYTE *ptr;
4232
4233 info->rgAltEntry =
4234 (CERT_ALT_NAME_ENTRY *)((BYTE *)pvStructInfo +
4235 sizeof(CERT_ALT_NAME_INFO));
4236 nextData = (BYTE *)info->rgAltEntry +
4237 cEntry * sizeof(CERT_ALT_NAME_ENTRY);
4238 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
4239 i < cEntry && ptr - pbEncoded - 1 - lenBytes <
4240 dataLen; i++)
4241 {
4242 info->rgAltEntry[i].u.pwszURL =
4243 (LPWSTR)nextData;
4244 size = bytesNeeded;
4245 ret = CRYPT_AsnDecodeAltNameEntry(ptr,
4246 cbEncoded - (ptr - pbEncoded), dwFlags,
4247 &info->rgAltEntry[i], &size);
4248 if (ret)
4249 {
4250 DWORD nextLen;
4251
4252 info->cAltEntry++;
4253 nextData += size -
4254 sizeof(CERT_ALT_NAME_ENTRY);
4255 bytesNeeded -= size;
4256 ret = CRYPT_GetLen(ptr,
4257 cbEncoded - (ptr - pbEncoded), &nextLen);
4258 if (ret)
4259 ptr += nextLen + 1 +
4260 GET_LEN_BYTES(ptr[1]);
4261 }
4262 }
4263 }
4264 }
4265 }
4266 }
4267 }
4268 else
4269 {
4270 SetLastError(CRYPT_E_ASN1_BADTAG);
4271 ret = FALSE;
4272 }
4273 }
4274 _SEH_EXCEPT(page_fault)
4275 {
4276 SetLastError(STATUS_ACCESS_VIOLATION);
4277 ret = FALSE;
4278 }
4279 _SEH_END
4280 return ret;
4281 }
4282
4283 struct PATH_LEN_CONSTRAINT
4284 {
4285 BOOL fPathLenConstraint;
4286 DWORD dwPathLenConstraint;
4287 };
4288
4289 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
4290 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4291 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4292 {
4293 BOOL ret = TRUE;
4294
4295 if (cbEncoded)
4296 {
4297 if (pbEncoded[0] == ASN_INTEGER)
4298 {
4299 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
4300
4301 if (!pvStructInfo)
4302 *pcbStructInfo = bytesNeeded;
4303 else if (*pcbStructInfo < bytesNeeded)
4304 {
4305 SetLastError(ERROR_MORE_DATA);
4306 *pcbStructInfo = bytesNeeded;
4307 ret = FALSE;
4308 }
4309 else
4310 {
4311 struct PATH_LEN_CONSTRAINT *constraint =
4312 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
4313 DWORD size = sizeof(constraint->dwPathLenConstraint);
4314
4315 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
4316 pbEncoded, cbEncoded, 0, NULL,
4317 &constraint->dwPathLenConstraint, &size);
4318 if (ret)
4319 constraint->fPathLenConstraint = TRUE;
4320 TRACE("got an int, dwPathLenConstraint is %ld\n",
4321 constraint->dwPathLenConstraint);
4322 }
4323 }
4324 else
4325 {
4326 SetLastError(CRYPT_E_ASN1_CORRUPT);
4327 ret = FALSE;
4328 }
4329 }
4330 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4331 return ret;
4332 }
4333
4334 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
4335 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4336 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4337 {
4338 BOOL ret;
4339
4340 _SEH_TRY
4341 {
4342 struct AsnDecodeSequenceItem items[] = {
4343 { offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA), CRYPT_AsnDecodeBool,
4344 sizeof(BOOL), TRUE, FALSE, 0, 0 },
4345 { offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fPathLenConstraint),
4346 CRYPT_AsnDecodePathLenConstraint, sizeof(struct PATH_LEN_CONSTRAINT),
4347 TRUE, FALSE, 0, 0 },
4348 };
4349
4350 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
4351 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
4352 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
4353 }
4354 _SEH_EXCEPT(page_fault)
4355 {
4356 SetLastError(STATUS_ACCESS_VIOLATION);
4357 ret = FALSE;
4358 }
4359 _SEH_END
4360 return ret;
4361 }
4362
4363 #define RSA1_MAGIC 0x31415352
4364
4365 struct DECODED_RSA_PUB_KEY
4366 {
4367 DWORD pubexp;
4368 CRYPT_INTEGER_BLOB modulus;
4369 };
4370
4371 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
4372 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4373 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4374 {
4375 BOOL ret;
4376
4377 _SEH_TRY
4378 {
4379 struct AsnDecodeSequenceItem items[] = {
4380 { offsetof(struct DECODED_RSA_PUB_KEY, modulus),
4381 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4382 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
4383 0 },
4384 { offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
4385 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4386 };
4387 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
4388 DWORD size = 0;
4389
4390 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
4391 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
4392 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
4393 if (ret)
4394 {
4395 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
4396 decodedKey->modulus.cbData;
4397
4398 if (!pvStructInfo)
4399 {
4400 *pcbStructInfo = bytesNeeded;
4401 ret = TRUE;
4402 }
4403 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4404 pvStructInfo, pcbStructInfo, bytesNeeded)))
4405 {
4406 BLOBHEADER *hdr;
4407 RSAPUBKEY *rsaPubKey;
4408
4409 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4410 pvStructInfo = *(BYTE **)pvStructInfo;
4411 hdr = (BLOBHEADER *)pvStructInfo;
4412 hdr->bType = PUBLICKEYBLOB;
4413 hdr->bVersion = CUR_BLOB_VERSION;
4414 hdr->reserved = 0;
4415 hdr->aiKeyAlg = CALG_RSA_KEYX;
4416 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
4417 sizeof(BLOBHEADER));
4418 rsaPubKey->magic = RSA1_MAGIC;
4419 rsaPubKey->pubexp = decodedKey->pubexp;
4420 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
4421 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
4422 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
4423 decodedKey->modulus.cbData);
4424 }
4425 LocalFree(decodedKey);
4426 }
4427 }
4428 _SEH_EXCEPT(page_fault)
4429 {
4430 SetLastError(STATUS_ACCESS_VIOLATION);
4431 ret = FALSE;
4432 }
4433 _SEH_END
4434 return ret;
4435 }
4436
4437 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
4438 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4439 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4440 {
4441 BOOL ret;
4442
4443 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
4444 pDecodePara, pvStructInfo, *pcbStructInfo);
4445
4446 if (pbEncoded[0] == ASN_OCTETSTRING)
4447 {
4448 DWORD bytesNeeded, dataLen;
4449
4450 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4451 {
4452 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4453 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
4454 else
4455 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
4456 if (!pvStructInfo)
4457 *pcbStructInfo = bytesNeeded;
4458 else if (*pcbStructInfo < bytesNeeded)
4459 {
4460 SetLastError(ERROR_MORE_DATA);
4461 *pcbStructInfo = bytesNeeded;
4462 ret = FALSE;
4463 }
4464 else
4465 {
4466 CRYPT_DATA_BLOB *blob;
4467 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4468
4469 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
4470 blob->cbData = dataLen;
4471 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4472 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
4473 else
4474 {
4475 assert(blob->pbData);
4476 if (blob->cbData)
4477 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
4478 blob->cbData);
4479 }
4480 }
4481 }
4482 }
4483 else
4484 {
4485 SetLastError(CRYPT_E_ASN1_BADTAG);
4486 ret = FALSE;
4487 }
4488 return ret;
4489 }
4490
4491 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
4492 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4493 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4494 {
4495 BOOL ret;
4496
4497 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
4498 pDecodePara, pvStructInfo, *pcbStructInfo);
4499
4500 _SEH_TRY
4501 {
4502 DWORD bytesNeeded;
4503
4504 if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
4505 lpszStructType, pbEncoded, cbEncoded,
4506 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
4507 {
4508 if (!pvStructInfo)
4509 *pcbStructInfo = bytesNeeded;
4510 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4511 pvStructInfo, pcbStructInfo, bytesNeeded)))
4512 {
4513 CRYPT_DATA_BLOB *blob;
4514
4515 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4516 pvStructInfo = *(BYTE **)pvStructInfo;
4517 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
4518 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
4519 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
4520 lpszStructType, pbEncoded, cbEncoded,
4521 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
4522 &bytesNeeded);
4523 }
4524 }
4525 else
4526 {
4527 SetLastError(CRYPT_E_ASN1_BADTAG);
4528 ret = FALSE;
4529 }
4530 }
4531 _SEH_EXCEPT(page_fault)
4532 {
4533 SetLastError(STATUS_ACCESS_VIOLATION);
4534 ret = FALSE;
4535 }
4536 _SEH_END
4537 return ret;
4538 }
4539
4540 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
4541 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4542 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4543 {
4544 BOOL ret;
4545
4546 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
4547 pDecodePara, pvStructInfo, *pcbStructInfo);
4548
4549 if (pbEncoded[0] == ASN_BITSTRING)
4550 {
4551 DWORD bytesNeeded, dataLen;
4552
4553 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4554 {
4555 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4556 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
4557 else
4558 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
4559 if (!pvStructInfo)
4560 *pcbStructInfo = bytesNeeded;
4561 else if (*pcbStructInfo < bytesNeeded)
4562 {
4563 *pcbStructInfo = bytesNeeded;
4564 SetLastError(ERROR_MORE_DATA);
4565 ret = FALSE;
4566 }
4567 else
4568 {
4569 CRYPT_BIT_BLOB *blob;
4570
4571 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
4572 blob->cbData = dataLen - 1;
4573 blob->cUnusedBits = *(pbEncoded + 1 +
4574 GET_LEN_BYTES(pbEncoded[1]));
4575 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4576 {
4577 blob->pbData = (BYTE *)pbEncoded + 2 +
4578 GET_LEN_BYTES(pbEncoded[1]);
4579 }
4580 else
4581 {
4582 assert(blob->pbData);
4583 if (blob->cbData)
4584 {
4585 BYTE mask = 0xff << blob->cUnusedBits;
4586
4587 memcpy(blob->pbData, pbEncoded + 2 +
4588 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
4589 blob->pbData[blob->cbData - 1] &= mask;
4590 }
4591 }
4592 }
4593 }
4594 }
4595 else
4596 {
4597 SetLastError(CRYPT_E_ASN1_BADTAG);
4598 ret = FALSE;
4599 }
4600 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4601 return ret;
4602 }
4603
4604 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
4605 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4606 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4607 {
4608 BOOL ret;
4609
4610 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
4611 pDecodePara, pvStructInfo, pcbStructInfo);
4612
4613 _SEH_TRY
4614 {
4615 DWORD bytesNeeded;
4616
4617 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
4618 lpszStructType, pbEncoded, cbEncoded,
4619 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
4620 {
4621 if (!pvStructInfo)
4622 *pcbStructInfo = bytesNeeded;
4623 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4624 pvStructInfo, pcbStructInfo, bytesNeeded)))
4625 {
4626 CRYPT_BIT_BLOB *blob;
4627
4628 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4629 pvStructInfo = *(BYTE **)pvStructInfo;
4630 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
4631 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
4632 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
4633 lpszStructType, pbEncoded, cbEncoded,
4634 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
4635 &bytesNeeded);
4636 }
4637 }
4638 }
4639 _SEH_EXCEPT(page_fault)
4640 {
4641 SetLastError(STATUS_ACCESS_VIOLATION);
4642 ret = FALSE;
4643 }
4644 _SEH_END
4645 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4646 return ret;
4647 }
4648
4649 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
4650 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4651 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4652 {
4653 BOOL ret;
4654
4655 if (!pvStructInfo)
4656 {
4657 *pcbStructInfo = sizeof(int);
4658 return TRUE;
4659 }
4660 _SEH_TRY
4661 {
4662 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
4663 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
4664 DWORD size = sizeof(buf);
4665
4666 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
4667 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
4668 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf, &size);
4669 if (ret)
4670 {
4671 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4672 pvStructInfo, pcbStructInfo, sizeof(int))))
4673 {
4674 int val, i;
4675
4676 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4677 pvStructInfo = *(BYTE **)pvStructInfo;
4678 if (blob->pbData[blob->cbData - 1] & 0x80)
4679 {
4680 /* initialize to a negative value to sign-extend */
4681 val = -1;
4682 }
4683 else
4684 val = 0;
4685 for (i = 0; i < blob->cbData; i++)
4686 {
4687 val <<= 8;
4688 val |= blob->pbData[blob->cbData - i - 1];
4689 }
4690 memcpy(pvStructInfo, &val, sizeof(int));
4691 }
4692 }
4693 else if (GetLastError() == ERROR_MORE_DATA)
4694 SetLastError(CRYPT_E_ASN1_LARGE);
4695 }
4696 _SEH_EXCEPT(page_fault)
4697 {
4698 SetLastError(STATUS_ACCESS_VIOLATION);
4699 ret = FALSE;
4700 }
4701 _SEH_END
4702 return ret;
4703 }
4704
4705 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
4706 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4707 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4708 {
4709 BOOL ret;
4710
4711 if (pbEncoded[0] == ASN_INTEGER)
4712 {
4713 DWORD bytesNeeded, dataLen;
4714
4715 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4716 {
4717 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4718
4719 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4720 if (!pvStructInfo)
4721 *pcbStructInfo = bytesNeeded;
4722 else if (*pcbStructInfo < bytesNeeded)
4723 {
4724 *pcbStructInfo = bytesNeeded;
4725 SetLastError(ERROR_MORE_DATA);
4726 ret = FALSE;
4727 }
4728 else
4729 {
4730 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
4731
4732 blob->cbData = dataLen;
4733 assert(blob->pbData);
4734 if (blob->cbData)
4735 {
4736 DWORD i;
4737
4738 for (i = 0; i < blob->cbData; i++)
4739 {
4740 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4741 dataLen - i - 1);
4742 }
4743 }
4744 }
4745 }
4746 }
4747 else
4748 {
4749 SetLastError(CRYPT_E_ASN1_BADTAG);
4750 ret = FALSE;
4751 }
4752 return ret;
4753 }
4754
4755 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4756 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4757 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4758 {
4759 BOOL ret;
4760
4761 _SEH_TRY
4762 {
4763 DWORD bytesNeeded;
4764
4765 if ((ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
4766 lpszStructType, pbEncoded, cbEncoded,
4767 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
4768 {
4769 if (!pvStructInfo)
4770 *pcbStructInfo = bytesNeeded;
4771 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4772 pvStructInfo, pcbStructInfo, bytesNeeded)))
4773 {
4774 CRYPT_INTEGER_BLOB *blob;
4775
4776 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4777 pvStructInfo = *(BYTE **)pvStructInfo;
4778 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
4779 blob->pbData = (BYTE *)pvStructInfo +
4780 sizeof(CRYPT_INTEGER_BLOB);
4781 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
4782 lpszStructType, pbEncoded, cbEncoded,
4783 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
4784 &bytesNeeded);
4785 }
4786 }
4787 }
4788 _SEH_EXCEPT(page_fault)
4789 {
4790 SetLastError(STATUS_ACCESS_VIOLATION);
4791 ret = FALSE;
4792 }
4793 _SEH_END
4794 return ret;
4795 }
4796
4797 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
4798 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
4799 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4800 void *pvStructInfo, DWORD *pcbStructInfo)
4801 {
4802 BOOL ret;
4803
4804 if (pbEncoded[0] == ASN_INTEGER)
4805 {
4806 DWORD bytesNeeded, dataLen;
4807
4808 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4809 {
4810 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4811
4812 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4813 if (!pvStructInfo)
4814 *pcbStructInfo = bytesNeeded;
4815 else if (*pcbStructInfo < bytesNeeded)
4816 {
4817 *pcbStructInfo = bytesNeeded;
4818 SetLastError(ERROR_MORE_DATA);
4819 ret = FALSE;
4820 }
4821 else
4822 {
4823 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
4824
4825 blob->cbData = dataLen;
4826 assert(blob->pbData);
4827 /* remove leading zero byte if it exists */
4828 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4829 {
4830 blob->cbData--;
4831 blob->pbData++;
4832 }
4833 if (blob->cbData)
4834 {
4835 DWORD i;
4836
4837 for (i = 0; i < blob->cbData; i++)
4838 {
4839 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4840 dataLen - i - 1);
4841 }
4842 }
4843 }
4844 }
4845 }
4846 else
4847 {
4848 SetLastError(CRYPT_E_ASN1_BADTAG);
4849 ret = FALSE;
4850 }
4851 return ret;
4852 }
4853
4854 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4855 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4856 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4857 {
4858 BOOL ret;
4859
4860 _SEH_TRY
4861 {
4862 DWORD bytesNeeded;
4863
4864 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
4865 lpszStructType, pbEncoded, cbEncoded,
4866 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
4867 {
4868 if (!pvStructInfo)
4869 *pcbStructInfo = bytesNeeded;
4870 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4871 pvStructInfo, pcbStructInfo, bytesNeeded)))
4872 {
4873 CRYPT_INTEGER_BLOB *blob;
4874
4875 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4876 pvStructInfo = *(BYTE **)pvStructInfo;
4877 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
4878 blob->pbData = (BYTE *)pvStructInfo +
4879 sizeof(CRYPT_INTEGER_BLOB);
4880 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
4881 lpszStructType, pbEncoded, cbEncoded,
4882 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
4883 &bytesNeeded);
4884 }
4885 }
4886 }
4887 _SEH_EXCEPT(page_fault)
4888 {
4889 SetLastError(STATUS_ACCESS_VIOLATION);
4890 ret = FALSE;
4891 }
4892 _SEH_END
4893 return ret;
4894 }
4895
4896 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4897 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4898 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4899 {
4900 BOOL ret;
4901
4902 if (!pvStructInfo)
4903 {
4904 *pcbStructInfo = sizeof(int);
4905 return TRUE;
4906 }
4907 _SEH_TRY
4908 {
4909 if (pbEncoded[0] == ASN_ENUMERATED)
4910 {
4911 unsigned int val = 0, i;
4912
4913 if (cbEncoded <= 1)
4914 {
4915 SetLastError(CRYPT_E_ASN1_EOD);
4916 ret = FALSE;
4917 }
4918 else if (pbEncoded[1] == 0)
4919 {
4920 SetLastError(CRYPT_E_ASN1_CORRUPT);
4921 ret = FALSE;
4922 }
4923 else
4924 {
4925 /* A little strange looking, but we have to accept a sign byte:
4926 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4927 * assuming a small length is okay here, it has to be in short
4928 * form.
4929 */
4930 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4931 {
4932 SetLastError(CRYPT_E_ASN1_LARGE);
4933 return FALSE;
4934 }
4935 for (i = 0; i < pbEncoded[1]; i++)
4936 {
4937 val <<= 8;
4938 val |= pbEncoded[2 + i];
4939 }
4940 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4941 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4942 {
4943 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4944 pvStructInfo = *(BYTE **)pvStructInfo;
4945 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4946 }
4947 }
4948 }
4949 else
4950 {
4951 SetLastError(CRYPT_E_ASN1_BADTAG);
4952 ret = FALSE;
4953 }
4954 }
4955 _SEH_EXCEPT(page_fault)
4956 {
4957 SetLastError(STATUS_ACCESS_VIOLATION);
4958 ret = FALSE;
4959 }
4960 _SEH_END
4961 return ret;
4962 }
4963
4964 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4965 * if it fails.
4966 */
4967 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4968 do { \
4969 BYTE i; \
4970 \
4971 (word) = 0; \
4972 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4973 { \
4974 if (!isdigit(*(pbEncoded))) \
4975 { \
4976 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4977 ret = FALSE; \
4978 } \
4979 else \
4980 { \
4981 (word) *= 10; \
4982 (word) += *(pbEncoded)++ - '0'; \
4983 } \
4984 } \
4985 } while (0)
4986
4987 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4988 SYSTEMTIME *sysTime)
4989 {
4990 BOOL ret;
4991
4992 _SEH_TRY
4993 {
4994 ret = TRUE;
4995 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4996 {
4997 WORD hours, minutes = 0;
4998 BYTE sign = *pbEncoded++;
4999
5000 len--;
5001 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
5002 if (ret && hours >= 24)
5003 {
5004 SetLastError(CRYPT_E_ASN1_CORRUPT);
5005 ret = FALSE;
5006 }
5007 else if (len >= 2)
5008 {
5009 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
5010 if (ret && minutes >= 60)
5011 {
5012 SetLastError(CRYPT_E_ASN1_CORRUPT);
5013 ret = FALSE;
5014 }
5015 }
5016 if (ret)
5017 {
5018 if (sign == '+')
5019 {
5020 sysTime->wHour += hours;
5021 sysTime->wMinute += minutes;
5022 }
5023 else
5024 {
5025 if (hours > sysTime->wHour)
5026 {
5027 sysTime->wDay--;
5028 sysTime->wHour = 24 - (hours - sysTime->wHour);
5029 }
5030 else
5031 sysTime->wHour -= hours;
5032 if (minutes > sysTime->wMinute)
5033 {
5034 sysTime->wHour--;
5035 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
5036 }
5037 else
5038 sysTime->wMinute -= minutes;
5039 }
5040 }
5041 }
5042 }
5043 _SEH_EXCEPT(page_fault)
5044 {
5045 SetLastError(STATUS_ACCESS_VIOLATION);
5046 ret = FALSE;
5047 }
5048 _SEH_END
5049 return ret;
5050 }
5051
5052 #define MIN_ENCODED_TIME_LENGTH 10
5053
5054 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
5055 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5056 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5057 {
5058 BOOL ret;
5059
5060 if (!pvStructInfo)
5061 {
5062 *pcbStructInfo = sizeof(FILETIME);
5063 return TRUE;
5064 }
5065 _SEH_TRY
5066 {
5067 ret = TRUE;
5068 if (pbEncoded[0] == ASN_UTCTIME)
5069 {
5070 if (cbEncoded <= 1)
5071 {
5072 SetLastError(CRYPT_E_ASN1_EOD);
5073 ret = FALSE;
5074 }
5075 else if (pbEncoded[1] > 0x7f)
5076 {
5077 /* long-form date strings really can't be valid */
5078 SetLastError(CRYPT_E_ASN1_CORRUPT);
5079 ret = FALSE;
5080 }
5081 else
5082 {
5083 SYSTEMTIME sysTime = { 0 };
5084 BYTE len = pbEncoded[1];
5085
5086 if (len < MIN_ENCODED_TIME_LENGTH)
5087 {
5088 SetLastError(CRYPT_E_ASN1_CORRUPT);
5089 ret = FALSE;
5090 }
5091 else
5092 {
5093 pbEncoded += 2;
5094 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
5095 if (sysTime.wYear >= 50)
5096 sysTime.wYear += 1900;
5097 else
5098 sysTime.wYear += 2000;
5099 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
5100 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
5101 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
5102 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
5103 if (ret && len > 0)
5104 {
5105 if (len >= 2 && isdigit(*pbEncoded) &&
5106 isdigit(*(pbEncoded + 1)))
5107 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5108 sysTime.wSecond);
5109 else if (isdigit(*pbEncoded))
5110 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
5111 sysTime.wSecond);
5112 if (ret)
5113 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
5114 &sysTime);
5115 }
5116 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
5117 pDecodePara, pvStructInfo, pcbStructInfo,
5118 sizeof(FILETIME))))
5119 {
5120 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5121 pvStructInfo = *(BYTE **)pvStructInfo;
5122 ret = SystemTimeToFileTime(&sysTime,
5123 (FILETIME *)pvStructInfo);
5124 }
5125 }
5126 }
5127 }
5128 else
5129 {
5130 SetLastError(CRYPT_E_ASN1_BADTAG);
5131 ret = FALSE;
5132 }
5133 }
5134 _SEH_EXCEPT(page_fault)
5135 {
5136 SetLastError(STATUS_ACCESS_VIOLATION);
5137 ret = FALSE;
5138 }
5139 _SEH_END
5140 return ret;
5141 }
5142
5143 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
5144 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5145 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5146 {
5147 BOOL ret;
5148
5149 if (!pvStructInfo)
5150 {
5151 *pcbStructInfo = sizeof(FILETIME);
5152 return TRUE;
5153 }
5154 _SEH_TRY
5155 {
5156 ret = TRUE;
5157 if (pbEncoded[0] == ASN_GENERALTIME)
5158 {
5159 if (cbEncoded <= 1)
5160 {
5161 SetLastError(CRYPT_E_ASN1_EOD);
5162 ret = FALSE;
5163 }
5164 else if (pbEncoded[1] > 0x7f)
5165 {
5166 /* long-form date strings really can't be valid */
5167 SetLastError(CRYPT_E_ASN1_CORRUPT);
5168 ret = FALSE;
5169 }
5170 else
5171 {
5172 BYTE len = pbEncoded[1];
5173
5174 if (len < MIN_ENCODED_TIME_LENGTH)
5175 {
5176 SetLastError(CRYPT_E_ASN1_CORRUPT);
5177 ret = FALSE;
5178 }
5179 else
5180 {
5181 SYSTEMTIME sysTime = { 0 };
5182
5183 pbEncoded += 2;
5184 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
5185 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
5186 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
5187 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
5188 if (ret && len > 0)
5189 {
5190 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5191 sysTime.wMinute);
5192 if (ret && len > 0)
5193 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5194 sysTime.wSecond);
5195 if (ret && len > 0 && (*pbEncoded == '.' ||
5196 *pbEncoded == ','))
5197 {
5198 BYTE digits;
5199
5200 pbEncoded++;
5201 len--;
5202 /* workaround macro weirdness */
5203 digits = min(len, 3);
5204 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
5205 sysTime.wMilliseconds);
5206 }
5207 if (ret)
5208 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
5209 &sysTime);
5210 }
5211 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
5212 pDecodePara, pvStructInfo, pcbStructInfo,
5213 sizeof(FILETIME))))
5214 {
5215 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5216 pvStructInfo = *(BYTE **)pvStructInfo;
5217 ret = SystemTimeToFileTime(&sysTime,
5218 (FILETIME *)pvStructInfo);
5219 }
5220 }
5221 }
5222 }
5223 else
5224 {
5225 SetLastError(CRYPT_E_ASN1_BADTAG);
5226 ret = FALSE;
5227 }
5228 }
5229 _SEH_EXCEPT(page_fault)
5230 {
5231 SetLastError(STATUS_ACCESS_VIOLATION);
5232 ret = FALSE;
5233 }
5234 _SEH_END
5235 return ret;
5236 }
5237
5238 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
5239 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5240 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5241 {
5242 BOOL ret;
5243
5244 _SEH_TRY
5245 {
5246 if (pbEncoded[0] == ASN_UTCTIME)
5247 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
5248 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5249 pcbStructInfo);
5250 else if (pbEncoded[0] == ASN_GENERALTIME)
5251 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
5252 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
5253 pvStructInfo, pcbStructInfo);
5254 else
5255 {
5256 SetLastError(CRYPT_E_ASN1_BADTAG);
5257 ret = FALSE;
5258 }
5259 }
5260 _SEH_EXCEPT(page_fault)
5261 {
5262 SetLastError(STATUS_ACCESS_VIOLATION);
5263 ret = FALSE;
5264 }
5265 _SEH_END
5266 return ret;
5267 }
5268
5269 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
5270 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5271 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5272 {
5273 BOOL ret = TRUE;
5274
5275 _SEH_TRY
5276 {
5277 if (pbEncoded[0] == ASN_SEQUENCEOF)
5278 {
5279 DWORD bytesNeeded, dataLen, remainingLen, cValue;
5280
5281 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
5282 {
5283 BYTE lenBytes;
5284 const BYTE *ptr;
5285
5286 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
5287 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
5288 cValue = 0;
5289 ptr = pbEncoded + 1 + lenBytes;
5290 remainingLen = dataLen;
5291 while (ret && remainingLen)
5292 {
5293 DWORD nextLen;
5294
5295 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5296 if (ret)
5297 {
5298 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5299
5300 remainingLen -= 1 + nextLenBytes + nextLen;
5301 ptr += 1 + nextLenBytes + nextLen;
5302 bytesNeeded += sizeof(CRYPT_DER_BLOB);
5303 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
5304 bytesNeeded += 1 + nextLenBytes + nextLen;
5305 cValue++;
5306 }
5307 }
5308 if (ret)
5309 {
5310 CRYPT_SEQUENCE_OF_ANY *seq;
5311 BYTE *nextPtr;
5312 DWORD i;
5313
5314 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5315 pvStructInfo, pcbStructInfo, bytesNeeded)))
5316 {
5317 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5318 pvStructInfo = *(BYTE **)pvStructInfo;
5319 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
5320 seq->cValue = cValue;
5321 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
5322 sizeof(*seq));
5323 nextPtr = (BYTE *)seq->rgValue +
5324 cValue * sizeof(CRYPT_DER_BLOB);
5325 ptr = pbEncoded + 1 + lenBytes;
5326 remainingLen = dataLen;
5327 i = 0;
5328 while (ret && remainingLen)
5329 {
5330 DWORD nextLen;
5331
5332 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5333 if (ret)
5334 {
5335 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5336
5337 seq->rgValue[i].cbData = 1 + nextLenBytes +
5338 nextLen;
5339 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
5340 seq->rgValue[i].pbData = (BYTE *)ptr;
5341 else
5342 {
5343 seq->rgValue[i].pbData = nextPtr;
5344 memcpy(nextPtr, ptr, 1 + nextLenBytes +
5345 nextLen);
5346 nextPtr += 1 + nextLenBytes + nextLen;
5347 }
5348 remainingLen -= 1 + nextLenBytes + nextLen;
5349 ptr += 1 + nextLenBytes + nextLen;
5350 i++;
5351 }
5352 }
5353 }
5354 }
5355 }
5356 }
5357 else
5358 {
5359 SetLastError(CRYPT_E_ASN1_BADTAG);
5360 return FALSE;
5361 }
5362 }
5363 _SEH_EXCEPT(page_fault)
5364 {
5365 SetLastError(STATUS_ACCESS_VIOLATION);
5366 ret = FALSE;
5367 }
5368 _SEH_END
5369 return ret;
5370 }
5371
5372 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5373 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5374 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5375 {
5376 BOOL ret = FALSE;
5377 HMODULE lib = NULL;
5378 CryptDecodeObjectExFunc decodeFunc = NULL;
5379
5380 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
5381 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5382 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5383
5384 if (!pvStructInfo && !pcbStructInfo)
5385 {
5386 SetLastError(ERROR_INVALID_PARAMETER);
5387 return FALSE;
5388 }
5389 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
5390 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
5391 {
5392 SetLastError(ERROR_FILE_NOT_FOUND);
5393 return FALSE;
5394 }
5395 if (!cbEncoded)
5396 {
5397 SetLastError(CRYPT_E_ASN1_EOD);
5398 return FALSE;
5399 }
5400 if (cbEncoded > MAX_ENCODED_LEN)
5401 {
5402 SetLastError(CRYPT_E_ASN1_LARGE);
5403 return FALSE;
5404 }
5405
5406 SetLastError(NOERROR);
5407 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
5408 *(BYTE **)pvStructInfo = NULL;
5409 if (!HIWORD(lpszStructType))
5410 {
5411 switch (LOWORD(lpszStructType))
5412 {
5413 case (WORD)X509_CERT:
5414 decodeFunc = CRYPT_AsnDecodeCert;
5415 break;
5416 case (WORD)X509_CERT_TO_BE_SIGNED:
5417 decodeFunc = CRYPT_AsnDecodeCertInfo;
5418 break;
5419 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
5420 decodeFunc = CRYPT_AsnDecodeCRLInfo;
5421 break;
5422 case (WORD)X509_EXTENSIONS:
5423 decodeFunc = CRYPT_AsnDecodeExtensions;
5424 break;
5425 case (WORD)X509_NAME:
5426 decodeFunc = CRYPT_AsnDecodeName;
5427 break;
5428 case (WORD)X509_PUBLIC_KEY_INFO:
5429 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
5430 break;
5431 case (WORD)X509_ALTERNATE_NAME:
5432 decodeFunc = CRYPT_AsnDecodeAltName;
5433 break;
5434 case (WORD)X509_BASIC_CONSTRAINTS2:
5435 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5436 break;
5437 case (WORD)RSA_CSP_PUBLICKEYBLOB:
5438 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
5439 break;
5440 case (WORD)X509_OCTET_STRING:
5441 decodeFunc = CRYPT_AsnDecodeOctets;
5442 break;
5443 case (WORD)X509_BITS:
5444 case (WORD)X509_KEY_USAGE:
5445 decodeFunc = CRYPT_AsnDecodeBits;
5446 break;
5447 case (WORD)X509_INTEGER:
5448 decodeFunc = CRYPT_AsnDecodeInt;
5449 break;
5450 case (WORD)X509_MULTI_BYTE_INTEGER:
5451 decodeFunc = CRYPT_AsnDecodeInteger;
5452 break;
5453 case (WORD)X509_MULTI_BYTE_UINT:
5454 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
5455 break;
5456 case (WORD)X509_ENUMERATED:
5457 decodeFunc = CRYPT_AsnDecodeEnumerated;
5458 break;
5459 case (WORD)X509_CHOICE_OF_TIME:
5460 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
5461 break;
5462 case (WORD)X509_SEQUENCE_OF_ANY:
5463 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
5464 break;
5465 case (WORD)PKCS_UTC_TIME:
5466 decodeFunc = CRYPT_AsnDecodeUtcTime;
5467 break;
5468 default:
5469 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
5470 }
5471 }
5472 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
5473 decodeFunc = CRYPT_AsnDecodeExtensions;
5474 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
5475 decodeFunc = CRYPT_AsnDecodeUtcTime;
5476 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
5477 decodeFunc = CRYPT_AsnDecodeEnumerated;
5478 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
5479 decodeFunc = CRYPT_AsnDecodeBits;
5480 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
5481 decodeFunc = CRYPT_AsnDecodeOctets;
5482 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
5483 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5484 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
5485 decodeFunc = CRYPT_AsnDecodeAltName;
5486 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
5487 decodeFunc = CRYPT_AsnDecodeAltName;
5488 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
5489 decodeFunc = CRYPT_AsnDecodeAltName;
5490 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
5491 decodeFunc = CRYPT_AsnDecodeAltName;
5492 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
5493 decodeFunc = CRYPT_AsnDecodeAltName;
5494 else
5495 TRACE("OID %s not found or unimplemented, looking for DLL\n",
5496 debugstr_a(lpszStructType));
5497 if (!decodeFunc)
5498 decodeFunc = (CryptDecodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType,
5499 lpszStructType, CRYPT_OID_DECODE_OBJECT_EX_FUNC, &lib);
5500 if (decodeFunc)
5501 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
5502 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5503 else
5504 SetLastError(ERROR_FILE_NOT_FOUND);
5505 if (lib)
5506 FreeLibrary(lib);
5507 return ret;
5508 }
5509
5510 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
5511 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5512 {
5513 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
5514 NULL, 0, NULL, pInfo, pcbInfo);
5515 }
5516
5517 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
5518 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
5519 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5520 {
5521 BOOL ret;
5522 HCRYPTKEY key;
5523
5524 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv, dwKeySpec,
5525 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
5526 pInfo, pcbInfo);
5527
5528 if (!pszPublicKeyObjId)
5529 pszPublicKeyObjId = szOID_RSA_RSA;
5530 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
5531 {
5532 DWORD keySize = 0;
5533
5534 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
5535 if (ret)
5536 {
5537 LPBYTE pubKey = CryptMemAlloc(keySize);
5538
5539 if (pubKey)
5540 {
5541 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
5542 &keySize);
5543 if (ret)
5544 {
5545 DWORD encodedLen = 0;
5546
5547 ret = CryptEncodeObject(dwCertEncodingType,
5548 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
5549 if (ret)
5550 {
5551 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
5552 strlen(pszPublicKeyObjId) + 1 + encodedLen;
5553
5554 if (!pInfo)
5555 *pcbInfo = sizeNeeded;
5556 else if (*pcbInfo < sizeNeeded)
5557 {
5558 SetLastError(ERROR_MORE_DATA);
5559 *pcbInfo = sizeNeeded;
5560 ret = FALSE;
5561 }
5562 else
5563 {
5564 pInfo->Algorithm.pszObjId = (char *)pInfo +
5565 sizeof(CERT_PUBLIC_KEY_INFO);
5566 lstrcpyA(pInfo->Algorithm.pszObjId,
5567 pszPublicKeyObjId);
5568 pInfo->Algorithm.Parameters.cbData = 0;
5569 pInfo->Algorithm.Parameters.pbData = NULL;
5570 pInfo->PublicKey.pbData =
5571 (BYTE *)pInfo->Algorithm.pszObjId
5572 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
5573 pInfo->PublicKey.cbData = encodedLen;
5574 pInfo->PublicKey.cUnusedBits = 0;
5575 ret = CryptEncodeObject(dwCertEncodingType,
5576 RSA_CSP_PUBLICKEYBLOB, pubKey,
5577 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
5578 }
5579 }
5580 }
5581 CryptMemFree(pubKey);
5582 }
5583 else
5584 ret = FALSE;
5585 }
5586 CryptDestroyKey(key);
5587 }
5588 return ret;
5589 }
5590
5591 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
5592 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
5593 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
5594
5595 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
5596 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
5597 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5598 {
5599 BOOL ret;
5600 ExportPublicKeyInfoExFunc exportFunc = NULL;
5601 HMODULE lib = NULL;
5602
5603 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv, dwKeySpec,
5604 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
5605 pInfo, pcbInfo);
5606
5607 if (!hCryptProv)
5608 {
5609 SetLastError(ERROR_INVALID_PARAMETER);
5610 return FALSE;
5611 }
5612
5613 if (pszPublicKeyObjId)
5614 exportFunc = CRYPT_GetFunc(dwCertEncodingType, pszPublicKeyObjId,
5615 CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC, &lib);
5616 if (!exportFunc)
5617 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
5618 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
5619 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
5620 if (lib)
5621 FreeLibrary(lib);
5622 return ret;
5623 }
5624
5625 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
5626 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
5627 {
5628 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
5629 0, 0, NULL, phKey);
5630 }
5631
5632 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
5633 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5634 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
5635 {
5636 BOOL ret;
5637 DWORD pubKeySize = 0;
5638
5639 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv,
5640 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
5641
5642 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
5643 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
5644 if (ret)
5645 {
5646 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
5647
5648 if (pubKey)
5649 {
5650 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
5651 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
5652 &pubKeySize);
5653 if (ret)
5654 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
5655 phKey);
5656 CryptMemFree(pubKey);
5657 }
5658 else
5659 ret = FALSE;
5660 }
5661 return ret;
5662 }
5663
5664 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
5665 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5666 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
5667
5668 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
5669 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5670 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
5671 {
5672 BOOL ret;
5673 ImportPublicKeyInfoExFunc importFunc = NULL;
5674 HMODULE lib = NULL;
5675
5676 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv,
5677 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
5678
5679 importFunc = CRYPT_GetFunc(dwCertEncodingType, pInfo->Algorithm.pszObjId,
5680 CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, &lib);
5681 if (!importFunc)
5682 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
5683 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
5684 pvAuxInfo, phKey);
5685 if (lib)
5686 FreeLibrary(lib);
5687 return ret;
5688 }