2 * Copyright 2002 Mike McCormack for CodeWeavers
3 * Copyright 2005 Juan Lang
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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.
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.)
29 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
32 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
39 #define NONAMELESSUNION
47 #include "wine/debug.h"
48 #include "wine/exception.h"
50 /* This is a bit arbitrary, but to set some limit: */
51 #define MAX_ENCODED_LEN 0x02000000
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_ENUMERATED (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0a)
57 #define ASN_SETOF (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x11)
58 #define ASN_NUMERICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x12)
59 #define ASN_PRINTABLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x13)
60 #define ASN_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16)
61 #define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17)
62 #define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18)
64 #define ASN_FLAGS_MASK 0xf0
65 #define ASN_TYPE_MASK 0x0f
67 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
69 static const WCHAR szDllName[] = { 'D','l','l',0 };
71 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
73 typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *,
74 DWORD, PCRYPT_ENCODE_PARA, BYTE *, DWORD *);
75 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
76 DWORD, DWORD, void *, DWORD *);
77 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
78 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
80 /* Prototypes for built-in encoders/decoders. They follow the Ex style
81 * prototypes. The dwCertEncodingType and lpszStructType are ignored by the
82 * built-in functions, but the parameters are retained to simplify
83 * CryptEncodeObjectEx/CryptDecodeObjectEx, since they must call functions in
84 * external DLLs that follow these signatures.
85 * FIXME: some built-in functions are suitable to be called directly by
86 * CryptEncodeObjectEx/CryptDecodeObjectEx (they implement exception handling
87 * and memory allocation if requested), others are only suitable to be called
88 * internally. Comment which are which.
90 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
93 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
94 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
95 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
96 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
97 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
98 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
99 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
100 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
101 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
102 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
103 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
104 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
105 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
106 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
107 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
108 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
109 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
110 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
111 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
112 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
113 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
114 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
115 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
116 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
117 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
118 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
119 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
120 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
121 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
122 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
124 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
125 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
126 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
127 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
128 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
129 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
130 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
131 * time, doesn't do memory allocation, and doesn't do exception handling.
132 * (This isn't intended to be the externally-called one.)
134 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
135 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
136 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
137 static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded,
138 DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId);
139 /* Assumes algo->Parameters.pbData is set ahead of time */
140 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
141 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
142 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
143 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
144 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
145 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
146 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
147 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
148 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
149 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
150 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
151 * member has been initialized, doesn't do exception handling, and doesn't do
154 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(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_AsnDecodeBits(DWORD dwCertEncodingType,
158 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
159 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
160 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
161 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
162 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
163 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
164 * member has been initialized, doesn't do exception handling, and doesn't do
167 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
168 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
169 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
170 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
171 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
172 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
173 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
174 void *pvStructInfo, DWORD *pcbStructInfo);
176 /* filter for page-fault exceptions */
177 static WINE_EXCEPTION_FILTER(page_fault)
179 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
180 return EXCEPTION_EXECUTE_HANDLER;
181 return EXCEPTION_CONTINUE_SEARCH;
184 static char *CRYPT_GetKeyName(DWORD dwEncodingType, LPCSTR pszFuncName,
187 static const char szEncodingTypeFmt[] =
188 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
190 char numericOID[7]; /* enough for "#65535" */
194 /* MSDN says the encoding type is a mask, but it isn't treated that way.
195 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
196 * "EncodingType 2" would be expected if it were a mask. Instead native
197 * stores values in "EncodingType 3".
201 snprintf(numericOID, sizeof(numericOID), "#%d", LOWORD(pszOID));
207 /* This is enough: the lengths of the two string parameters are explicitly
208 * counted, and we need up to five additional characters for the encoding
209 * type. These are covered by the "%d", "%s", and "%s" characters in the
210 * format specifier that are removed by sprintf.
212 len = sizeof(szEncodingTypeFmt) + lstrlenA(pszFuncName) + lstrlenA(oid);
213 szKey = CryptMemAlloc(len);
215 sprintf(szKey, szEncodingTypeFmt, dwEncodingType, pszFuncName, oid);
219 BOOL WINAPI CryptRegisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
220 LPCSTR pszOID, LPCWSTR pwszDll, LPCSTR pszOverrideFuncName)
226 TRACE("%lx %s %s %s %s\n", dwEncodingType, pszFuncName, pszOID,
227 debugstr_w(pwszDll), pszOverrideFuncName);
229 /* This only registers functions for encoding certs, not messages */
230 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
233 /* Native does nothing pwszDll is NULL */
237 /* I'm not matching MS bug for bug here, because I doubt any app depends on
239 * - native "succeeds" if pszFuncName is NULL, but the nonsensical entry
240 * it creates would never be used
241 * - native returns an HRESULT rather than a Win32 error if pszOID is NULL.
242 * Instead I disallow both of these with ERROR_INVALID_PARAMETER.
244 if (!pszFuncName || !pszOID)
246 SetLastError(ERROR_INVALID_PARAMETER);
250 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
251 TRACE("Key name is %s\n", debugstr_a(szKey));
256 r = RegCreateKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
258 if(r != ERROR_SUCCESS)
261 /* write the values */
262 if (pszOverrideFuncName)
263 RegSetValueExA(hKey, "FuncName", 0, REG_SZ, (const BYTE*)pszOverrideFuncName,
264 lstrlenA(pszOverrideFuncName) + 1);
265 RegSetValueExW(hKey, szDllName, 0, REG_SZ, (const BYTE*) pwszDll,
266 (lstrlenW(pwszDll) + 1) * sizeof (WCHAR));
272 BOOL WINAPI CryptUnregisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
278 TRACE("%lx %s %s\n", dwEncodingType, pszFuncName, pszOID);
280 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
283 if (!pszFuncName || !pszOID)
285 SetLastError(ERROR_INVALID_PARAMETER);
289 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
290 rc = RegDeleteKeyA(HKEY_LOCAL_MACHINE, szKey);
294 return rc ? FALSE : TRUE;
297 BOOL WINAPI CryptGetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
298 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD *pdwValueType, BYTE *pbValueData,
305 TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType, debugstr_a(pszFuncName),
306 debugstr_a(pszOID), debugstr_w(pwszValueName), pdwValueType, pbValueData,
309 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
312 if (!pszFuncName || !pszOID || !pwszValueName)
314 SetLastError(ERROR_INVALID_PARAMETER);
318 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
319 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
325 rc = RegQueryValueExW(hKey, pwszValueName, NULL, pdwValueType,
326 pbValueData, pcbValueData);
331 return rc ? FALSE : TRUE;
334 BOOL WINAPI CryptSetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
335 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD dwValueType,
336 const BYTE *pbValueData, DWORD cbValueData)
342 TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType, debugstr_a(pszFuncName),
343 debugstr_a(pszOID), debugstr_w(pwszValueName), dwValueType, pbValueData,
346 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
349 if (!pszFuncName || !pszOID || !pwszValueName)
351 SetLastError(ERROR_INVALID_PARAMETER);
355 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
356 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
362 rc = RegSetValueExW(hKey, pwszValueName, 0, dwValueType, pbValueData,
368 return rc ? FALSE : TRUE;
371 /* Gets the registered function named szFuncName for dwCertEncodingType and
372 * lpszStructType, or NULL if one could not be found. *lib will be set to the
373 * handle of the module it's in, or NULL if no module was loaded. If the
374 * return value is NULL, *lib will also be NULL, to simplify error handling.
376 static void *CRYPT_GetFunc(DWORD dwCertEncodingType, LPCSTR lpszStructType,
377 LPCSTR szFuncName, HMODULE *lib)
380 char *szKey = CRYPT_GetKeyName(dwCertEncodingType, szFuncName,
382 const char *funcName;
385 DWORD type, size = 0;
387 TRACE("(%08lx %s %s %p)\n", dwCertEncodingType, debugstr_a(lpszStructType),
388 debugstr_a(szFuncName), lib);
391 r = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
393 if(r != ERROR_SUCCESS)
396 RegQueryValueExA(hKey, "FuncName", NULL, &type, NULL, &size);
397 if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ)
399 funcName = CryptMemAlloc(size);
400 RegQueryValueExA(hKey, "FuncName", NULL, &type, (LPBYTE)funcName,
404 funcName = szFuncName;
405 RegQueryValueExW(hKey, szDllName, NULL, &type, NULL, &size);
406 if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ)
408 LPWSTR dllName = CryptMemAlloc(size);
410 RegQueryValueExW(hKey, szDllName, NULL, &type, (LPBYTE)dllName,
412 *lib = LoadLibraryW(dllName);
415 ret = GetProcAddress(*lib, funcName);
418 /* Unload the library, the caller doesn't want to unload it
419 * when the return value is NULL.
425 CryptMemFree(dllName);
427 if (funcName != szFuncName)
428 CryptMemFree((char *)funcName);
429 TRACE("returning %p\n", ret);
433 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
434 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
438 CryptEncodeObjectFunc pCryptEncodeObject;
440 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType,
441 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
444 if (!pbEncoded && !pcbEncoded)
446 SetLastError(ERROR_INVALID_PARAMETER);
450 /* Try registered DLL first.. */
452 (CryptEncodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType,
453 lpszStructType, CRYPT_OID_ENCODE_OBJECT_FUNC, &lib);
454 if (pCryptEncodeObject)
456 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
457 pvStructInfo, pbEncoded, pcbEncoded);
462 /* If not, use CryptEncodeObjectEx */
463 ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
464 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
469 /* Helper function to check *pcbEncoded, set it to the required size, and
470 * optionally to allocate memory. Assumes pbEncoded is not NULL.
471 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
472 * pointer to the newly allocated memory.
474 static BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags,
475 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded,
480 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
482 if (pEncodePara && pEncodePara->pfnAlloc)
483 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
485 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
486 if (!*(BYTE **)pbEncoded)
489 *pcbEncoded = bytesNeeded;
491 else if (bytesNeeded > *pcbEncoded)
493 *pcbEncoded = bytesNeeded;
494 SetLastError(ERROR_MORE_DATA);
500 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
502 DWORD bytesNeeded, significantBytes = 0;
510 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
511 temp <<= 8, significantBytes--)
513 bytesNeeded = significantBytes + 1;
517 *pcbEncoded = bytesNeeded;
520 if (*pcbEncoded < bytesNeeded)
522 SetLastError(ERROR_MORE_DATA);
526 *pbEncoded = (BYTE)len;
531 *pbEncoded++ = significantBytes | 0x80;
532 for (i = 0; i < significantBytes; i++)
534 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
538 *pcbEncoded = bytesNeeded;
542 struct AsnEncodeSequenceItem
544 const void *pvStructInfo;
545 CryptEncodeObjectExFunc encodeFunc;
546 DWORD size; /* used during encoding, not for your use */
549 static BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
550 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
551 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
554 DWORD i, dataLen = 0;
556 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items, cItem, dwFlags, pEncodePara,
557 pbEncoded, *pcbEncoded);
558 for (i = 0, ret = TRUE; ret && i < cItem; i++)
560 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
561 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
562 NULL, &items[i].size);
563 dataLen += items[i].size;
567 DWORD lenBytes, bytesNeeded;
569 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
570 bytesNeeded = 1 + lenBytes + dataLen;
572 *pcbEncoded = bytesNeeded;
575 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
576 pcbEncoded, bytesNeeded)))
578 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
579 pbEncoded = *(BYTE **)pbEncoded;
580 *pbEncoded++ = ASN_SEQUENCE;
581 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
582 pbEncoded += lenBytes;
583 for (i = 0; ret && i < cItem; i++)
585 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
586 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
587 NULL, pbEncoded, &items[i].size);
588 pbEncoded += items[i].size;
593 TRACE("returning %d (%08lx)\n", ret, GetLastError());
597 struct AsnConstructedItem
600 const void *pvStructInfo;
601 CryptEncodeObjectExFunc encodeFunc;
604 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
605 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
606 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
609 const struct AsnConstructedItem *item =
610 (const struct AsnConstructedItem *)pvStructInfo;
613 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
614 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
616 DWORD dataLen, bytesNeeded;
618 CRYPT_EncodeLen(len, NULL, &dataLen);
619 bytesNeeded = 1 + dataLen + len;
621 *pcbEncoded = bytesNeeded;
622 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
623 pbEncoded, pcbEncoded, bytesNeeded)))
625 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
626 pbEncoded = *(BYTE **)pbEncoded;
627 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
628 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
629 pbEncoded += dataLen;
630 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
631 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
638 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
639 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
640 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
642 const DWORD *ver = (const DWORD *)pvStructInfo;
645 /* CERT_V1 is not encoded */
653 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
655 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
656 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
661 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
662 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
663 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
665 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
670 *pcbEncoded = blob->cbData;
673 else if (*pcbEncoded < blob->cbData)
675 *pcbEncoded = blob->cbData;
676 SetLastError(ERROR_MORE_DATA);
682 memcpy(pbEncoded, blob->pbData, blob->cbData);
683 *pcbEncoded = blob->cbData;
689 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
690 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
691 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
694 /* This has two filetimes in a row, a NotBefore and a NotAfter */
695 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
696 struct AsnEncodeSequenceItem items[] = {
697 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
698 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
701 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
702 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
707 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(
708 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
709 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
712 const CRYPT_ALGORITHM_IDENTIFIER *algo =
713 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
715 struct AsnEncodeSequenceItem items[] = {
716 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
717 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
720 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
721 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
726 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
727 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
728 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
734 const CERT_PUBLIC_KEY_INFO *info =
735 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
736 struct AsnEncodeSequenceItem items[] = {
737 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
738 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
741 TRACE("Encoding public key with OID %s\n",
742 debugstr_a(info->Algorithm.pszObjId));
743 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
744 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
749 SetLastError(STATUS_ACCESS_VIOLATION);
756 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
757 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
758 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
764 const CERT_SIGNED_CONTENT_INFO *info =
765 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
766 struct AsnEncodeSequenceItem items[] = {
767 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
768 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
769 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
772 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
773 items[2].encodeFunc = CRYPT_AsnEncodeBits;
774 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
775 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
780 SetLastError(STATUS_ACCESS_VIOLATION);
787 /* Like in Windows, this blithely ignores the validity of the passed-in
788 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
789 * decode properly, see CRYPT_AsnDecodeCertInfo.
791 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
792 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
793 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
799 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
800 struct AsnEncodeSequenceItem items[10] = {
801 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
802 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
803 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
804 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
805 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
806 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
807 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
810 struct AsnConstructedItem constructed[3] = { { 0 } };
811 DWORD cItem = 7, cConstructed = 0;
813 if (info->IssuerUniqueId.cbData)
815 constructed[cConstructed].tag = 1;
816 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
817 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
818 items[cItem].pvStructInfo = &constructed[cConstructed];
819 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
823 if (info->SubjectUniqueId.cbData)
825 constructed[cConstructed].tag = 2;
826 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
827 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
828 items[cItem].pvStructInfo = &constructed[cConstructed];
829 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
833 if (info->cExtension)
835 constructed[cConstructed].tag = 3;
836 constructed[cConstructed].pvStructInfo = &info->cExtension;
837 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
838 items[cItem].pvStructInfo = &constructed[cConstructed];
839 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
844 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
845 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
849 SetLastError(STATUS_ACCESS_VIOLATION);
856 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
857 BYTE *pbEncoded, DWORD *pcbEncoded)
859 struct AsnEncodeSequenceItem items[3] = {
860 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
861 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
867 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
869 if (entry->cExtension)
871 items[cItem].pvStructInfo = &entry->cExtension;
872 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
876 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
877 pbEncoded, pcbEncoded);
879 TRACE("returning %d (%08lx)\n", ret, GetLastError());
883 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
884 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
885 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
887 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
888 DWORD bytesNeeded, dataLen, lenBytes, i;
889 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY **)
890 ((const BYTE *)pvStructInfo + sizeof(DWORD));
893 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
897 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
901 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
902 bytesNeeded = 1 + lenBytes + dataLen;
904 *pcbEncoded = bytesNeeded;
907 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
908 pcbEncoded, bytesNeeded)))
910 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
911 pbEncoded = *(BYTE **)pbEncoded;
912 *pbEncoded++ = ASN_SEQUENCEOF;
913 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
914 pbEncoded += lenBytes;
915 for (i = 0; i < cCRLEntry; i++)
917 DWORD size = dataLen;
919 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
928 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
929 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
930 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
932 const DWORD *ver = (const DWORD *)pvStructInfo;
935 /* CRL_V1 is not encoded */
942 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
943 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
947 /* Like in Windows, this blithely ignores the validity of the passed-in
948 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
949 * decode properly, see CRYPT_AsnDecodeCRLInfo.
951 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
952 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
953 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
959 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
960 struct AsnEncodeSequenceItem items[7] = {
961 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
962 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
963 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
964 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
969 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
971 items[cItem].pvStructInfo = &info->NextUpdate;
972 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
977 items[cItem].pvStructInfo = &info->cCRLEntry;
978 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
981 if (info->cExtension)
983 items[cItem].pvStructInfo = &info->cExtension;
984 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
988 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
989 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
993 SetLastError(STATUS_ACCESS_VIOLATION);
1000 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
1004 struct AsnEncodeSequenceItem items[3] = {
1005 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
1011 TRACE("%p, %p, %ld\n", ext, pbEncoded, *pcbEncoded);
1015 items[cItem].pvStructInfo = &ext->fCritical;
1016 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
1019 items[cItem].pvStructInfo = &ext->Value;
1020 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1023 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
1024 pbEncoded, pcbEncoded);
1025 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1029 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
1030 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1031 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1037 DWORD bytesNeeded, dataLen, lenBytes, i;
1038 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
1041 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
1045 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
1049 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1050 bytesNeeded = 1 + lenBytes + dataLen;
1052 *pcbEncoded = bytesNeeded;
1055 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1056 pcbEncoded, bytesNeeded)))
1058 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1059 pbEncoded = *(BYTE **)pbEncoded;
1060 *pbEncoded++ = ASN_SEQUENCEOF;
1061 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1062 pbEncoded += lenBytes;
1063 for (i = 0; i < exts->cExtension; i++)
1065 DWORD size = dataLen;
1067 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
1075 __EXCEPT(page_fault)
1077 SetLastError(STATUS_ACCESS_VIOLATION);
1084 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
1085 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1086 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1088 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
1089 DWORD bytesNeeded = 0, lenBytes;
1094 TRACE("%s\n", debugstr_a(pszObjId));
1101 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
1103 SetLastError(CRYPT_E_ASN1_ERROR);
1107 firstByte = val1 * 40 + val2;
1108 ptr = pszObjId + firstPos;
1113 /* note I assume each component is at most 32-bits long in base 2 */
1114 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
1116 if (val1 >= 0x10000000)
1118 else if (val1 >= 0x200000)
1120 else if (val1 >= 0x4000)
1122 else if (val1 >= 0x80)
1132 SetLastError(CRYPT_E_ASN1_ERROR);
1136 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1140 bytesNeeded += 1 + lenBytes;
1143 if (*pcbEncoded < bytesNeeded)
1145 SetLastError(ERROR_MORE_DATA);
1150 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
1151 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
1152 pbEncoded += lenBytes;
1158 *pbEncoded++ = firstByte;
1159 ptr = pszObjId + firstPos;
1162 sscanf(ptr, "%d%n", &val, &pos);
1164 unsigned char outBytes[5];
1167 if (val >= 0x10000000)
1169 else if (val >= 0x200000)
1171 else if (val >= 0x4000)
1173 else if (val >= 0x80)
1177 for (i = numBytes; i > 0; i--)
1179 outBytes[i - 1] = val & 0x7f;
1182 for (i = 0; i < numBytes - 1; i++)
1183 *pbEncoded++ = outBytes[i] | 0x80;
1184 *pbEncoded++ = outBytes[i];
1193 *pcbEncoded = bytesNeeded;
1197 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1198 CERT_NAME_VALUE *value, BYTE *pbEncoded, DWORD *pcbEncoded)
1201 DWORD bytesNeeded, lenBytes, encodedLen;
1204 switch (value->dwValueType)
1206 case CERT_RDN_NUMERIC_STRING:
1207 tag = ASN_NUMERICSTRING;
1208 encodedLen = value->Value.cbData;
1210 case CERT_RDN_PRINTABLE_STRING:
1211 tag = ASN_PRINTABLESTRING;
1212 encodedLen = value->Value.cbData;
1214 case CERT_RDN_IA5_STRING:
1215 tag = ASN_IA5STRING;
1216 encodedLen = value->Value.cbData;
1218 case CERT_RDN_ANY_TYPE:
1219 /* explicitly disallowed */
1220 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1223 FIXME("String type %ld unimplemented\n", value->dwValueType);
1226 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1227 bytesNeeded = 1 + lenBytes + encodedLen;
1230 if (*pcbEncoded < bytesNeeded)
1232 SetLastError(ERROR_MORE_DATA);
1238 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1239 pbEncoded += lenBytes;
1240 switch (value->dwValueType)
1242 case CERT_RDN_NUMERIC_STRING:
1243 case CERT_RDN_PRINTABLE_STRING:
1244 case CERT_RDN_IA5_STRING:
1245 memcpy(pbEncoded, value->Value.pbData, value->Value.cbData);
1249 *pcbEncoded = bytesNeeded;
1253 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1254 CERT_RDN_ATTR *attr, BYTE *pbEncoded, DWORD *pcbEncoded)
1256 DWORD bytesNeeded = 0, lenBytes, size;
1259 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1260 0, NULL, NULL, &size);
1263 bytesNeeded += size;
1264 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1265 * with dwValueType, so "cast" it to get its encoded size
1267 ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType,
1268 (CERT_NAME_VALUE *)&attr->dwValueType, NULL, &size);
1271 bytesNeeded += size;
1272 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1273 bytesNeeded += 1 + lenBytes;
1276 if (*pcbEncoded < bytesNeeded)
1278 SetLastError(ERROR_MORE_DATA);
1283 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SEQUENCE;
1284 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1286 pbEncoded += lenBytes;
1287 size = bytesNeeded - 1 - lenBytes;
1288 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1289 attr->pszObjId, 0, NULL, pbEncoded, &size);
1293 size = bytesNeeded - 1 - lenBytes - size;
1294 ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType,
1295 (CERT_NAME_VALUE *)&attr->dwValueType, pbEncoded,
1300 *pcbEncoded = bytesNeeded;
1306 static int BLOBComp(const void *l, const void *r)
1308 CRYPT_DER_BLOB *a = (CRYPT_DER_BLOB *)l, *b = (CRYPT_DER_BLOB *)r;
1311 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1312 ret = a->cbData - b->cbData;
1316 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1318 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1319 BYTE *pbEncoded, DWORD *pcbEncoded)
1322 CRYPT_DER_BLOB *blobs = NULL;
1326 DWORD bytesNeeded = 0, lenBytes, i;
1332 blobs = CryptMemAlloc(rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
1336 memset(blobs, 0, rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
1338 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1340 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1341 NULL, &blobs[i].cbData);
1343 bytesNeeded += blobs[i].cbData;
1347 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1348 bytesNeeded += 1 + lenBytes;
1351 if (*pcbEncoded < bytesNeeded)
1353 SetLastError(ERROR_MORE_DATA);
1358 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1360 blobs[i].pbData = CryptMemAlloc(blobs[i].cbData);
1361 if (!blobs[i].pbData)
1364 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1365 &rdn->rgRDNAttr[i], blobs[i].pbData,
1370 qsort(blobs, rdn->cRDNAttr, sizeof(CRYPT_DER_BLOB),
1372 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1373 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1375 pbEncoded += lenBytes;
1376 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1378 memcpy(pbEncoded, blobs[i].pbData, blobs[i].cbData);
1379 pbEncoded += blobs[i].cbData;
1384 *pcbEncoded = bytesNeeded;
1388 for (i = 0; i < rdn->cRDNAttr; i++)
1389 CryptMemFree(blobs[i].pbData);
1392 __EXCEPT(page_fault)
1394 SetLastError(STATUS_ACCESS_VIOLATION);
1398 CryptMemFree(blobs);
1402 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1403 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1404 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1410 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1411 DWORD bytesNeeded = 0, lenBytes, size, i;
1413 TRACE("encoding name with %ld RDNs\n", info->cRDN);
1415 for (i = 0; ret && i < info->cRDN; i++)
1417 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], NULL,
1420 bytesNeeded += size;
1422 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1423 bytesNeeded += 1 + lenBytes;
1427 *pcbEncoded = bytesNeeded;
1430 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1431 pbEncoded, pcbEncoded, bytesNeeded)))
1433 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1434 pbEncoded = *(BYTE **)pbEncoded;
1435 *pbEncoded++ = ASN_SEQUENCEOF;
1436 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1438 pbEncoded += lenBytes;
1439 for (i = 0; ret && i < info->cRDN; i++)
1442 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1443 &info->rgRDN[i], pbEncoded, &size);
1447 bytesNeeded -= size;
1454 __EXCEPT(page_fault)
1456 SetLastError(STATUS_ACCESS_VIOLATION);
1463 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1464 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1465 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1467 BOOL val = *(const BOOL *)pvStructInfo, ret;
1476 else if (*pcbEncoded < 3)
1479 SetLastError(ERROR_MORE_DATA);
1485 *pbEncoded++ = ASN_BOOL;
1487 *pbEncoded++ = val ? 0xff : 0;
1490 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1494 static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry,
1495 BYTE *pbEncoded, DWORD *pcbEncoded)
1501 switch (entry->dwAltNameChoice)
1503 case CERT_ALT_NAME_RFC822_NAME:
1504 case CERT_ALT_NAME_DNS_NAME:
1505 case CERT_ALT_NAME_URL:
1506 if (entry->u.pwszURL)
1510 /* Not + 1: don't encode the NULL-terminator */
1511 dataLen = lstrlenW(entry->u.pwszURL);
1512 for (i = 0; ret && i < dataLen; i++)
1514 if (entry->u.pwszURL[i] > 0x7f)
1516 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1525 case CERT_ALT_NAME_IP_ADDRESS:
1526 dataLen = entry->u.IPAddress.cbData;
1528 case CERT_ALT_NAME_REGISTERED_ID:
1529 /* FIXME: encode OID */
1530 case CERT_ALT_NAME_OTHER_NAME:
1531 case CERT_ALT_NAME_DIRECTORY_NAME:
1532 FIXME("name type %ld unimplemented\n", entry->dwAltNameChoice);
1535 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1540 DWORD bytesNeeded, lenBytes;
1542 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1543 bytesNeeded = 1 + dataLen + lenBytes;
1545 *pcbEncoded = bytesNeeded;
1546 else if (*pcbEncoded < bytesNeeded)
1548 SetLastError(ERROR_MORE_DATA);
1549 *pcbEncoded = bytesNeeded;
1554 *pbEncoded++ = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1555 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1556 pbEncoded += lenBytes;
1557 switch (entry->dwAltNameChoice)
1559 case CERT_ALT_NAME_RFC822_NAME:
1560 case CERT_ALT_NAME_DNS_NAME:
1561 case CERT_ALT_NAME_URL:
1565 for (i = 0; i < dataLen; i++)
1566 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
1569 case CERT_ALT_NAME_IP_ADDRESS:
1570 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
1574 *pcbEncoded = bytesNeeded;
1577 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1581 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
1582 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1583 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1589 const CERT_ALT_NAME_INFO *info =
1590 (const CERT_ALT_NAME_INFO *)pvStructInfo;
1592 DWORD bytesNeeded, dataLen, lenBytes, i;
1595 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1596 * can't encode an erroneous entry index if it's bigger than this.
1598 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
1602 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], NULL,
1606 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
1608 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1609 * the bad character, now set the index of the bad
1612 *pcbEncoded = (BYTE)i <<
1613 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
1618 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1619 bytesNeeded = 1 + lenBytes + dataLen;
1622 *pcbEncoded = bytesNeeded;
1627 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1628 pbEncoded, pcbEncoded, bytesNeeded)))
1630 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1631 pbEncoded = *(BYTE **)pbEncoded;
1632 *pbEncoded++ = ASN_SEQUENCEOF;
1633 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1634 pbEncoded += lenBytes;
1635 for (i = 0; ret && i < info->cAltEntry; i++)
1637 DWORD len = dataLen;
1639 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i],
1651 __EXCEPT(page_fault)
1653 SetLastError(STATUS_ACCESS_VIOLATION);
1660 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
1661 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1662 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1668 const CERT_BASIC_CONSTRAINTS2_INFO *info =
1669 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
1670 struct AsnEncodeSequenceItem items[2] = { { 0 } };
1675 items[cItem].pvStructInfo = &info->fCA;
1676 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
1679 if (info->fPathLenConstraint)
1681 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
1682 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
1685 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1686 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1688 __EXCEPT(page_fault)
1690 SetLastError(STATUS_ACCESS_VIOLATION);
1697 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
1698 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1699 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1705 const BLOBHEADER *hdr =
1706 (const BLOBHEADER *)pvStructInfo;
1708 if (hdr->bType != PUBLICKEYBLOB)
1710 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1715 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
1716 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
1717 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
1718 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
1719 struct AsnEncodeSequenceItem items[] = {
1720 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
1721 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
1724 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1725 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1729 __EXCEPT(page_fault)
1731 SetLastError(STATUS_ACCESS_VIOLATION);
1738 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
1739 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1740 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1746 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
1747 DWORD bytesNeeded, lenBytes;
1749 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob->cbData, blob->pbData,
1750 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
1752 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
1753 bytesNeeded = 1 + lenBytes + blob->cbData;
1756 *pcbEncoded = bytesNeeded;
1761 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1762 pcbEncoded, bytesNeeded)))
1764 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1765 pbEncoded = *(BYTE **)pbEncoded;
1766 *pbEncoded++ = ASN_OCTETSTRING;
1767 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
1768 pbEncoded += lenBytes;
1770 memcpy(pbEncoded, blob->pbData, blob->cbData);
1774 __EXCEPT(page_fault)
1776 SetLastError(STATUS_ACCESS_VIOLATION);
1780 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1784 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
1785 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1786 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1792 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
1793 DWORD bytesNeeded, lenBytes, dataBytes;
1796 /* yep, MS allows cUnusedBits to be >= 8 */
1797 if (!blob->cUnusedBits)
1799 dataBytes = blob->cbData;
1802 else if (blob->cbData * 8 > blob->cUnusedBits)
1804 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
1805 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
1813 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
1814 bytesNeeded = 1 + lenBytes + dataBytes + 1;
1817 *pcbEncoded = bytesNeeded;
1822 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1823 pcbEncoded, bytesNeeded)))
1825 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1826 pbEncoded = *(BYTE **)pbEncoded;
1827 *pbEncoded++ = ASN_BITSTRING;
1828 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
1829 pbEncoded += lenBytes;
1830 *pbEncoded++ = unusedBits;
1833 BYTE mask = 0xff << unusedBits;
1837 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
1838 pbEncoded += dataBytes - 1;
1840 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
1845 __EXCEPT(page_fault)
1847 SetLastError(STATUS_ACCESS_VIOLATION);
1854 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
1855 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1856 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1862 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
1863 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
1868 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
1873 for (i = 0; i < newBlob.cbData; i++)
1874 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
1880 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
1881 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1882 CryptMemFree(newBlob.pbData);
1884 __EXCEPT(page_fault)
1886 SetLastError(STATUS_ACCESS_VIOLATION);
1893 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
1894 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1895 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1897 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
1899 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
1900 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1903 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
1904 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1905 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1911 DWORD significantBytes, lenBytes;
1912 BYTE padByte = 0, bytesNeeded;
1914 const CRYPT_INTEGER_BLOB *blob =
1915 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
1917 significantBytes = blob->cbData;
1918 if (significantBytes)
1920 if (blob->pbData[significantBytes - 1] & 0x80)
1922 /* negative, lop off leading (little-endian) 0xffs */
1923 for (; significantBytes > 0 &&
1924 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
1926 if (blob->pbData[significantBytes - 1] < 0x80)
1934 /* positive, lop off leading (little-endian) zeroes */
1935 for (; significantBytes > 0 &&
1936 !blob->pbData[significantBytes - 1]; significantBytes--)
1938 if (significantBytes == 0)
1939 significantBytes = 1;
1940 if (blob->pbData[significantBytes - 1] > 0x7f)
1948 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
1950 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
1951 bytesNeeded = 1 + lenBytes + significantBytes;
1956 *pcbEncoded = bytesNeeded;
1961 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1962 pcbEncoded, bytesNeeded)))
1964 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1965 pbEncoded = *(BYTE **)pbEncoded;
1966 *pbEncoded++ = ASN_INTEGER;
1969 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
1970 pbEncoded += lenBytes;
1971 *pbEncoded++ = padByte;
1975 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
1976 pbEncoded += lenBytes;
1978 for (; significantBytes > 0; significantBytes--)
1979 *(pbEncoded++) = blob->pbData[significantBytes - 1];
1983 __EXCEPT(page_fault)
1985 SetLastError(STATUS_ACCESS_VIOLATION);
1992 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
1993 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1994 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2000 DWORD significantBytes, lenBytes;
2003 const CRYPT_INTEGER_BLOB *blob =
2004 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2006 significantBytes = blob->cbData;
2007 if (significantBytes)
2009 /* positive, lop off leading (little-endian) zeroes */
2010 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2013 if (significantBytes == 0)
2014 significantBytes = 1;
2015 if (blob->pbData[significantBytes - 1] > 0x7f)
2019 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2021 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2022 bytesNeeded = 1 + lenBytes + significantBytes;
2027 *pcbEncoded = bytesNeeded;
2032 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2033 pcbEncoded, bytesNeeded)))
2035 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2036 pbEncoded = *(BYTE **)pbEncoded;
2037 *pbEncoded++ = ASN_INTEGER;
2040 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2041 pbEncoded += lenBytes;
2046 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2047 pbEncoded += lenBytes;
2049 for (; significantBytes > 0; significantBytes--)
2050 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2054 __EXCEPT(page_fault)
2056 SetLastError(STATUS_ACCESS_VIOLATION);
2063 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2064 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2065 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2067 CRYPT_INTEGER_BLOB blob;
2070 /* Encode as an unsigned integer, then change the tag to enumerated */
2071 blob.cbData = sizeof(DWORD);
2072 blob.pbData = (BYTE *)pvStructInfo;
2073 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2074 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2075 if (ret && pbEncoded)
2077 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2078 pbEncoded = *(BYTE **)pbEncoded;
2079 pbEncoded[0] = ASN_ENUMERATED;
2084 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2085 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2086 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2093 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2094 * temporary buffer because the output buffer is not NULL-terminated.
2097 static const DWORD bytesNeeded = sizeof(buf) - 1;
2101 *pcbEncoded = bytesNeeded;
2106 /* Sanity check the year, this is a two-digit year format */
2107 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2109 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2111 SetLastError(CRYPT_E_BAD_ENCODE);
2116 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2117 pbEncoded, pcbEncoded, bytesNeeded)))
2119 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2120 pbEncoded = *(BYTE **)pbEncoded;
2121 buf[0] = ASN_UTCTIME;
2122 buf[1] = bytesNeeded - 2;
2123 snprintf(buf + 2, sizeof(buf) - 2,
2124 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2125 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2126 sysTime.wDay, sysTime.wMonth, sysTime.wHour,
2127 sysTime.wMinute, sysTime.wSecond);
2128 memcpy(pbEncoded, buf, bytesNeeded);
2133 __EXCEPT(page_fault)
2135 SetLastError(STATUS_ACCESS_VIOLATION);
2142 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2143 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2144 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2151 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2152 * temporary buffer because the output buffer is not NULL-terminated.
2155 static const DWORD bytesNeeded = sizeof(buf) - 1;
2159 *pcbEncoded = bytesNeeded;
2164 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2167 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2168 pcbEncoded, bytesNeeded);
2171 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2172 pbEncoded = *(BYTE **)pbEncoded;
2173 buf[0] = ASN_GENERALTIME;
2174 buf[1] = bytesNeeded - 2;
2175 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2176 sysTime.wYear, sysTime.wDay, sysTime.wMonth, sysTime.wHour,
2177 sysTime.wMinute, sysTime.wSecond);
2178 memcpy(pbEncoded, buf, bytesNeeded);
2182 __EXCEPT(page_fault)
2184 SetLastError(STATUS_ACCESS_VIOLATION);
2191 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2192 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2193 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2201 /* Check the year, if it's in the UTCTime range call that encode func */
2202 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2204 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2205 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2206 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2208 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2209 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2212 __EXCEPT(page_fault)
2214 SetLastError(STATUS_ACCESS_VIOLATION);
2221 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2222 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2223 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2229 DWORD bytesNeeded, dataLen, lenBytes, i;
2230 const CRYPT_SEQUENCE_OF_ANY *seq =
2231 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2233 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2234 dataLen += seq->rgValue[i].cbData;
2235 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2236 bytesNeeded = 1 + lenBytes + dataLen;
2239 *pcbEncoded = bytesNeeded;
2244 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2245 pcbEncoded, bytesNeeded)))
2247 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2248 pbEncoded = *(BYTE **)pbEncoded;
2249 *pbEncoded++ = ASN_SEQUENCEOF;
2250 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2251 pbEncoded += lenBytes;
2252 for (i = 0; i < seq->cValue; i++)
2254 memcpy(pbEncoded, seq->rgValue[i].pbData,
2255 seq->rgValue[i].cbData);
2256 pbEncoded += seq->rgValue[i].cbData;
2261 __EXCEPT(page_fault)
2263 SetLastError(STATUS_ACCESS_VIOLATION);
2270 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
2271 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
2272 void *pvEncoded, DWORD *pcbEncoded)
2276 CryptEncodeObjectExFunc encodeFunc = NULL;
2278 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType,
2279 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
2280 pvEncoded, pcbEncoded);
2282 if (!pvEncoded && !pcbEncoded)
2284 SetLastError(ERROR_INVALID_PARAMETER);
2287 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
2288 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
2290 SetLastError(ERROR_FILE_NOT_FOUND);
2294 SetLastError(NOERROR);
2295 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
2296 *(BYTE **)pvEncoded = NULL;
2297 if (!HIWORD(lpszStructType))
2299 switch (LOWORD(lpszStructType))
2301 case (WORD)X509_CERT:
2302 encodeFunc = CRYPT_AsnEncodeCert;
2304 case (WORD)X509_CERT_TO_BE_SIGNED:
2305 encodeFunc = CRYPT_AsnEncodeCertInfo;
2307 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
2308 encodeFunc = CRYPT_AsnEncodeCRLInfo;
2310 case (WORD)X509_EXTENSIONS:
2311 encodeFunc = CRYPT_AsnEncodeExtensions;
2313 case (WORD)X509_NAME:
2314 encodeFunc = CRYPT_AsnEncodeName;
2316 case (WORD)X509_PUBLIC_KEY_INFO:
2317 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
2319 case (WORD)X509_ALTERNATE_NAME:
2320 encodeFunc = CRYPT_AsnEncodeAltName;
2322 case (WORD)X509_BASIC_CONSTRAINTS2:
2323 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
2325 case (WORD)RSA_CSP_PUBLICKEYBLOB:
2326 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
2328 case (WORD)X509_OCTET_STRING:
2329 encodeFunc = CRYPT_AsnEncodeOctets;
2331 case (WORD)X509_BITS:
2332 case (WORD)X509_KEY_USAGE:
2333 encodeFunc = CRYPT_AsnEncodeBits;
2335 case (WORD)X509_INTEGER:
2336 encodeFunc = CRYPT_AsnEncodeInt;
2338 case (WORD)X509_MULTI_BYTE_INTEGER:
2339 encodeFunc = CRYPT_AsnEncodeInteger;
2341 case (WORD)X509_MULTI_BYTE_UINT:
2342 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
2344 case (WORD)X509_ENUMERATED:
2345 encodeFunc = CRYPT_AsnEncodeEnumerated;
2347 case (WORD)X509_CHOICE_OF_TIME:
2348 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
2350 case (WORD)X509_SEQUENCE_OF_ANY:
2351 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2353 case (WORD)PKCS_UTC_TIME:
2354 encodeFunc = CRYPT_AsnEncodeUtcTime;
2357 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
2360 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
2361 encodeFunc = CRYPT_AsnEncodeExtensions;
2362 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
2363 encodeFunc = CRYPT_AsnEncodeUtcTime;
2364 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
2365 encodeFunc = CRYPT_AsnEncodeEnumerated;
2366 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
2367 encodeFunc = CRYPT_AsnEncodeBits;
2368 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
2369 encodeFunc = CRYPT_AsnEncodeOctets;
2370 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
2371 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
2372 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
2373 encodeFunc = CRYPT_AsnEncodeAltName;
2374 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
2375 encodeFunc = CRYPT_AsnEncodeAltName;
2376 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
2377 encodeFunc = CRYPT_AsnEncodeAltName;
2378 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
2379 encodeFunc = CRYPT_AsnEncodeAltName;
2380 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
2381 encodeFunc = CRYPT_AsnEncodeAltName;
2383 TRACE("OID %s not found or unimplemented, looking for DLL\n",
2384 debugstr_a(lpszStructType));
2386 encodeFunc = (CryptEncodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType,
2387 lpszStructType, CRYPT_OID_ENCODE_OBJECT_EX_FUNC, &lib);
2389 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
2390 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
2392 SetLastError(ERROR_FILE_NOT_FOUND);
2398 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
2399 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2400 DWORD *pcbStructInfo)
2404 CryptDecodeObjectFunc pCryptDecodeObject;
2406 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType,
2407 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
2408 pvStructInfo, pcbStructInfo);
2410 if (!pvStructInfo && !pcbStructInfo)
2412 SetLastError(ERROR_INVALID_PARAMETER);
2416 /* Try registered DLL first.. */
2417 pCryptDecodeObject =
2418 (CryptDecodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType,
2419 lpszStructType, CRYPT_OID_DECODE_OBJECT_FUNC, &lib);
2420 if (pCryptDecodeObject)
2422 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
2423 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
2428 /* If not, use CryptDecodeObjectEx */
2429 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
2430 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
2435 /* Gets the number of length bytes from the given (leading) length byte */
2436 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
2438 /* Helper function to get the encoded length of the data starting at pbEncoded,
2439 * where pbEncoded[0] is the tag. If the data are too short to contain a
2440 * length or if the length is too large for cbEncoded, sets an appropriate
2441 * error code and returns FALSE.
2443 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
2450 SetLastError(CRYPT_E_ASN1_CORRUPT);
2453 else if (pbEncoded[1] <= 0x7f)
2455 if (pbEncoded[1] + 1 > cbEncoded)
2457 SetLastError(CRYPT_E_ASN1_EOD);
2462 *len = pbEncoded[1];
2468 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
2470 if (lenLen > sizeof(DWORD) + 1)
2472 SetLastError(CRYPT_E_ASN1_LARGE);
2475 else if (lenLen + 2 > cbEncoded)
2477 SetLastError(CRYPT_E_ASN1_CORRUPT);
2488 out |= *pbEncoded++;
2490 if (out + lenLen + 1 > cbEncoded)
2492 SetLastError(CRYPT_E_ASN1_EOD);
2505 /* Helper function to check *pcbStructInfo, set it to the required size, and
2506 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
2507 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
2508 * pointer to the newly allocated memory.
2510 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
2511 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
2516 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2518 if (pDecodePara && pDecodePara->pfnAlloc)
2519 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
2521 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
2522 if (!*(BYTE **)pvStructInfo)
2525 *pcbStructInfo = bytesNeeded;
2527 else if (*pcbStructInfo < bytesNeeded)
2529 *pcbStructInfo = bytesNeeded;
2530 SetLastError(ERROR_MORE_DATA);
2536 /* A few of the members need explanation:
2538 * A sequence is decoded into a struct. The offset member is the
2539 * offset of this item within that struct.
2541 * The decoder function to use. If this is NULL, then the member isn't
2542 * decoded, but minSize space is reserved for it.
2544 * The minimum amount of space occupied after decoding. You must set this.
2546 * If true, and a decoding function fails with CRYPT_E_ASN1_BADTAG, then
2547 * minSize space is filled with 0 for this member. (Any other failure
2548 * results in CRYPT_AsnDecodeSequence failing.)
2549 * hasPointer, pointerOffset, minSize:
2550 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
2551 * the offset within the (outer) struct of the data pointer (or to the
2552 * first data pointer, if more than one exist).
2554 * Used by CRYPT_AsnDecodeSequence, not for your use.
2556 struct AsnDecodeSequenceItem
2559 CryptDecodeObjectExFunc decodeFunc;
2563 DWORD pointerOffset;
2567 /* This decodes an arbitrary sequence into a contiguous block of memory
2568 * (basically, a struct.) Each element being decoded is described by a struct
2569 * AsnDecodeSequenceItem, see above.
2570 * startingPointer is an optional pointer to the first place where dynamic
2571 * data will be stored. If you know the starting offset, you may pass it
2572 * here. Otherwise, pass NULL, and one will be inferred from the items.
2573 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
2574 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
2576 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
2577 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
2578 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2579 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
2583 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items, cItem, pbEncoded,
2584 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
2587 if (pbEncoded[0] == ASN_SEQUENCE)
2591 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2593 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2594 DWORD i, bytesNeeded = 0, minSize = 0;
2597 ptr = pbEncoded + 1 + lenBytes;
2598 for (i = 0; ret && i < cItem; i++)
2602 minSize += items[i].minSize;
2603 if (cbEncoded - (ptr - pbEncoded) != 0)
2605 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
2608 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
2610 if (items[i].decodeFunc)
2612 TRACE("sizing item %ld\n", i);
2613 ret = items[i].decodeFunc(dwCertEncodingType, NULL,
2614 ptr, 1 + nextItemLenBytes + nextItemLen,
2615 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
2619 /* Account for alignment padding */
2620 bytesNeeded += items[i].size;
2621 if (items[i].size % sizeof(DWORD))
2622 bytesNeeded += sizeof(DWORD) -
2623 items[i].size % sizeof(DWORD);
2624 ptr += 1 + nextItemLenBytes + nextItemLen;
2626 else if (items[i].optional &&
2627 GetLastError() == CRYPT_E_ASN1_BADTAG)
2629 TRACE("skipping optional item %ld\n", i);
2630 bytesNeeded += items[i].minSize;
2631 SetLastError(NOERROR);
2635 TRACE("item %ld failed: %08lx\n", i,
2639 bytesNeeded += items[i].minSize;
2642 else if (items[i].optional)
2643 bytesNeeded += items[i].minSize;
2646 SetLastError(CRYPT_E_ASN1_CORRUPT);
2650 if (cbEncoded - (ptr - pbEncoded) != 0)
2652 TRACE("%ld remaining bytes, failing\n", cbEncoded -
2654 SetLastError(CRYPT_E_ASN1_CORRUPT);
2660 *pcbStructInfo = bytesNeeded;
2661 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
2662 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
2666 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2667 pvStructInfo = *(BYTE **)pvStructInfo;
2668 if (startingPointer)
2669 nextData = (BYTE *)startingPointer;
2671 nextData = (BYTE *)pvStructInfo + minSize;
2672 memset(pvStructInfo, 0, minSize);
2673 ptr = pbEncoded + 1 + lenBytes;
2674 for (i = 0; ret && i < cItem; i++)
2676 if (cbEncoded - (ptr - pbEncoded) != 0)
2679 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
2681 CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
2683 if (items[i].hasPointer)
2685 *(BYTE **)((BYTE *)pvStructInfo +
2686 items[i].pointerOffset) = nextData;
2688 if (items[i].decodeFunc)
2690 TRACE("decoding item %ld\n", i);
2691 ret = items[i].decodeFunc(dwCertEncodingType,
2692 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
2693 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
2694 (BYTE *)pvStructInfo + items[i].offset,
2697 TRACE("item %ld failed: %08lx\n", i,
2701 items[i].size = items[i].minSize;
2704 if (items[i].hasPointer &&
2705 items[i].size > items[i].minSize)
2707 nextData += items[i].size -
2709 /* align nextData to DWORD boundaries */
2710 if (items[i].size % sizeof(DWORD))
2712 nextData += sizeof(DWORD) -
2713 items[i].size % sizeof(DWORD);
2716 ptr += 1 + nextItemLenBytes + nextItemLen;
2718 else if (items[i].optional &&
2719 GetLastError() == CRYPT_E_ASN1_BADTAG)
2721 SetLastError(NOERROR);
2725 else if (!items[i].optional)
2727 SetLastError(CRYPT_E_ASN1_CORRUPT);
2737 SetLastError(CRYPT_E_ASN1_BADTAG);
2740 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2744 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
2745 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
2746 * to CRYPT_E_ASN1_CORRUPT.
2747 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
2750 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
2751 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2752 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2757 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2759 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2760 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
2762 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2763 bytesNeeded += 1 + lenBytes + dataLen;
2766 *pcbStructInfo = bytesNeeded;
2767 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2768 pvStructInfo, pcbStructInfo, bytesNeeded)))
2770 CRYPT_DER_BLOB *blob = (CRYPT_DER_BLOB *)pvStructInfo;
2772 blob->cbData = 1 + lenBytes + dataLen;
2775 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2776 blob->pbData = (BYTE *)pbEncoded;
2779 assert(blob->pbData);
2780 memcpy(blob->pbData, pbEncoded, blob->cbData);
2785 SetLastError(CRYPT_E_ASN1_CORRUPT);
2793 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
2794 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
2795 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2796 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2800 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2801 pDecodePara, pvStructInfo, *pcbStructInfo);
2803 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2806 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
2807 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
2808 pvStructInfo, pcbStructInfo);
2809 if (ret && pvStructInfo)
2811 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2818 for (i = 0; i < blob->cbData / 2; i++)
2820 temp = blob->pbData[i];
2821 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2822 blob->pbData[blob->cbData - i - 1] = temp;
2826 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2830 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
2831 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2832 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2836 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2837 pDecodePara, pvStructInfo, *pcbStructInfo);
2841 struct AsnDecodeSequenceItem items[] = {
2842 { offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
2843 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
2844 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
2845 { offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm),
2846 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2847 FALSE, TRUE, offsetof(CERT_SIGNED_CONTENT_INFO,
2848 SignatureAlgorithm.pszObjId), 0 },
2849 { offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
2850 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2851 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
2854 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
2855 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
2856 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2857 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2858 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2860 __EXCEPT(page_fault)
2862 SetLastError(STATUS_ACCESS_VIOLATION);
2869 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
2870 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2871 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2875 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR))
2879 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2881 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2883 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2884 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
2885 pvStructInfo, pcbStructInfo);
2890 SetLastError(CRYPT_E_ASN1_BADTAG);
2896 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
2897 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2898 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2902 struct AsnDecodeSequenceItem items[] = {
2903 { offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
2904 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
2905 { offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
2906 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
2909 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2910 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2911 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2915 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
2916 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2917 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2921 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 3))
2925 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2927 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2929 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
2930 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
2931 pDecodePara, pvStructInfo, pcbStructInfo);
2936 SetLastError(CRYPT_E_ASN1_BADTAG);
2942 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
2943 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2944 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2948 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2949 pDecodePara, pvStructInfo, *pcbStructInfo);
2953 struct AsnDecodeSequenceItem items[] = {
2954 { offsetof(CERT_INFO, dwVersion), CRYPT_AsnDecodeCertVersion,
2955 sizeof(DWORD), TRUE, FALSE, 0, 0 },
2956 { offsetof(CERT_INFO, SerialNumber), CRYPT_AsnDecodeIntegerInternal,
2957 sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
2958 SerialNumber.pbData), 0 },
2959 { offsetof(CERT_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
2960 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CERT_INFO,
2961 SignatureAlgorithm.pszObjId), 0 },
2962 { offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
2963 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
2965 { offsetof(CERT_INFO, NotBefore), CRYPT_AsnDecodeValidity,
2966 sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE, FALSE, 0 },
2967 { offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
2968 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
2970 { offsetof(CERT_INFO, SubjectPublicKeyInfo), CRYPT_AsnDecodePubKeyInfo,
2971 sizeof(CERT_PUBLIC_KEY_INFO), FALSE, TRUE, offsetof(CERT_INFO,
2972 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
2973 { offsetof(CERT_INFO, IssuerUniqueId), CRYPT_AsnDecodeBitsInternal,
2974 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO,
2975 IssuerUniqueId.pbData), 0 },
2976 { offsetof(CERT_INFO, SubjectUniqueId), CRYPT_AsnDecodeBitsInternal,
2977 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO,
2978 SubjectUniqueId.pbData), 0 },
2979 { offsetof(CERT_INFO, cExtension), CRYPT_AsnDecodeCertExtensions,
2980 sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CERT_INFO,
2984 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2985 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2986 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2988 __EXCEPT(page_fault)
2990 SetLastError(STATUS_ACCESS_VIOLATION);
2997 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2998 DWORD dwFlags, PCRL_ENTRY entry, DWORD *pcbEntry)
3001 struct AsnDecodeSequenceItem items[] = {
3002 { offsetof(CRL_ENTRY, SerialNumber), CRYPT_AsnDecodeIntegerInternal,
3003 sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CRL_ENTRY,
3004 SerialNumber.pbData), 0 },
3005 { offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
3006 sizeof(FILETIME), FALSE, FALSE, 0 },
3007 { offsetof(CRL_ENTRY, cExtension), CRYPT_AsnDecodeExtensionsInternal,
3008 sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CRL_ENTRY,
3012 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
3015 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3016 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
3017 NULL, entry, pcbEntry, entry ? entry->SerialNumber.pbData : NULL);
3018 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
3022 typedef struct _WINE_CRL_ENTRIES {
3024 PCRL_ENTRY rgCRLEntry;
3025 } WINE_CRL_ENTRIES, *PWINE_CRL_ENTRIES;
3027 /* Warning: assumes pvStructInfo is a WINE_CRL_ENTRIES whose rgCRLEntry has
3028 * been set prior to calling.
3030 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
3031 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3032 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3036 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3037 pDecodePara, pvStructInfo, *pcbStructInfo);
3039 if (pbEncoded[0] == ASN_SEQUENCEOF)
3041 DWORD dataLen, bytesNeeded;
3043 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3045 DWORD cCRLEntry = 0;
3046 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3048 bytesNeeded = sizeof(WINE_CRL_ENTRIES);
3054 for (ptr = pbEncoded + 1 + lenBytes; ret &&
3055 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3058 ret = CRYPT_AsnDecodeCRLEntry(ptr,
3059 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
3065 bytesNeeded += size;
3066 ret = CRYPT_GetLen(ptr,
3067 cbEncoded - (ptr - pbEncoded), &nextLen);
3069 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3076 *pcbStructInfo = bytesNeeded;
3077 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3078 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3083 PWINE_CRL_ENTRIES entries;
3085 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3086 pvStructInfo = *(BYTE **)pvStructInfo;
3087 *pcbStructInfo = bytesNeeded;
3088 entries = (PWINE_CRL_ENTRIES)pvStructInfo;
3089 entries->cCRLEntry = cCRLEntry;
3090 assert(entries->rgCRLEntry);
3091 nextData = (BYTE *)entries->rgCRLEntry +
3092 entries->cCRLEntry * sizeof(CRL_ENTRY);
3093 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
3094 i < cCRLEntry && ptr - pbEncoded - 1 - lenBytes <
3097 entries->rgCRLEntry[i].SerialNumber.pbData = nextData;
3099 ret = CRYPT_AsnDecodeCRLEntry(ptr,
3100 cbEncoded - (ptr - pbEncoded), dwFlags,
3101 &entries->rgCRLEntry[i], &size);
3106 bytesNeeded -= size;
3107 /* Increment nextData by the difference of the
3108 * minimum size and the actual size.
3110 if (size > sizeof(CRL_ENTRY))
3111 nextData += size - sizeof(CRL_ENTRY);
3112 ret = CRYPT_GetLen(ptr,
3113 cbEncoded - (ptr - pbEncoded), &nextLen);
3115 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3124 SetLastError(CRYPT_E_ASN1_BADTAG);
3127 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
3131 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
3132 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3133 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3137 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3138 pDecodePara, pvStructInfo, *pcbStructInfo);
3142 struct AsnDecodeSequenceItem items[] = {
3143 { offsetof(CRL_INFO, dwVersion), CRYPT_AsnDecodeCertVersion,
3144 sizeof(DWORD), TRUE, FALSE, 0, 0 },
3145 { offsetof(CRL_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
3146 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CRL_INFO,
3147 SignatureAlgorithm.pszObjId), 0 },
3148 { offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
3149 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
3151 { offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
3152 sizeof(FILETIME), FALSE, FALSE, 0 },
3153 { offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
3154 sizeof(FILETIME), TRUE, FALSE, 0 },
3155 { offsetof(CRL_INFO, cCRLEntry), CRYPT_AsnDecodeCRLEntries,
3156 sizeof(WINE_CRL_ENTRIES), TRUE, TRUE, offsetof(CRL_INFO,
3158 /* Note that the extensions are ignored by MS, so I'll ignore them too
3160 { offsetof(CRL_INFO, cExtension), NULL,
3161 sizeof(CERT_EXTENSIONS), TRUE, FALSE, 0 },
3164 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3165 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
3166 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3168 __EXCEPT(page_fault)
3170 SetLastError(STATUS_ACCESS_VIOLATION);
3175 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
3179 /* Differences between this and CRYPT_AsnDecodeOid:
3180 * - pvStructInfo is a LPSTR *, not an LPSTR
3181 * - CRYPT_AsnDecodeOid doesn't account for the size of an LPSTR in its byte
3182 * count, whereas our callers (typically CRYPT_AsnDecodeSequence) expect this
3185 static BOOL WINAPI CRYPT_AsnDecodeOidWrapper(DWORD dwCertEncodingType,
3186 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3187 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3191 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3192 pDecodePara, pvStructInfo, *pcbStructInfo);
3194 ret = CRYPT_AsnDecodeOid(pbEncoded, cbEncoded, dwFlags,
3195 pvStructInfo ? *(LPSTR *)pvStructInfo : NULL, pcbStructInfo);
3196 if (ret || GetLastError() == ERROR_MORE_DATA)
3197 *pcbStructInfo += sizeof(LPSTR);
3198 if (ret && pvStructInfo)
3199 TRACE("returning %s\n", debugstr_a(*(LPSTR *)pvStructInfo));
3203 /* Warning: assumes ext->pszObjId is set ahead of time! */
3204 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
3205 DWORD dwFlags, CERT_EXTENSION *ext, DWORD *pcbExt)
3207 struct AsnDecodeSequenceItem items[] = {
3208 { offsetof(CERT_EXTENSION, pszObjId), CRYPT_AsnDecodeOidWrapper,
3209 sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_EXTENSION, pszObjId), 0 },
3210 { offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
3211 sizeof(BOOL), TRUE, FALSE, 0, 0 },
3212 { offsetof(CERT_EXTENSION, Value), CRYPT_AsnDecodeOctetsInternal,
3213 sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE, offsetof(CERT_EXTENSION,
3218 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
3222 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
3223 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3224 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
3225 ext, pcbExt, ext ? ext->pszObjId : NULL);
3227 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
3228 debugstr_a(ext->pszObjId));
3229 TRACE("returning %d (%08lx)\n", ret, GetLastError());
3233 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
3234 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3235 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3239 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3240 pDecodePara, pvStructInfo, *pcbStructInfo);
3242 if (pbEncoded[0] == ASN_SEQUENCEOF)
3244 DWORD dataLen, bytesNeeded;
3246 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3248 DWORD cExtension = 0;
3249 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3251 bytesNeeded = sizeof(CERT_EXTENSIONS);
3257 for (ptr = pbEncoded + 1 + lenBytes; ret &&
3258 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3261 ret = CRYPT_AsnDecodeExtension(ptr,
3262 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
3268 bytesNeeded += size;
3269 ret = CRYPT_GetLen(ptr,
3270 cbEncoded - (ptr - pbEncoded), &nextLen);
3272 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3279 *pcbStructInfo = bytesNeeded;
3280 else if (*pcbStructInfo < bytesNeeded)
3282 SetLastError(ERROR_MORE_DATA);
3283 *pcbStructInfo = bytesNeeded;
3291 CERT_EXTENSIONS *exts;
3293 *pcbStructInfo = bytesNeeded;
3294 exts = (CERT_EXTENSIONS *)pvStructInfo;
3295 exts->cExtension = cExtension;
3296 assert(exts->rgExtension);
3297 nextData = (BYTE *)exts->rgExtension +
3298 exts->cExtension * sizeof(CERT_EXTENSION);
3299 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
3300 i < cExtension && ptr - pbEncoded - 1 - lenBytes <
3303 exts->rgExtension[i].pszObjId = (LPSTR)nextData;
3305 ret = CRYPT_AsnDecodeExtension(ptr,
3306 cbEncoded - (ptr - pbEncoded), dwFlags,
3307 &exts->rgExtension[i], &size);
3312 bytesNeeded -= size;
3313 if (size > sizeof(CERT_EXTENSION))
3314 nextData += size - sizeof(CERT_EXTENSION);
3315 ret = CRYPT_GetLen(ptr,
3316 cbEncoded - (ptr - pbEncoded), &nextLen);
3318 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3327 SetLastError(CRYPT_E_ASN1_BADTAG);
3333 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
3334 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3335 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3341 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
3342 lpszStructType, pbEncoded, cbEncoded,
3343 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
3344 if (ret && pvStructInfo)
3346 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3347 pcbStructInfo, *pcbStructInfo);
3350 CERT_EXTENSIONS *exts;
3352 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3353 pvStructInfo = *(BYTE **)pvStructInfo;
3354 exts = (CERT_EXTENSIONS *)pvStructInfo;
3355 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
3356 sizeof(CERT_EXTENSIONS));
3357 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
3358 lpszStructType, pbEncoded, cbEncoded,
3359 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
3364 __EXCEPT(page_fault)
3366 SetLastError(STATUS_ACCESS_VIOLATION);
3373 /* FIXME: honor the CRYPT_DECODE_SHARE_OID_STRING_FLAG. */
3374 static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded,
3375 DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId)
3379 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, pszObjId,
3384 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
3388 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3390 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3395 /* The largest possible string for the first two components
3396 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
3401 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
3402 pbEncoded[1 + lenBytes] / 40,
3403 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
3405 bytesNeeded = strlen(firstTwo) + 1;
3406 for (ptr = pbEncoded + 2 + lenBytes; ret &&
3407 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3409 /* large enough for ".4000000" */
3413 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
3420 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
3423 SetLastError(CRYPT_E_ASN1_CORRUPT);
3430 snprintf(str, sizeof(str), ".%d", val);
3431 bytesNeeded += strlen(str);
3435 *pcbObjId = bytesNeeded;
3436 else if (*pcbObjId < bytesNeeded)
3438 *pcbObjId = bytesNeeded;
3439 SetLastError(ERROR_MORE_DATA);
3445 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
3446 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
3448 pszObjId += strlen(pszObjId);
3449 for (ptr = pbEncoded + 2 + lenBytes; ret &&
3450 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3454 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
3463 sprintf(pszObjId, ".%d", val);
3464 pszObjId += strlen(pszObjId);
3470 *pcbObjId = bytesNeeded;
3475 SetLastError(CRYPT_E_ASN1_BADTAG);
3479 __EXCEPT(page_fault)
3481 SetLastError(STATUS_ACCESS_VIOLATION);
3488 /* Warning: this assumes the address of value->Value.pbData is already set, in
3489 * order to avoid overwriting memory. (In some cases, it may change it, if it
3490 * doesn't copy anything to memory.) Be sure to set it correctly!
3492 static BOOL WINAPI CRYPT_AsnDecodeNameValue(const BYTE *pbEncoded,
3493 DWORD cbEncoded, DWORD dwFlags, CERT_NAME_VALUE *value, DWORD *pcbValue)
3501 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3503 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3505 switch (pbEncoded[0])
3507 case ASN_NUMERICSTRING:
3508 case ASN_PRINTABLESTRING:
3512 FIXME("Unimplemented string type %02x\n", pbEncoded[0]);
3513 SetLastError(OSS_UNIMPLEMENTED);
3518 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE);
3520 switch (pbEncoded[0])
3522 case ASN_NUMERICSTRING:
3523 case ASN_PRINTABLESTRING:
3525 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3526 bytesNeeded += dataLen;
3530 *pcbValue = bytesNeeded;
3531 else if (*pcbValue < bytesNeeded)
3533 *pcbValue = bytesNeeded;
3534 SetLastError(ERROR_MORE_DATA);
3539 *pcbValue = bytesNeeded;
3540 switch (pbEncoded[0])
3542 case ASN_NUMERICSTRING:
3543 value->dwValueType = CERT_RDN_NUMERIC_STRING;
3545 case ASN_PRINTABLESTRING:
3546 value->dwValueType = CERT_RDN_PRINTABLE_STRING;
3549 value->dwValueType = CERT_RDN_IA5_STRING;
3554 switch (pbEncoded[0])
3556 case ASN_NUMERICSTRING:
3557 case ASN_PRINTABLESTRING:
3559 value->Value.cbData = dataLen;
3560 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3561 value->Value.pbData = (BYTE *)pbEncoded + 1 +
3565 assert(value->Value.pbData);
3566 memcpy(value->Value.pbData,
3567 pbEncoded + 1 + lenBytes, dataLen);
3574 value->Value.cbData = 0;
3575 value->Value.pbData = NULL;
3581 __EXCEPT(page_fault)
3583 SetLastError(STATUS_ACCESS_VIOLATION);
3590 /* FIXME: this should use CRYPT_AsnDecodeSequence (though that won't accept it
3591 * at the moment because of the ASN_CONSTRUCTOR tag.)
3593 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded,
3594 DWORD cbEncoded, DWORD dwFlags, CERT_RDN_ATTR *attr, DWORD *pcbAttr)
3600 if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SEQUENCE))
3602 DWORD bytesNeeded, dataLen, size;
3605 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3607 /* The data length must be at least 4, two for the tag and
3608 * length for the OID, and two for the string (assuming both
3609 * have short-form lengths.)
3613 SetLastError(CRYPT_E_ASN1_EOD);
3618 bytesNeeded = sizeof(CERT_RDN_ATTR);
3619 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3620 ret = CRYPT_AsnDecodeOid(pbEncoded + 1 + lenBytes,
3621 cbEncoded - 1 - lenBytes, dwFlags, NULL, &size);
3624 /* ugly: need to know the size of the next element of
3625 * the sequence, so get it directly
3627 DWORD objIdOfset = 1 + lenBytes, objIdLen,
3628 nameValueOffset = 0;
3630 ret = CRYPT_GetLen(pbEncoded + objIdOfset,
3631 cbEncoded - objIdOfset, &objIdLen);
3632 bytesNeeded += size;
3633 /* hack: like encoding, this takes advantage of the
3634 * fact that the rest of the structure is identical to
3635 * a CERT_NAME_VALUE.
3639 nameValueOffset = objIdOfset + objIdLen + 1 +
3640 GET_LEN_BYTES(pbEncoded[objIdOfset]);
3641 ret = CRYPT_AsnDecodeNameValue(
3642 pbEncoded + nameValueOffset,
3643 cbEncoded - nameValueOffset, dwFlags, NULL, &size);
3647 bytesNeeded += size;
3649 *pcbAttr = bytesNeeded;
3650 else if (*pcbAttr < bytesNeeded)
3652 *pcbAttr = bytesNeeded;
3653 SetLastError(ERROR_MORE_DATA);
3658 BYTE *originalData = attr->Value.pbData;
3660 *pcbAttr = bytesNeeded;
3661 /* strange: decode the value first, because it
3662 * has a counted size, and we can store the OID
3663 * after it. Keep track of the original data
3664 * pointer, we'll need to know whether it was
3668 ret = CRYPT_AsnDecodeNameValue(
3669 pbEncoded + nameValueOffset,
3670 cbEncoded - nameValueOffset, dwFlags,
3671 (CERT_NAME_VALUE *)&attr->dwValueType, &size);
3676 /* if the data were copied to the
3677 * original location, the OID goes
3678 * after. Otherwise it goes in the
3679 * spot originally reserved for the
3682 if (attr->Value.pbData == originalData)
3684 (LPSTR)(attr->Value.pbData +
3685 attr->Value.cbData);
3688 (LPSTR)originalData;
3689 size = bytesNeeded - size;
3690 ret = CRYPT_AsnDecodeOid(
3691 pbEncoded + objIdOfset,
3692 cbEncoded - objIdOfset,
3693 dwFlags, attr->pszObjId, &size);
3696 attr->pszObjId = NULL;
3706 SetLastError(CRYPT_E_ASN1_BADTAG);
3710 __EXCEPT(page_fault)
3712 SetLastError(STATUS_ACCESS_VIOLATION);
3719 static BOOL WINAPI CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
3720 DWORD dwFlags, CERT_RDN *rdn, DWORD *pcbRdn)
3726 if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SETOF))
3730 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3732 DWORD bytesNeeded, cRDNAttr = 0;
3733 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3735 bytesNeeded = sizeof(CERT_RDN);
3741 for (ptr = pbEncoded + 1 + lenBytes; ret &&
3742 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3744 ret = CRYPT_AsnDecodeRdnAttr(ptr,
3745 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
3751 bytesNeeded += size;
3752 ret = CRYPT_GetLen(ptr,
3753 cbEncoded - (ptr - pbEncoded), &nextLen);
3755 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3762 *pcbRdn = bytesNeeded;
3763 else if (*pcbRdn < bytesNeeded)
3765 *pcbRdn = bytesNeeded;
3766 SetLastError(ERROR_MORE_DATA);
3775 *pcbRdn = bytesNeeded;
3776 rdn->cRDNAttr = cRDNAttr;
3777 rdn->rgRDNAttr = (CERT_RDN_ATTR *)((BYTE *)rdn +
3779 nextData = (BYTE *)rdn->rgRDNAttr +
3780 rdn->cRDNAttr * sizeof(CERT_RDN_ATTR);
3781 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
3782 i < cRDNAttr && ptr - pbEncoded - 1 - lenBytes <
3785 rdn->rgRDNAttr[i].Value.pbData = nextData;
3787 ret = CRYPT_AsnDecodeRdnAttr(ptr,
3788 cbEncoded - (ptr - pbEncoded), dwFlags,
3789 &rdn->rgRDNAttr[i], &size);
3794 bytesNeeded -= size;
3795 /* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG, the
3796 * data may not have been copied.
3798 if (rdn->rgRDNAttr[i].Value.pbData == nextData)
3800 rdn->rgRDNAttr[i].Value.cbData;
3801 /* Ugly: the OID, if copied, is stored in
3802 * memory after the value, so increment by its
3803 * string length if it's set and points here.
3805 if ((const BYTE *)rdn->rgRDNAttr[i].pszObjId
3808 rdn->rgRDNAttr[i].pszObjId) + 1;
3809 ret = CRYPT_GetLen(ptr,
3810 cbEncoded - (ptr - pbEncoded), &nextLen);
3812 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3821 SetLastError(CRYPT_E_ASN1_BADTAG);
3825 __EXCEPT(page_fault)
3827 SetLastError(STATUS_ACCESS_VIOLATION);
3834 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
3835 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3836 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3842 if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SEQUENCEOF))
3846 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3848 DWORD bytesNeeded, cRDN = 0;
3849 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3851 bytesNeeded = sizeof(CERT_NAME_INFO);
3856 for (ptr = pbEncoded + 1 + lenBytes; ret &&
3857 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3861 ret = CRYPT_AsnDecodeRdn(ptr,
3862 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
3868 bytesNeeded += size;
3869 ret = CRYPT_GetLen(ptr,
3870 cbEncoded - (ptr - pbEncoded), &nextLen);
3872 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3879 *pcbStructInfo = bytesNeeded;
3880 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3881 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3883 CERT_NAME_INFO *info;
3885 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3886 pvStructInfo = *(BYTE **)pvStructInfo;
3887 info = (CERT_NAME_INFO *)pvStructInfo;
3889 if (info->cRDN == 0)
3897 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
3898 sizeof(CERT_NAME_INFO));
3899 nextData = (BYTE *)info->rgRDN +
3900 info->cRDN * sizeof(CERT_RDN);
3901 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
3902 i < cRDN && ptr - pbEncoded - 1 - lenBytes <
3905 info->rgRDN[i].rgRDNAttr =
3906 (CERT_RDN_ATTR *)nextData;
3908 ret = CRYPT_AsnDecodeRdn(ptr,
3909 cbEncoded - (ptr - pbEncoded), dwFlags,
3910 &info->rgRDN[i], &size);
3916 bytesNeeded -= size;
3917 ret = CRYPT_GetLen(ptr,
3918 cbEncoded - (ptr - pbEncoded), &nextLen);
3920 ptr += nextLen + 1 +
3921 GET_LEN_BYTES(ptr[1]);
3931 SetLastError(CRYPT_E_ASN1_BADTAG);
3935 __EXCEPT(page_fault)
3937 SetLastError(STATUS_ACCESS_VIOLATION);
3944 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
3945 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3946 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3949 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
3951 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3952 pDecodePara, pvStructInfo, *pcbStructInfo);
3954 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3955 bytesNeeded += cbEncoded;
3957 *pcbStructInfo = bytesNeeded;
3958 else if (*pcbStructInfo < bytesNeeded)
3960 SetLastError(ERROR_MORE_DATA);
3961 *pcbStructInfo = bytesNeeded;
3966 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
3968 *pcbStructInfo = bytesNeeded;
3969 blob->cbData = cbEncoded;
3970 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3971 blob->pbData = (LPBYTE)pbEncoded;
3974 assert(blob->pbData);
3975 memcpy(blob->pbData, pbEncoded, blob->cbData);
3981 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
3982 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3983 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3985 CRYPT_ALGORITHM_IDENTIFIER *algo =
3986 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
3988 struct AsnDecodeSequenceItem items[] = {
3989 { offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
3990 CRYPT_AsnDecodeOidWrapper, sizeof(LPSTR), FALSE, TRUE,
3991 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
3992 { offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
3993 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3994 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
3997 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3998 pDecodePara, pvStructInfo, *pcbStructInfo);
4000 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
4001 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
4002 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
4003 if (ret && pvStructInfo)
4005 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
4006 debugstr_a(algo->pszObjId));
4011 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
4012 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4013 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4019 struct AsnDecodeSequenceItem items[] = {
4020 { offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
4021 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4022 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
4023 Algorithm.pszObjId) },
4024 { offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
4025 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
4026 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
4029 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
4030 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
4031 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
4033 __EXCEPT(page_fault)
4035 SetLastError(STATUS_ACCESS_VIOLATION);
4042 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
4043 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4044 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4050 SetLastError(CRYPT_E_ASN1_CORRUPT);
4053 if (pbEncoded[0] != ASN_BOOL)
4055 SetLastError(CRYPT_E_ASN1_BADTAG);
4058 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
4060 SetLastError(CRYPT_E_ASN1_CORRUPT);
4063 if (pbEncoded[1] > 1)
4065 SetLastError(CRYPT_E_ASN1_CORRUPT);
4070 *pcbStructInfo = sizeof(BOOL);
4073 else if (*pcbStructInfo < sizeof(BOOL))
4075 *pcbStructInfo = sizeof(BOOL);
4076 SetLastError(ERROR_MORE_DATA);
4081 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
4084 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4088 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
4089 DWORD dwFlags, CERT_ALT_NAME_ENTRY *entry, DWORD *pcbEntry)
4091 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
4096 SetLastError(CRYPT_E_ASN1_CORRUPT);
4099 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
4101 SetLastError(CRYPT_E_ASN1_BADTAG);
4104 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4105 if (1 + lenBytes > cbEncoded)
4107 SetLastError(CRYPT_E_ASN1_CORRUPT);
4110 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4112 switch (pbEncoded[0] & ASN_TYPE_MASK)
4114 case 1: /* rfc822Name */
4115 case 2: /* dNSName */
4116 case 6: /* uniformResourceIdentifier */
4117 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
4119 case 7: /* iPAddress */
4120 bytesNeeded += dataLen;
4122 case 8: /* registeredID */
4123 /* FIXME: decode as OID */
4124 case 0: /* otherName */
4125 case 4: /* directoryName */
4127 SetLastError(CRYPT_E_ASN1_BADTAG);
4130 case 3: /* x400Address, unimplemented */
4131 case 5: /* ediPartyName, unimplemented */
4132 SetLastError(CRYPT_E_ASN1_BADTAG);
4136 SetLastError(CRYPT_E_ASN1_CORRUPT);
4142 *pcbEntry = bytesNeeded;
4143 else if (*pcbEntry < bytesNeeded)
4145 SetLastError(ERROR_MORE_DATA);
4150 /* MS used values one greater than the asn1 ones.. sigh */
4151 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
4152 switch (pbEncoded[0] & ASN_TYPE_MASK)
4154 case 1: /* rfc822Name */
4155 case 2: /* dNSName */
4156 case 6: /* uniformResourceIdentifier */
4160 for (i = 0; i < dataLen; i++)
4161 entry->u.pwszURL[i] =
4162 (WCHAR)pbEncoded[1 + lenBytes + i];
4163 entry->u.pwszURL[i] = 0;
4166 case 7: /* iPAddress */
4167 /* The next data pointer is in the pwszURL spot, that is,
4168 * the first 4 bytes. Need to move it to the next spot.
4170 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
4171 entry->u.IPAddress.cbData = dataLen;
4172 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
4182 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
4183 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4184 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4190 if (pbEncoded[0] == ASN_SEQUENCEOF)
4194 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4196 DWORD bytesNeeded, cEntry = 0;
4197 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4199 bytesNeeded = sizeof(CERT_ALT_NAME_INFO);
4204 for (ptr = pbEncoded + 1 + lenBytes; ret &&
4205 ptr - pbEncoded - 1 - lenBytes < dataLen; )
4209 ret = CRYPT_AsnDecodeAltNameEntry(ptr,
4210 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
4216 bytesNeeded += size;
4217 ret = CRYPT_GetLen(ptr,
4218 cbEncoded - (ptr - pbEncoded), &nextLen);
4220 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
4227 *pcbStructInfo = bytesNeeded;
4228 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4229 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4231 CERT_ALT_NAME_INFO *info;
4233 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4234 pvStructInfo = *(BYTE **)pvStructInfo;
4235 info = (CERT_ALT_NAME_INFO *)pvStructInfo;
4236 info->cAltEntry = 0;
4238 info->rgAltEntry = NULL;
4246 (CERT_ALT_NAME_ENTRY *)((BYTE *)pvStructInfo +
4247 sizeof(CERT_ALT_NAME_INFO));
4248 nextData = (BYTE *)info->rgAltEntry +
4249 cEntry * sizeof(CERT_ALT_NAME_ENTRY);
4250 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
4251 i < cEntry && ptr - pbEncoded - 1 - lenBytes <
4254 info->rgAltEntry[i].u.pwszURL =
4257 ret = CRYPT_AsnDecodeAltNameEntry(ptr,
4258 cbEncoded - (ptr - pbEncoded), dwFlags,
4259 &info->rgAltEntry[i], &size);
4266 sizeof(CERT_ALT_NAME_ENTRY);
4267 bytesNeeded -= size;
4268 ret = CRYPT_GetLen(ptr,
4269 cbEncoded - (ptr - pbEncoded), &nextLen);
4271 ptr += nextLen + 1 +
4272 GET_LEN_BYTES(ptr[1]);
4282 SetLastError(CRYPT_E_ASN1_BADTAG);
4286 __EXCEPT(page_fault)
4288 SetLastError(STATUS_ACCESS_VIOLATION);
4295 struct PATH_LEN_CONSTRAINT
4297 BOOL fPathLenConstraint;
4298 DWORD dwPathLenConstraint;
4301 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
4302 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4303 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4309 if (pbEncoded[0] == ASN_INTEGER)
4311 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
4314 *pcbStructInfo = bytesNeeded;
4315 else if (*pcbStructInfo < bytesNeeded)
4317 SetLastError(ERROR_MORE_DATA);
4318 *pcbStructInfo = bytesNeeded;
4323 struct PATH_LEN_CONSTRAINT *constraint =
4324 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
4325 DWORD size = sizeof(constraint->dwPathLenConstraint);
4327 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
4328 pbEncoded, cbEncoded, 0, NULL,
4329 &constraint->dwPathLenConstraint, &size);
4331 constraint->fPathLenConstraint = TRUE;
4332 TRACE("got an int, dwPathLenConstraint is %ld\n",
4333 constraint->dwPathLenConstraint);
4338 SetLastError(CRYPT_E_ASN1_CORRUPT);
4342 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4346 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
4347 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4348 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4354 struct AsnDecodeSequenceItem items[] = {
4355 { offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA), CRYPT_AsnDecodeBool,
4356 sizeof(BOOL), TRUE, FALSE, 0, 0 },
4357 { offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fPathLenConstraint),
4358 CRYPT_AsnDecodePathLenConstraint, sizeof(struct PATH_LEN_CONSTRAINT),
4359 TRUE, FALSE, 0, 0 },
4362 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
4363 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
4364 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
4366 __EXCEPT(page_fault)
4368 SetLastError(STATUS_ACCESS_VIOLATION);
4375 #define RSA1_MAGIC 0x31415352
4377 struct DECODED_RSA_PUB_KEY
4380 CRYPT_INTEGER_BLOB modulus;
4383 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
4384 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4385 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4391 struct AsnDecodeSequenceItem items[] = {
4392 { offsetof(struct DECODED_RSA_PUB_KEY, modulus),
4393 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4394 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
4396 { offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
4397 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4399 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
4402 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
4403 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
4404 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
4407 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
4408 decodedKey->modulus.cbData;
4412 *pcbStructInfo = bytesNeeded;
4415 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4416 pvStructInfo, pcbStructInfo, bytesNeeded)))
4419 RSAPUBKEY *rsaPubKey;
4421 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4422 pvStructInfo = *(BYTE **)pvStructInfo;
4423 hdr = (BLOBHEADER *)pvStructInfo;
4424 hdr->bType = PUBLICKEYBLOB;
4425 hdr->bVersion = CUR_BLOB_VERSION;
4427 hdr->aiKeyAlg = CALG_RSA_KEYX;
4428 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
4429 sizeof(BLOBHEADER));
4430 rsaPubKey->magic = RSA1_MAGIC;
4431 rsaPubKey->pubexp = decodedKey->pubexp;
4432 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
4433 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
4434 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
4435 decodedKey->modulus.cbData);
4437 LocalFree(decodedKey);
4440 __EXCEPT(page_fault)
4442 SetLastError(STATUS_ACCESS_VIOLATION);
4449 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
4450 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4451 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4455 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
4456 pDecodePara, pvStructInfo, *pcbStructInfo);
4458 if (pbEncoded[0] == ASN_OCTETSTRING)
4460 DWORD bytesNeeded, dataLen;
4462 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4464 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4465 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
4467 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
4469 *pcbStructInfo = bytesNeeded;
4470 else if (*pcbStructInfo < bytesNeeded)
4472 SetLastError(ERROR_MORE_DATA);
4473 *pcbStructInfo = bytesNeeded;
4478 CRYPT_DATA_BLOB *blob;
4479 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4481 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
4482 blob->cbData = dataLen;
4483 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4484 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
4487 assert(blob->pbData);
4489 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
4497 SetLastError(CRYPT_E_ASN1_BADTAG);
4503 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
4504 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4505 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4509 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
4510 pDecodePara, pvStructInfo, *pcbStructInfo);
4516 if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
4517 lpszStructType, pbEncoded, cbEncoded,
4518 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
4521 *pcbStructInfo = bytesNeeded;
4522 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4523 pvStructInfo, pcbStructInfo, bytesNeeded)))
4525 CRYPT_DATA_BLOB *blob;
4527 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4528 pvStructInfo = *(BYTE **)pvStructInfo;
4529 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
4530 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
4531 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
4532 lpszStructType, pbEncoded, cbEncoded,
4533 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
4539 SetLastError(CRYPT_E_ASN1_BADTAG);
4543 __EXCEPT(page_fault)
4545 SetLastError(STATUS_ACCESS_VIOLATION);
4552 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
4553 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4554 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4558 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
4559 pDecodePara, pvStructInfo, *pcbStructInfo);
4561 if (pbEncoded[0] == ASN_BITSTRING)
4563 DWORD bytesNeeded, dataLen;
4565 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4567 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4568 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
4570 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
4572 *pcbStructInfo = bytesNeeded;
4573 else if (*pcbStructInfo < bytesNeeded)
4575 *pcbStructInfo = bytesNeeded;
4576 SetLastError(ERROR_MORE_DATA);
4581 CRYPT_BIT_BLOB *blob;
4583 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
4584 blob->cbData = dataLen - 1;
4585 blob->cUnusedBits = *(pbEncoded + 1 +
4586 GET_LEN_BYTES(pbEncoded[1]));
4587 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4589 blob->pbData = (BYTE *)pbEncoded + 2 +
4590 GET_LEN_BYTES(pbEncoded[1]);
4594 assert(blob->pbData);
4597 BYTE mask = 0xff << blob->cUnusedBits;
4599 memcpy(blob->pbData, pbEncoded + 2 +
4600 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
4601 blob->pbData[blob->cbData - 1] &= mask;
4609 SetLastError(CRYPT_E_ASN1_BADTAG);
4612 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4616 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
4617 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4618 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4622 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
4623 pDecodePara, pvStructInfo, pcbStructInfo);
4629 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
4630 lpszStructType, pbEncoded, cbEncoded,
4631 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
4634 *pcbStructInfo = bytesNeeded;
4635 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4636 pvStructInfo, pcbStructInfo, bytesNeeded)))
4638 CRYPT_BIT_BLOB *blob;
4640 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4641 pvStructInfo = *(BYTE **)pvStructInfo;
4642 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
4643 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
4644 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
4645 lpszStructType, pbEncoded, cbEncoded,
4646 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
4651 __EXCEPT(page_fault)
4653 SetLastError(STATUS_ACCESS_VIOLATION);
4657 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4661 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
4662 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4663 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4669 *pcbStructInfo = sizeof(int);
4674 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
4675 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
4676 DWORD size = sizeof(buf);
4678 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
4679 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
4680 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf, &size);
4683 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4684 pvStructInfo, pcbStructInfo, sizeof(int))))
4688 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4689 pvStructInfo = *(BYTE **)pvStructInfo;
4690 if (blob->pbData[blob->cbData - 1] & 0x80)
4692 /* initialize to a negative value to sign-extend */
4697 for (i = 0; i < blob->cbData; i++)
4700 val |= blob->pbData[blob->cbData - i - 1];
4702 memcpy(pvStructInfo, &val, sizeof(int));
4705 else if (GetLastError() == ERROR_MORE_DATA)
4706 SetLastError(CRYPT_E_ASN1_LARGE);
4708 __EXCEPT(page_fault)
4710 SetLastError(STATUS_ACCESS_VIOLATION);
4717 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
4718 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4719 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4723 if (pbEncoded[0] == ASN_INTEGER)
4725 DWORD bytesNeeded, dataLen;
4727 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4729 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4731 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4733 *pcbStructInfo = bytesNeeded;
4734 else if (*pcbStructInfo < bytesNeeded)
4736 *pcbStructInfo = bytesNeeded;
4737 SetLastError(ERROR_MORE_DATA);
4742 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
4744 blob->cbData = dataLen;
4745 assert(blob->pbData);
4750 for (i = 0; i < blob->cbData; i++)
4752 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4761 SetLastError(CRYPT_E_ASN1_BADTAG);
4767 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4768 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4769 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4777 if ((ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
4778 lpszStructType, pbEncoded, cbEncoded,
4779 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
4782 *pcbStructInfo = bytesNeeded;
4783 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4784 pvStructInfo, pcbStructInfo, bytesNeeded)))
4786 CRYPT_INTEGER_BLOB *blob;
4788 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4789 pvStructInfo = *(BYTE **)pvStructInfo;
4790 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
4791 blob->pbData = (BYTE *)pvStructInfo +
4792 sizeof(CRYPT_INTEGER_BLOB);
4793 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
4794 lpszStructType, pbEncoded, cbEncoded,
4795 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
4800 __EXCEPT(page_fault)
4802 SetLastError(STATUS_ACCESS_VIOLATION);
4809 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
4810 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
4811 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4812 void *pvStructInfo, DWORD *pcbStructInfo)
4816 if (pbEncoded[0] == ASN_INTEGER)
4818 DWORD bytesNeeded, dataLen;
4820 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4822 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4824 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4826 *pcbStructInfo = bytesNeeded;
4827 else if (*pcbStructInfo < bytesNeeded)
4829 *pcbStructInfo = bytesNeeded;
4830 SetLastError(ERROR_MORE_DATA);
4835 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
4837 blob->cbData = dataLen;
4838 assert(blob->pbData);
4839 /* remove leading zero byte if it exists */
4840 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4849 for (i = 0; i < blob->cbData; i++)
4851 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4860 SetLastError(CRYPT_E_ASN1_BADTAG);
4866 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4867 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4868 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4876 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
4877 lpszStructType, pbEncoded, cbEncoded,
4878 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
4881 *pcbStructInfo = bytesNeeded;
4882 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4883 pvStructInfo, pcbStructInfo, bytesNeeded)))
4885 CRYPT_INTEGER_BLOB *blob;
4887 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4888 pvStructInfo = *(BYTE **)pvStructInfo;
4889 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
4890 blob->pbData = (BYTE *)pvStructInfo +
4891 sizeof(CRYPT_INTEGER_BLOB);
4892 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
4893 lpszStructType, pbEncoded, cbEncoded,
4894 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
4899 __EXCEPT(page_fault)
4901 SetLastError(STATUS_ACCESS_VIOLATION);
4908 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4909 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4910 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4916 *pcbStructInfo = sizeof(int);
4921 if (pbEncoded[0] == ASN_ENUMERATED)
4923 unsigned int val = 0, i;
4927 SetLastError(CRYPT_E_ASN1_EOD);
4930 else if (pbEncoded[1] == 0)
4932 SetLastError(CRYPT_E_ASN1_CORRUPT);
4937 /* A little strange looking, but we have to accept a sign byte:
4938 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4939 * assuming a small length is okay here, it has to be in short
4942 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4944 SetLastError(CRYPT_E_ASN1_LARGE);
4947 for (i = 0; i < pbEncoded[1]; i++)
4950 val |= pbEncoded[2 + i];
4952 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4953 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4955 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4956 pvStructInfo = *(BYTE **)pvStructInfo;
4957 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4963 SetLastError(CRYPT_E_ASN1_BADTAG);
4967 __EXCEPT(page_fault)
4969 SetLastError(STATUS_ACCESS_VIOLATION);
4976 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4979 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4984 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4986 if (!isdigit(*(pbEncoded))) \
4988 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4994 (word) += *(pbEncoded)++ - '0'; \
4999 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
5000 SYSTEMTIME *sysTime)
5007 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
5009 WORD hours, minutes = 0;
5010 BYTE sign = *pbEncoded++;
5013 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
5014 if (ret && hours >= 24)
5016 SetLastError(CRYPT_E_ASN1_CORRUPT);
5021 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
5022 if (ret && minutes >= 60)
5024 SetLastError(CRYPT_E_ASN1_CORRUPT);
5032 sysTime->wHour += hours;
5033 sysTime->wMinute += minutes;
5037 if (hours > sysTime->wHour)
5040 sysTime->wHour = 24 - (hours - sysTime->wHour);
5043 sysTime->wHour -= hours;
5044 if (minutes > sysTime->wMinute)
5047 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
5050 sysTime->wMinute -= minutes;
5055 __EXCEPT(page_fault)
5057 SetLastError(STATUS_ACCESS_VIOLATION);
5064 #define MIN_ENCODED_TIME_LENGTH 10
5066 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
5067 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5068 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5074 *pcbStructInfo = sizeof(FILETIME);
5080 if (pbEncoded[0] == ASN_UTCTIME)
5084 SetLastError(CRYPT_E_ASN1_EOD);
5087 else if (pbEncoded[1] > 0x7f)
5089 /* long-form date strings really can't be valid */
5090 SetLastError(CRYPT_E_ASN1_CORRUPT);
5095 SYSTEMTIME sysTime = { 0 };
5096 BYTE len = pbEncoded[1];
5098 if (len < MIN_ENCODED_TIME_LENGTH)
5100 SetLastError(CRYPT_E_ASN1_CORRUPT);
5106 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
5107 if (sysTime.wYear >= 50)
5108 sysTime.wYear += 1900;
5110 sysTime.wYear += 2000;
5111 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
5112 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
5113 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
5114 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
5117 if (len >= 2 && isdigit(*pbEncoded) &&
5118 isdigit(*(pbEncoded + 1)))
5119 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5121 else if (isdigit(*pbEncoded))
5122 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
5125 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
5128 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
5129 pDecodePara, pvStructInfo, pcbStructInfo,
5132 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5133 pvStructInfo = *(BYTE **)pvStructInfo;
5134 ret = SystemTimeToFileTime(&sysTime,
5135 (FILETIME *)pvStructInfo);
5142 SetLastError(CRYPT_E_ASN1_BADTAG);
5146 __EXCEPT(page_fault)
5148 SetLastError(STATUS_ACCESS_VIOLATION);
5155 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
5156 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5157 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5163 *pcbStructInfo = sizeof(FILETIME);
5169 if (pbEncoded[0] == ASN_GENERALTIME)
5173 SetLastError(CRYPT_E_ASN1_EOD);
5176 else if (pbEncoded[1] > 0x7f)
5178 /* long-form date strings really can't be valid */
5179 SetLastError(CRYPT_E_ASN1_CORRUPT);
5184 BYTE len = pbEncoded[1];
5186 if (len < MIN_ENCODED_TIME_LENGTH)
5188 SetLastError(CRYPT_E_ASN1_CORRUPT);
5193 SYSTEMTIME sysTime = { 0 };
5196 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
5197 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
5198 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
5199 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
5202 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5205 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5207 if (ret && len > 0 && (*pbEncoded == '.' ||
5214 /* workaround macro weirdness */
5215 digits = min(len, 3);
5216 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
5217 sysTime.wMilliseconds);
5220 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
5223 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
5224 pDecodePara, pvStructInfo, pcbStructInfo,
5227 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5228 pvStructInfo = *(BYTE **)pvStructInfo;
5229 ret = SystemTimeToFileTime(&sysTime,
5230 (FILETIME *)pvStructInfo);
5237 SetLastError(CRYPT_E_ASN1_BADTAG);
5241 __EXCEPT(page_fault)
5243 SetLastError(STATUS_ACCESS_VIOLATION);
5250 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
5251 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5252 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5258 if (pbEncoded[0] == ASN_UTCTIME)
5259 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
5260 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5262 else if (pbEncoded[0] == ASN_GENERALTIME)
5263 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
5264 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
5265 pvStructInfo, pcbStructInfo);
5268 SetLastError(CRYPT_E_ASN1_BADTAG);
5272 __EXCEPT(page_fault)
5274 SetLastError(STATUS_ACCESS_VIOLATION);
5281 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
5282 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5283 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5289 if (pbEncoded[0] == ASN_SEQUENCEOF)
5291 DWORD bytesNeeded, dataLen, remainingLen, cValue;
5293 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
5298 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
5299 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
5301 ptr = pbEncoded + 1 + lenBytes;
5302 remainingLen = dataLen;
5303 while (ret && remainingLen)
5307 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5310 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5312 remainingLen -= 1 + nextLenBytes + nextLen;
5313 ptr += 1 + nextLenBytes + nextLen;
5314 bytesNeeded += sizeof(CRYPT_DER_BLOB);
5315 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
5316 bytesNeeded += 1 + nextLenBytes + nextLen;
5322 CRYPT_SEQUENCE_OF_ANY *seq;
5326 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5327 pvStructInfo, pcbStructInfo, bytesNeeded)))
5329 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5330 pvStructInfo = *(BYTE **)pvStructInfo;
5331 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
5332 seq->cValue = cValue;
5333 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
5335 nextPtr = (BYTE *)seq->rgValue +
5336 cValue * sizeof(CRYPT_DER_BLOB);
5337 ptr = pbEncoded + 1 + lenBytes;
5338 remainingLen = dataLen;
5340 while (ret && remainingLen)
5344 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5347 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5349 seq->rgValue[i].cbData = 1 + nextLenBytes +
5351 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
5352 seq->rgValue[i].pbData = (BYTE *)ptr;
5355 seq->rgValue[i].pbData = nextPtr;
5356 memcpy(nextPtr, ptr, 1 + nextLenBytes +
5358 nextPtr += 1 + nextLenBytes + nextLen;
5360 remainingLen -= 1 + nextLenBytes + nextLen;
5361 ptr += 1 + nextLenBytes + nextLen;
5371 SetLastError(CRYPT_E_ASN1_BADTAG);
5375 __EXCEPT(page_fault)
5377 SetLastError(STATUS_ACCESS_VIOLATION);
5384 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5385 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5386 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5390 CryptDecodeObjectExFunc decodeFunc = NULL;
5392 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
5393 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5394 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5396 if (!pvStructInfo && !pcbStructInfo)
5398 SetLastError(ERROR_INVALID_PARAMETER);
5401 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
5402 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
5404 SetLastError(ERROR_FILE_NOT_FOUND);
5409 SetLastError(CRYPT_E_ASN1_EOD);
5412 if (cbEncoded > MAX_ENCODED_LEN)
5414 SetLastError(CRYPT_E_ASN1_LARGE);
5418 SetLastError(NOERROR);
5419 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
5420 *(BYTE **)pvStructInfo = NULL;
5421 if (!HIWORD(lpszStructType))
5423 switch (LOWORD(lpszStructType))
5425 case (WORD)X509_CERT:
5426 decodeFunc = CRYPT_AsnDecodeCert;
5428 case (WORD)X509_CERT_TO_BE_SIGNED:
5429 decodeFunc = CRYPT_AsnDecodeCertInfo;
5431 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
5432 decodeFunc = CRYPT_AsnDecodeCRLInfo;
5434 case (WORD)X509_EXTENSIONS:
5435 decodeFunc = CRYPT_AsnDecodeExtensions;
5437 case (WORD)X509_NAME:
5438 decodeFunc = CRYPT_AsnDecodeName;
5440 case (WORD)X509_PUBLIC_KEY_INFO:
5441 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
5443 case (WORD)X509_ALTERNATE_NAME:
5444 decodeFunc = CRYPT_AsnDecodeAltName;
5446 case (WORD)X509_BASIC_CONSTRAINTS2:
5447 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5449 case (WORD)RSA_CSP_PUBLICKEYBLOB:
5450 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
5452 case (WORD)X509_OCTET_STRING:
5453 decodeFunc = CRYPT_AsnDecodeOctets;
5455 case (WORD)X509_BITS:
5456 case (WORD)X509_KEY_USAGE:
5457 decodeFunc = CRYPT_AsnDecodeBits;
5459 case (WORD)X509_INTEGER:
5460 decodeFunc = CRYPT_AsnDecodeInt;
5462 case (WORD)X509_MULTI_BYTE_INTEGER:
5463 decodeFunc = CRYPT_AsnDecodeInteger;
5465 case (WORD)X509_MULTI_BYTE_UINT:
5466 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
5468 case (WORD)X509_ENUMERATED:
5469 decodeFunc = CRYPT_AsnDecodeEnumerated;
5471 case (WORD)X509_CHOICE_OF_TIME:
5472 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
5474 case (WORD)X509_SEQUENCE_OF_ANY:
5475 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
5477 case (WORD)PKCS_UTC_TIME:
5478 decodeFunc = CRYPT_AsnDecodeUtcTime;
5481 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
5484 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
5485 decodeFunc = CRYPT_AsnDecodeExtensions;
5486 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
5487 decodeFunc = CRYPT_AsnDecodeUtcTime;
5488 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
5489 decodeFunc = CRYPT_AsnDecodeEnumerated;
5490 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
5491 decodeFunc = CRYPT_AsnDecodeBits;
5492 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
5493 decodeFunc = CRYPT_AsnDecodeOctets;
5494 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
5495 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5496 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
5497 decodeFunc = CRYPT_AsnDecodeAltName;
5498 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
5499 decodeFunc = CRYPT_AsnDecodeAltName;
5500 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
5501 decodeFunc = CRYPT_AsnDecodeAltName;
5502 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
5503 decodeFunc = CRYPT_AsnDecodeAltName;
5504 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
5505 decodeFunc = CRYPT_AsnDecodeAltName;
5507 TRACE("OID %s not found or unimplemented, looking for DLL\n",
5508 debugstr_a(lpszStructType));
5510 decodeFunc = (CryptDecodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType,
5511 lpszStructType, CRYPT_OID_DECODE_OBJECT_EX_FUNC, &lib);
5513 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
5514 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5516 SetLastError(ERROR_FILE_NOT_FOUND);
5522 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
5523 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5525 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
5526 NULL, 0, NULL, pInfo, pcbInfo);
5529 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
5530 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
5531 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5536 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv, dwKeySpec,
5537 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
5540 if (!pszPublicKeyObjId)
5541 pszPublicKeyObjId = szOID_RSA_RSA;
5542 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
5546 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
5549 LPBYTE pubKey = CryptMemAlloc(keySize);
5553 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
5557 DWORD encodedLen = 0;
5559 ret = CryptEncodeObject(dwCertEncodingType,
5560 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
5563 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
5564 strlen(pszPublicKeyObjId) + 1 + encodedLen;
5567 *pcbInfo = sizeNeeded;
5568 else if (*pcbInfo < sizeNeeded)
5570 SetLastError(ERROR_MORE_DATA);
5571 *pcbInfo = sizeNeeded;
5576 pInfo->Algorithm.pszObjId = (char *)pInfo +
5577 sizeof(CERT_PUBLIC_KEY_INFO);
5578 lstrcpyA(pInfo->Algorithm.pszObjId,
5580 pInfo->Algorithm.Parameters.cbData = 0;
5581 pInfo->Algorithm.Parameters.pbData = NULL;
5582 pInfo->PublicKey.pbData =
5583 (BYTE *)pInfo->Algorithm.pszObjId
5584 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
5585 pInfo->PublicKey.cbData = encodedLen;
5586 pInfo->PublicKey.cUnusedBits = 0;
5587 ret = CryptEncodeObject(dwCertEncodingType,
5588 RSA_CSP_PUBLICKEYBLOB, pubKey,
5589 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
5593 CryptMemFree(pubKey);
5598 CryptDestroyKey(key);
5603 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
5604 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
5605 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
5607 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
5608 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
5609 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5612 ExportPublicKeyInfoExFunc exportFunc = NULL;
5615 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv, dwKeySpec,
5616 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
5621 SetLastError(ERROR_INVALID_PARAMETER);
5625 if (pszPublicKeyObjId)
5626 exportFunc = CRYPT_GetFunc(dwCertEncodingType, pszPublicKeyObjId,
5627 CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC, &lib);
5629 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
5630 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
5631 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
5637 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
5638 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
5640 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
5644 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
5645 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5646 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
5649 DWORD pubKeySize = 0;
5651 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv,
5652 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
5654 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
5655 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
5658 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
5662 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
5663 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
5666 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
5668 CryptMemFree(pubKey);
5676 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
5677 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5678 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
5680 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
5681 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5682 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
5685 ImportPublicKeyInfoExFunc importFunc = NULL;
5688 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv,
5689 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
5691 importFunc = CRYPT_GetFunc(dwCertEncodingType, pInfo->Algorithm.pszObjId,
5692 CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, &lib);
5694 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
5695 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,