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