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
43 #include "wine/debug.h"
44 #include "wine/exception.h"
46 /* This is a bit arbitrary, but to set some limit: */
47 #define MAX_ENCODED_LEN 0x02000000
49 /* a few asn.1 tags we need */
50 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
51 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
52 #define ASN_OCTETSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x04)
53 #define ASN_ENUMERATED (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0a)
54 #define ASN_SETOF (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x11)
55 #define ASN_NUMERICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x12)
56 #define ASN_PRINTABLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x13)
57 #define ASN_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16)
58 #define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17)
59 #define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18)
61 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
63 static const WCHAR szDllName[] = { 'D','l','l',0 };
65 static BOOL WINAPI CRYPT_AsnEncodeOid(LPCSTR pszObjId, BYTE *pbEncoded,
67 static BOOL CRYPT_EncodeBool(BOOL val, BYTE *pbEncoded, DWORD *pcbEncoded);
68 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
69 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
70 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
71 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
72 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
73 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
74 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
75 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
76 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
77 static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded,
78 DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId);
79 static BOOL WINAPI CRYPT_DecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
81 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
82 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
83 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
84 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
86 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
87 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
88 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
89 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
91 /* filter for page-fault exceptions */
92 static WINE_EXCEPTION_FILTER(page_fault)
94 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
95 return EXCEPTION_EXECUTE_HANDLER;
96 return EXCEPTION_CONTINUE_SEARCH;
99 static char *CRYPT_GetKeyName(DWORD dwEncodingType, LPCSTR pszFuncName,
102 static const char szEncodingTypeFmt[] =
103 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
105 char numericOID[7]; /* enough for "#65535" */
109 /* MSDN says the encoding type is a mask, but it isn't treated that way.
110 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
111 * "EncodingType 2" would be expected if it were a mask. Instead native
112 * stores values in "EncodingType 3".
116 snprintf(numericOID, sizeof(numericOID), "#%d", (int)pszOID);
122 /* This is enough: the lengths of the two string parameters are explicitly
123 * counted, and we need up to five additional characters for the encoding
124 * type. These are covered by the "%d", "%s", and "%s" characters in the
125 * format specifier that are removed by sprintf.
127 len = sizeof(szEncodingTypeFmt) + lstrlenA(pszFuncName) + lstrlenA(oid);
128 szKey = HeapAlloc(GetProcessHeap(), 0, len);
130 sprintf(szKey, szEncodingTypeFmt, dwEncodingType, pszFuncName, oid);
134 BOOL WINAPI CryptRegisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
135 LPCSTR pszOID, LPCWSTR pwszDll, LPCSTR pszOverrideFuncName)
141 TRACE("%lx %s %s %s %s\n", dwEncodingType, pszFuncName, pszOID,
142 debugstr_w(pwszDll), pszOverrideFuncName);
144 /* This only registers functions for encoding certs, not messages */
145 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
148 /* Native does nothing pwszDll is NULL */
152 /* I'm not matching MS bug for bug here, because I doubt any app depends on
154 * - native "succeeds" if pszFuncName is NULL, but the nonsensical entry
155 * it creates would never be used
156 * - native returns an HRESULT rather than a Win32 error if pszOID is NULL.
157 * Instead I disallow both of these with ERROR_INVALID_PARAMETER.
159 if (!pszFuncName || !pszOID)
161 SetLastError(ERROR_INVALID_PARAMETER);
165 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
166 TRACE("Key name is %s\n", debugstr_a(szKey));
171 r = RegCreateKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
172 HeapFree(GetProcessHeap(), 0, szKey);
173 if(r != ERROR_SUCCESS)
176 /* write the values */
177 if (pszOverrideFuncName)
178 RegSetValueExA(hKey, "FuncName", 0, REG_SZ, pszOverrideFuncName,
179 lstrlenA(pszOverrideFuncName) + 1);
180 RegSetValueExW(hKey, szDllName, 0, REG_SZ, (const BYTE*) pwszDll,
181 (lstrlenW(pwszDll) + 1) * sizeof (WCHAR));
187 BOOL WINAPI CryptUnregisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
193 TRACE("%lx %s %s\n", dwEncodingType, pszFuncName, pszOID);
195 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
198 if (!pszFuncName || !pszOID)
200 SetLastError(ERROR_INVALID_PARAMETER);
204 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
205 rc = RegDeleteKeyA(HKEY_LOCAL_MACHINE, szKey);
206 HeapFree(GetProcessHeap(), 0, szKey);
209 return rc ? FALSE : TRUE;
212 BOOL WINAPI CryptGetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
213 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD *pdwValueType, BYTE *pbValueData,
220 TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType, debugstr_a(pszFuncName),
221 debugstr_a(pszOID), debugstr_w(pwszValueName), pdwValueType, pbValueData,
224 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
227 if (!pszFuncName || !pszOID || !pwszValueName)
229 SetLastError(ERROR_INVALID_PARAMETER);
233 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
234 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
235 HeapFree(GetProcessHeap(), 0, szKey);
240 rc = RegQueryValueExW(hKey, pwszValueName, NULL, pdwValueType,
241 pbValueData, pcbValueData);
246 return rc ? FALSE : TRUE;
249 BOOL WINAPI CryptSetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
250 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD dwValueType,
251 const BYTE *pbValueData, DWORD cbValueData)
257 TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType, debugstr_a(pszFuncName),
258 debugstr_a(pszOID), debugstr_w(pwszValueName), dwValueType, pbValueData,
261 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
264 if (!pszFuncName || !pszOID || !pwszValueName)
266 SetLastError(ERROR_INVALID_PARAMETER);
270 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
271 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
272 HeapFree(GetProcessHeap(), 0, szKey);
277 rc = RegSetValueExW(hKey, pwszValueName, 0, dwValueType, pbValueData,
283 return rc ? FALSE : TRUE;
286 /* Gets the registered function named szFuncName for dwCertEncodingType and
287 * lpszStructType, or NULL if one could not be found. *lib will be set to the
288 * handle of the module it's in, or NULL if no module was loaded. If the
289 * return value is NULL, *lib will also be NULL, to simplify error handling.
291 static void *CRYPT_GetFunc(DWORD dwCertEncodingType, LPCSTR lpszStructType,
292 LPCSTR szFuncName, HMODULE *lib)
295 char *szKey = CRYPT_GetKeyName(dwCertEncodingType, szFuncName,
297 const char *funcName;
300 DWORD type, size = 0;
302 TRACE("(%08lx %s %s %p)\n", dwCertEncodingType, debugstr_a(lpszStructType),
303 debugstr_a(szFuncName), lib);
306 r = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
307 HeapFree(GetProcessHeap(), 0, szKey);
308 if(r != ERROR_SUCCESS)
311 RegQueryValueExA(hKey, "FuncName", NULL, &type, NULL, &size);
312 if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ)
314 funcName = HeapAlloc(GetProcessHeap(), 0, size);
315 RegQueryValueExA(hKey, "FuncName", NULL, &type, (LPBYTE)funcName,
319 funcName = szFuncName;
320 RegQueryValueExW(hKey, szDllName, NULL, &type, NULL, &size);
321 if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ)
323 LPWSTR dllName = HeapAlloc(GetProcessHeap(), 0, size);
325 RegQueryValueExW(hKey, szDllName, NULL, &type, (LPBYTE)dllName,
327 *lib = LoadLibraryW(dllName);
330 ret = GetProcAddress(*lib, funcName);
333 /* Unload the library, the caller doesn't want to unload it
334 * when the return value is NULL.
340 HeapFree(GetProcessHeap(), 0, dllName);
342 if (funcName != szFuncName)
343 HeapFree(GetProcessHeap(), 0, (char *)funcName);
344 TRACE("returning %p\n", ret);
348 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
351 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
352 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
356 CryptEncodeObjectFunc pCryptEncodeObject;
358 TRACE("(0x%08lx, %s, %p, %p, %p)\n",
359 dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
360 "(integer value)", pvStructInfo, pbEncoded, pcbEncoded);
362 if (!pbEncoded && !pcbEncoded)
364 SetLastError(ERROR_INVALID_PARAMETER);
368 /* Try registered DLL first.. */
370 (CryptEncodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType,
371 lpszStructType, "CryptEncodeObject", &lib);
372 if (pCryptEncodeObject)
374 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
375 pvStructInfo, pbEncoded, pcbEncoded);
380 /* If not, use CryptEncodeObjectEx */
381 ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
382 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
387 /* Helper function to check *pcbEncoded, set it to the required size, and
388 * optionally to allocate memory. Assumes pbEncoded is not NULL.
389 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
390 * pointer to the newly allocated memory.
392 static BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags,
393 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded,
398 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
400 if (pEncodePara && pEncodePara->pfnAlloc)
401 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
403 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
404 if (!*(BYTE **)pbEncoded)
407 *pcbEncoded = bytesNeeded;
409 else if (bytesNeeded > *pcbEncoded)
411 *pcbEncoded = bytesNeeded;
412 SetLastError(ERROR_MORE_DATA);
418 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
420 DWORD bytesNeeded, significantBytes = 0;
428 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
429 temp <<= 8, significantBytes--)
431 bytesNeeded = significantBytes + 1;
435 *pcbEncoded = bytesNeeded;
438 if (*pcbEncoded < bytesNeeded)
440 SetLastError(ERROR_MORE_DATA);
444 *pbEncoded = (BYTE)len;
449 *pbEncoded++ = significantBytes | 0x80;
450 for (i = 0; i < significantBytes; i++)
452 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
456 *pcbEncoded = bytesNeeded;
460 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
464 DWORD dataLen, octetsLen, lenBytes, size;
466 ret = CRYPT_AsnEncodeOid(ext->pszObjId, NULL, &size);
472 ret = CRYPT_EncodeBool(TRUE, NULL, &size);
477 ret = CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, X509_OCTET_STRING,
478 &ext->Value, 0, NULL, NULL, &octetsLen);
479 dataLen += octetsLen;
481 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
482 *pcbEncoded = 1 + lenBytes + dataLen;
484 if (ret && pbEncoded)
486 *pbEncoded++ = ASN_SEQUENCE;
487 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
488 pbEncoded += lenBytes;
489 ret = CRYPT_AsnEncodeOid(ext->pszObjId, pbEncoded, &size);
495 ret = CRYPT_EncodeBool(TRUE, pbEncoded, &size);
500 ret = CRYPT_AsnEncodeOctets(X509_ASN_ENCODING,
501 X509_OCTET_STRING, &ext->Value, 0, NULL, pbEncoded,
503 pbEncoded += octetsLen;
510 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
511 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
512 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
518 DWORD bytesNeeded, dataLen, lenBytes, i;
519 CERT_EXTENSIONS *exts = (CERT_EXTENSIONS *)pvStructInfo;
522 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
526 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
530 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
531 bytesNeeded = 1 + lenBytes + dataLen;
533 *pcbEncoded = bytesNeeded;
536 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
537 pcbEncoded, bytesNeeded)))
539 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
540 pbEncoded = *(BYTE **)pbEncoded;
541 *pbEncoded++ = ASN_SEQUENCEOF;
542 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
543 pbEncoded += lenBytes;
544 for (i = 0; i < exts->cExtension; i++)
548 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
558 SetLastError(STATUS_ACCESS_VIOLATION);
565 static BOOL WINAPI CRYPT_AsnEncodeOid(LPCSTR pszObjId, BYTE *pbEncoded,
568 DWORD bytesNeeded = 0, lenBytes;
578 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
580 SetLastError(CRYPT_E_ASN1_ERROR);
584 firstByte = val1 * 40 + val2;
585 ptr = pszObjId + firstPos;
590 /* note I assume each component is at most 32-bits long in base 2 */
591 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
593 if (val1 >= 0x10000000)
595 else if (val1 >= 0x200000)
597 else if (val1 >= 0x4000)
599 else if (val1 >= 0x80)
609 SetLastError(CRYPT_E_ASN1_ERROR);
613 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
617 bytesNeeded += 1 + lenBytes;
620 if (*pbEncoded < bytesNeeded)
622 SetLastError(ERROR_MORE_DATA);
627 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
628 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
629 pbEncoded += lenBytes;
635 *pbEncoded++ = firstByte;
636 ptr = pszObjId + firstPos;
639 sscanf(ptr, "%d%n", &val, &pos);
641 unsigned char outBytes[5];
644 if (val >= 0x10000000)
646 else if (val >= 0x200000)
648 else if (val >= 0x4000)
650 else if (val >= 0x80)
654 for (i = numBytes; i > 0; i--)
656 outBytes[i - 1] = val & 0x7f;
659 for (i = 0; i < numBytes - 1; i++)
660 *pbEncoded++ = outBytes[i] | 0x80;
661 *pbEncoded++ = outBytes[i];
670 *pcbEncoded = bytesNeeded;
674 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
675 CERT_NAME_VALUE *value, BYTE *pbEncoded, DWORD *pcbEncoded)
678 DWORD bytesNeeded, lenBytes, encodedLen;
681 switch (value->dwValueType)
683 case CERT_RDN_NUMERIC_STRING:
684 tag = ASN_NUMERICSTRING;
685 encodedLen = value->Value.cbData;
687 case CERT_RDN_PRINTABLE_STRING:
688 tag = ASN_PRINTABLESTRING;
689 encodedLen = value->Value.cbData;
691 case CERT_RDN_IA5_STRING:
693 encodedLen = value->Value.cbData;
695 case CERT_RDN_ANY_TYPE:
696 /* explicitly disallowed */
697 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
700 FIXME("String type %ld unimplemented\n", value->dwValueType);
703 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
704 bytesNeeded = 1 + lenBytes + encodedLen;
707 if (*pcbEncoded < bytesNeeded)
709 SetLastError(ERROR_MORE_DATA);
715 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
716 pbEncoded += lenBytes;
717 switch (value->dwValueType)
719 case CERT_RDN_NUMERIC_STRING:
720 case CERT_RDN_PRINTABLE_STRING:
721 case CERT_RDN_IA5_STRING:
722 memcpy(pbEncoded, value->Value.pbData, value->Value.cbData);
726 *pcbEncoded = bytesNeeded;
730 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
731 CERT_RDN_ATTR *attr, BYTE *pbEncoded, DWORD *pcbEncoded)
733 DWORD bytesNeeded = 0, lenBytes, size;
736 ret = CRYPT_AsnEncodeOid(attr->pszObjId, NULL, &size);
740 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
741 * with dwValueType, so "cast" it to get its encoded size
743 ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType,
744 (CERT_NAME_VALUE *)&attr->dwValueType, NULL, &size);
748 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
749 bytesNeeded += 1 + lenBytes;
752 if (*pcbEncoded < bytesNeeded)
754 SetLastError(ERROR_MORE_DATA);
759 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SEQUENCE;
760 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
762 pbEncoded += lenBytes;
763 size = bytesNeeded - 1 - lenBytes;
764 ret = CRYPT_AsnEncodeOid(attr->pszObjId, pbEncoded, &size);
768 size = bytesNeeded - 1 - lenBytes - size;
769 ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType,
770 (CERT_NAME_VALUE *)&attr->dwValueType, pbEncoded,
775 *pcbEncoded = bytesNeeded;
781 static int BLOBComp(const void *l, const void *r)
783 CRYPT_DER_BLOB *a = (CRYPT_DER_BLOB *)l, *b = (CRYPT_DER_BLOB *)r;
786 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
787 ret = a->cbData - b->cbData;
791 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
793 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
794 BYTE *pbEncoded, DWORD *pcbEncoded)
797 CRYPT_DER_BLOB *blobs = NULL;
801 DWORD bytesNeeded = 0, lenBytes, i;
806 blobs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
807 rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
811 for (i = 0; ret && i < rdn->cRDNAttr; i++)
813 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
814 NULL, &blobs[i].cbData);
816 bytesNeeded += blobs[i].cbData;
820 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
821 bytesNeeded += 1 + lenBytes;
824 if (*pcbEncoded < bytesNeeded)
826 SetLastError(ERROR_MORE_DATA);
831 for (i = 0; ret && i < rdn->cRDNAttr; i++)
833 blobs[i].pbData = HeapAlloc(GetProcessHeap(), 0,
835 if (!blobs[i].pbData)
838 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
839 &rdn->rgRDNAttr[i], blobs[i].pbData,
844 qsort(blobs, rdn->cRDNAttr, sizeof(CRYPT_DER_BLOB),
846 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
847 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
849 pbEncoded += lenBytes;
850 for (i = 0; ret && i < rdn->cRDNAttr; i++)
852 memcpy(pbEncoded, blobs[i].pbData, blobs[i].cbData);
853 pbEncoded += blobs[i].cbData;
858 *pcbEncoded = bytesNeeded;
862 for (i = 0; i < rdn->cRDNAttr; i++)
863 HeapFree(GetProcessHeap(), 0, blobs[i].pbData);
868 SetLastError(STATUS_ACCESS_VIOLATION);
872 HeapFree(GetProcessHeap(), 0, blobs);
876 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
877 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
878 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
884 CERT_NAME_INFO *info = (CERT_NAME_INFO *)pvStructInfo;
885 DWORD bytesNeeded = 0, lenBytes, size, i;
887 TRACE("encoding name with %ld RDNs\n", info->cRDN);
889 for (i = 0; ret && i < info->cRDN; i++)
891 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], NULL,
896 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
897 bytesNeeded += 1 + lenBytes;
901 *pcbEncoded = bytesNeeded;
904 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
905 pbEncoded, pcbEncoded, bytesNeeded)))
907 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
908 pbEncoded = *(BYTE **)pbEncoded;
909 *pbEncoded++ = ASN_SEQUENCEOF;
910 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
912 pbEncoded += lenBytes;
913 for (i = 0; ret && i < info->cRDN; i++)
916 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
917 &info->rgRDN[i], pbEncoded, &size);
930 SetLastError(STATUS_ACCESS_VIOLATION);
937 static BOOL CRYPT_EncodeBool(BOOL val, BYTE *pbEncoded, DWORD *pcbEncoded)
947 SetLastError(ERROR_MORE_DATA);
951 *pbEncoded++ = ASN_BOOL;
953 *pbEncoded++ = val ? 0xff : 0;
957 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
958 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
959 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
965 CERT_BASIC_CONSTRAINTS2_INFO *info =
966 (CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
967 DWORD bytesNeeded = 0, lenBytes, caLen = 0, pathConstraintLen = 0;
972 ret = CRYPT_EncodeBool(TRUE, NULL, &caLen);
974 bytesNeeded += caLen;
976 if (info->fPathLenConstraint)
978 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
979 &info->dwPathLenConstraint, 0, NULL, NULL, &pathConstraintLen);
981 bytesNeeded += pathConstraintLen;
985 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
986 bytesNeeded += 1 + lenBytes;
988 *pcbEncoded = bytesNeeded;
991 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
992 pbEncoded, pcbEncoded, bytesNeeded)))
994 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
995 pbEncoded = *(BYTE **)pbEncoded;
996 *pbEncoded++ = ASN_SEQUENCE;
997 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded,
999 pbEncoded += lenBytes;
1002 ret = CRYPT_EncodeBool(TRUE, pbEncoded, &caLen);
1006 if (info->fPathLenConstraint)
1008 ret = CRYPT_AsnEncodeInt(dwCertEncodingType,
1009 X509_INTEGER, &info->dwPathLenConstraint, 0, NULL,
1010 pbEncoded, &pathConstraintLen);
1016 __EXCEPT(page_fault)
1018 SetLastError(STATUS_ACCESS_VIOLATION);
1025 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
1026 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1027 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1033 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
1034 DWORD bytesNeeded, lenBytes;
1036 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
1037 bytesNeeded = 1 + lenBytes + blob->cbData;
1040 *pcbEncoded = bytesNeeded;
1045 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1046 pcbEncoded, bytesNeeded)))
1048 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1049 pbEncoded = *(BYTE **)pbEncoded;
1050 *pbEncoded++ = ASN_OCTETSTRING;
1051 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
1052 pbEncoded += lenBytes;
1054 memcpy(pbEncoded, blob->pbData, blob->cbData);
1058 __EXCEPT(page_fault)
1060 SetLastError(STATUS_ACCESS_VIOLATION);
1067 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
1068 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1069 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1075 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
1076 DWORD bytesNeeded, lenBytes, dataBytes;
1079 /* yep, MS allows cUnusedBits to be >= 8 */
1080 if (blob->cbData * 8 > blob->cUnusedBits)
1082 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
1083 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
1091 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
1092 bytesNeeded = 1 + lenBytes + dataBytes + 1;
1095 *pcbEncoded = bytesNeeded;
1100 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1101 pcbEncoded, bytesNeeded)))
1103 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1104 pbEncoded = *(BYTE **)pbEncoded;
1105 *pbEncoded++ = ASN_BITSTRING;
1106 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
1107 pbEncoded += lenBytes;
1108 *pbEncoded++ = unusedBits;
1111 BYTE mask = 0xff << unusedBits;
1115 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
1116 pbEncoded += dataBytes - 1;
1118 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
1123 __EXCEPT(page_fault)
1125 SetLastError(STATUS_ACCESS_VIOLATION);
1132 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
1133 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1134 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1136 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
1138 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
1139 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1142 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
1143 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1144 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1150 DWORD significantBytes, lenBytes;
1151 BYTE padByte = 0, bytesNeeded;
1153 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
1155 significantBytes = blob->cbData;
1156 if (significantBytes)
1158 if (blob->pbData[significantBytes - 1] & 0x80)
1160 /* negative, lop off leading (little-endian) 0xffs */
1161 for (; significantBytes > 0 &&
1162 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
1164 if (blob->pbData[significantBytes - 1] < 0x80)
1172 /* positive, lop off leading (little-endian) zeroes */
1173 for (; significantBytes > 0 &&
1174 !blob->pbData[significantBytes - 1]; significantBytes--)
1176 if (significantBytes == 0)
1177 significantBytes = 1;
1178 if (blob->pbData[significantBytes - 1] > 0x7f)
1186 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
1188 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
1189 bytesNeeded = 1 + lenBytes + significantBytes;
1194 *pcbEncoded = bytesNeeded;
1199 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1200 pcbEncoded, bytesNeeded)))
1202 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1203 pbEncoded = *(BYTE **)pbEncoded;
1204 *pbEncoded++ = ASN_INTEGER;
1207 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
1208 pbEncoded += lenBytes;
1209 *pbEncoded++ = padByte;
1213 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
1214 pbEncoded += lenBytes;
1216 for (; significantBytes > 0; significantBytes--)
1217 *(pbEncoded++) = blob->pbData[significantBytes - 1];
1221 __EXCEPT(page_fault)
1223 SetLastError(STATUS_ACCESS_VIOLATION);
1230 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
1231 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1232 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1238 DWORD significantBytes, lenBytes;
1241 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
1243 significantBytes = blob->cbData;
1244 if (significantBytes)
1246 /* positive, lop off leading (little-endian) zeroes */
1247 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
1250 if (significantBytes == 0)
1251 significantBytes = 1;
1252 if (blob->pbData[significantBytes - 1] > 0x7f)
1256 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
1258 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
1259 bytesNeeded = 1 + lenBytes + significantBytes;
1264 *pcbEncoded = bytesNeeded;
1269 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1270 pcbEncoded, bytesNeeded)))
1272 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1273 pbEncoded = *(BYTE **)pbEncoded;
1274 *pbEncoded++ = ASN_INTEGER;
1277 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
1278 pbEncoded += lenBytes;
1283 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
1284 pbEncoded += lenBytes;
1286 for (; significantBytes > 0; significantBytes--)
1287 *(pbEncoded++) = blob->pbData[significantBytes - 1];
1291 __EXCEPT(page_fault)
1293 SetLastError(STATUS_ACCESS_VIOLATION);
1300 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
1301 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1302 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1304 CRYPT_INTEGER_BLOB blob;
1307 /* Encode as an unsigned integer, then change the tag to enumerated */
1308 blob.cbData = sizeof(DWORD);
1309 blob.pbData = (BYTE *)pvStructInfo;
1310 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
1311 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1312 if (ret && pbEncoded)
1314 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1315 pbEncoded = *(BYTE **)pbEncoded;
1316 pbEncoded[0] = ASN_ENUMERATED;
1321 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
1322 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1323 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1330 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
1331 * temporary buffer because the output buffer is not NULL-terminated.
1334 static const DWORD bytesNeeded = sizeof(buf) - 1;
1338 *pcbEncoded = bytesNeeded;
1343 /* Sanity check the year, this is a two-digit year format */
1344 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
1346 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
1348 SetLastError(CRYPT_E_BAD_ENCODE);
1353 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1354 pbEncoded, pcbEncoded, bytesNeeded)))
1356 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1357 pbEncoded = *(BYTE **)pbEncoded;
1358 buf[0] = ASN_UTCTIME;
1359 buf[1] = bytesNeeded - 2;
1360 snprintf(buf + 2, sizeof(buf) - 2,
1361 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
1362 sysTime.wYear - 2000 : sysTime.wYear - 1900,
1363 sysTime.wDay, sysTime.wMonth, sysTime.wHour,
1364 sysTime.wMinute, sysTime.wSecond);
1365 memcpy(pbEncoded, buf, bytesNeeded);
1370 __EXCEPT(page_fault)
1372 SetLastError(STATUS_ACCESS_VIOLATION);
1379 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
1380 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1381 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1388 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
1389 * temporary buffer because the output buffer is not NULL-terminated.
1392 static const DWORD bytesNeeded = sizeof(buf) - 1;
1396 *pcbEncoded = bytesNeeded;
1401 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
1404 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1405 pcbEncoded, bytesNeeded);
1408 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1409 pbEncoded = *(BYTE **)pbEncoded;
1410 buf[0] = ASN_GENERALTIME;
1411 buf[1] = bytesNeeded - 2;
1412 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
1413 sysTime.wYear, sysTime.wDay, sysTime.wMonth, sysTime.wHour,
1414 sysTime.wMinute, sysTime.wSecond);
1415 memcpy(pbEncoded, buf, bytesNeeded);
1419 __EXCEPT(page_fault)
1421 SetLastError(STATUS_ACCESS_VIOLATION);
1428 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
1429 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1430 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1438 /* Check the year, if it's in the UTCTime range call that encode func */
1439 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
1441 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
1442 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
1443 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1445 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
1446 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1449 __EXCEPT(page_fault)
1451 SetLastError(STATUS_ACCESS_VIOLATION);
1458 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
1459 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1460 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1466 DWORD bytesNeeded, dataLen, lenBytes, i;
1467 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
1469 for (i = 0, dataLen = 0; i < seq->cValue; i++)
1470 dataLen += seq->rgValue[i].cbData;
1471 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1472 bytesNeeded = 1 + lenBytes + dataLen;
1475 *pcbEncoded = bytesNeeded;
1480 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1481 pcbEncoded, bytesNeeded)))
1483 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1484 pbEncoded = *(BYTE **)pbEncoded;
1485 *pbEncoded++ = ASN_SEQUENCEOF;
1486 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1487 pbEncoded += lenBytes;
1488 for (i = 0; i < seq->cValue; i++)
1490 memcpy(pbEncoded, seq->rgValue[i].pbData,
1491 seq->rgValue[i].cbData);
1492 pbEncoded += seq->rgValue[i].cbData;
1497 __EXCEPT(page_fault)
1499 SetLastError(STATUS_ACCESS_VIOLATION);
1506 typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *,
1507 DWORD, PCRYPT_ENCODE_PARA, BYTE *, DWORD *);
1509 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
1510 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
1511 void *pvEncoded, DWORD *pcbEncoded)
1515 CryptEncodeObjectExFunc encodeFunc = NULL;
1517 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n",
1518 dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
1519 "(integer value)", pvStructInfo, dwFlags, pEncodePara, pvEncoded,
1522 if (!pvEncoded && !pcbEncoded)
1524 SetLastError(ERROR_INVALID_PARAMETER);
1527 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
1528 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
1530 SetLastError(ERROR_FILE_NOT_FOUND);
1534 SetLastError(NOERROR);
1535 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
1536 *(BYTE **)pvEncoded = NULL;
1537 if (!HIWORD(lpszStructType))
1539 switch (LOWORD(lpszStructType))
1541 case (WORD)X509_EXTENSIONS:
1542 encodeFunc = CRYPT_AsnEncodeExtensions;
1544 case (WORD)X509_NAME:
1545 encodeFunc = CRYPT_AsnEncodeName;
1547 case (WORD)X509_BASIC_CONSTRAINTS2:
1548 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
1550 case (WORD)X509_OCTET_STRING:
1551 encodeFunc = CRYPT_AsnEncodeOctets;
1553 case (WORD)X509_BITS:
1554 case (WORD)X509_KEY_USAGE:
1555 encodeFunc = CRYPT_AsnEncodeBits;
1557 case (WORD)X509_INTEGER:
1558 encodeFunc = CRYPT_AsnEncodeInt;
1560 case (WORD)X509_MULTI_BYTE_INTEGER:
1561 encodeFunc = CRYPT_AsnEncodeInteger;
1563 case (WORD)X509_MULTI_BYTE_UINT:
1564 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
1566 case (WORD)X509_ENUMERATED:
1567 encodeFunc = CRYPT_AsnEncodeEnumerated;
1569 case (WORD)X509_CHOICE_OF_TIME:
1570 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1572 case (WORD)X509_SEQUENCE_OF_ANY:
1573 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
1575 case (WORD)PKCS_UTC_TIME:
1576 encodeFunc = CRYPT_AsnEncodeUtcTime;
1579 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
1582 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
1583 encodeFunc = CRYPT_AsnEncodeExtensions;
1584 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
1585 encodeFunc = CRYPT_AsnEncodeUtcTime;
1586 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
1587 encodeFunc = CRYPT_AsnEncodeEnumerated;
1588 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
1589 encodeFunc = CRYPT_AsnEncodeBits;
1590 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
1591 encodeFunc = CRYPT_AsnEncodeOctets;
1592 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
1593 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
1595 TRACE("OID %s not found or unimplemented, looking for DLL\n",
1596 debugstr_a(lpszStructType));
1598 encodeFunc = (CryptEncodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType,
1599 lpszStructType, "CryptEncodeObjectEx", &lib);
1601 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
1602 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
1604 SetLastError(ERROR_FILE_NOT_FOUND);
1610 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
1611 DWORD, DWORD, void *, DWORD *);
1613 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
1614 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
1615 DWORD *pcbStructInfo)
1619 CryptDecodeObjectFunc pCryptDecodeObject;
1621 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n",
1622 dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
1623 "(integer value)", pbEncoded, cbEncoded, dwFlags, pvStructInfo,
1626 if (!pvStructInfo && !pcbStructInfo)
1628 SetLastError(ERROR_INVALID_PARAMETER);
1632 /* Try registered DLL first.. */
1633 pCryptDecodeObject =
1634 (CryptDecodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType,
1635 lpszStructType, "CryptDecodeObject", &lib);
1636 if (pCryptDecodeObject)
1638 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
1639 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
1644 /* If not, use CryptDecodeObjectEx */
1645 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
1646 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
1651 /* Gets the number of length bytes from the given (leading) length byte */
1652 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
1654 /* Helper function to get the encoded length of the data starting at pbEncoded,
1655 * where pbEncoded[0] is the tag. If the data are too short to contain a
1656 * length or if the length is too large for cbEncoded, sets an appropriate
1657 * error code and returns FALSE.
1659 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
1666 SetLastError(CRYPT_E_ASN1_EOD);
1669 else if (pbEncoded[1] <= 0x7f)
1671 *len = pbEncoded[1];
1676 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
1678 if (lenLen > sizeof(DWORD) + 1)
1680 SetLastError(CRYPT_E_ASN1_LARGE);
1683 else if (lenLen + 2 > cbEncoded)
1685 SetLastError(CRYPT_E_ASN1_CORRUPT);
1696 out |= *pbEncoded++;
1698 if (out + lenLen + 1 > cbEncoded)
1700 SetLastError(CRYPT_E_ASN1_EOD);
1713 /* Helper function to check *pcbStructInfo, set it to the required size, and
1714 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
1715 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
1716 * pointer to the newly allocated memory.
1718 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
1719 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
1724 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1726 if (pDecodePara && pDecodePara->pfnAlloc)
1727 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
1729 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
1730 if (!*(BYTE **)pvStructInfo)
1733 *pcbStructInfo = bytesNeeded;
1735 else if (*pcbStructInfo < bytesNeeded)
1737 *pcbStructInfo = bytesNeeded;
1738 SetLastError(ERROR_MORE_DATA);
1744 /* Warning: assumes ext->Value.pbData is set ahead of time! */
1745 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1746 DWORD dwFlags, CERT_EXTENSION *ext, DWORD *pcbExt)
1750 if (pbEncoded[0] == ASN_SEQUENCE)
1752 DWORD dataLen, bytesNeeded;
1754 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1756 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]), oidLenBytes = 0;
1758 bytesNeeded = sizeof(CERT_EXTENSION);
1761 const BYTE *ptr = pbEncoded + 1 + lenBytes;
1762 DWORD encodedOidLen, oidLen;
1764 CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
1766 oidLenBytes = GET_LEN_BYTES(ptr[1]);
1767 ret = CRYPT_AsnDecodeOid(ptr, cbEncoded - (ptr - pbEncoded),
1768 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &oidLen);
1771 bytesNeeded += oidLen;
1772 ptr += 1 + encodedOidLen + oidLenBytes;
1773 if (*ptr == ASN_BOOL)
1775 ret = CRYPT_AsnDecodeOctets(X509_ASN_ENCODING,
1776 X509_OCTET_STRING, ptr, cbEncoded - (ptr - pbEncoded),
1777 0, NULL, NULL, &dataLen);
1778 bytesNeeded += dataLen;
1782 *pcbExt = bytesNeeded;
1783 else if (*pcbExt < bytesNeeded)
1785 SetLastError(ERROR_MORE_DATA);
1790 ptr = pbEncoded + 2 + lenBytes + encodedOidLen +
1792 if (*ptr == ASN_BOOL)
1794 CRYPT_DecodeBool(ptr, cbEncoded -
1795 (ptr - pbEncoded), &ext->fCritical);
1798 ret = CRYPT_AsnDecodeOctets(X509_ASN_ENCODING,
1799 X509_OCTET_STRING, ptr,
1800 cbEncoded - (ptr - pbEncoded),
1801 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
1802 &ext->Value, &dataLen);
1805 ext->pszObjId = ext->Value.pbData +
1807 ptr = pbEncoded + 1 + lenBytes;
1808 ret = CRYPT_AsnDecodeOid(ptr,
1809 cbEncoded - (ptr - pbEncoded),
1810 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
1811 ext->pszObjId, &oidLen);
1819 SetLastError(CRYPT_E_ASN1_EOD);
1826 SetLastError(CRYPT_E_ASN1_BADTAG);
1832 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1833 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1834 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1840 if (pbEncoded[0] == ASN_SEQUENCEOF)
1842 DWORD dataLen, bytesNeeded;
1844 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1846 DWORD cExtension = 0;
1847 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1849 bytesNeeded = sizeof(CERT_EXTENSIONS);
1855 for (ptr = pbEncoded + 1 + lenBytes; ret &&
1856 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1858 ret = CRYPT_AsnDecodeExtension(ptr,
1859 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
1865 bytesNeeded += size;
1866 ret = CRYPT_GetLen(ptr,
1867 cbEncoded - (ptr - pbEncoded), &nextLen);
1869 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
1876 *pcbStructInfo = bytesNeeded;
1877 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
1878 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
1883 CERT_EXTENSIONS *exts;
1885 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1886 pvStructInfo = *(BYTE **)pvStructInfo;
1887 *pcbStructInfo = bytesNeeded;
1888 exts = (CERT_EXTENSIONS *)pvStructInfo;
1889 exts->cExtension = cExtension;
1890 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1891 sizeof(CERT_EXTENSIONS));
1892 nextData = (BYTE *)exts->rgExtension +
1893 exts->cExtension * sizeof(CERT_EXTENSION);
1894 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
1895 i < cExtension && ptr - pbEncoded - 1 - lenBytes <
1898 exts->rgExtension[i].Value.pbData = nextData;
1900 ret = CRYPT_AsnDecodeExtension(ptr,
1901 cbEncoded - (ptr - pbEncoded), dwFlags,
1902 &exts->rgExtension[i], &size);
1907 bytesNeeded -= size;
1908 /* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG, the
1909 * data may not have been copied.
1911 if (exts->rgExtension[i].Value.pbData ==
1914 exts->rgExtension[i].Value.cbData;
1915 /* Ugly: the OID, if copied, is stored in
1916 * memory after the value, so increment by its
1917 * string length if it's set and points here.
1919 if ((const BYTE *)exts->rgExtension[i].pszObjId
1922 exts->rgExtension[i].pszObjId) + 1;
1923 ret = CRYPT_GetLen(ptr,
1924 cbEncoded - (ptr - pbEncoded), &nextLen);
1926 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
1935 SetLastError(CRYPT_E_ASN1_BADTAG);
1939 __EXCEPT(page_fault)
1941 SetLastError(STATUS_ACCESS_VIOLATION);
1948 /* FIXME: honor the CRYPT_DECODE_SHARE_OID_STRING_FLAG. */
1949 static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded,
1950 DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId)
1956 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1960 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1962 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1967 /* The largest possible string for the first two components
1968 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1973 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1974 pbEncoded[1 + lenBytes] / 40,
1975 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1977 bytesNeeded = strlen(firstTwo) + 1;
1978 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1979 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1981 /* large enough for ".4000000" */
1985 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1992 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1995 SetLastError(CRYPT_E_ASN1_CORRUPT);
2002 snprintf(str, sizeof(str), ".%d", val);
2003 bytesNeeded += strlen(str);
2007 *pcbObjId = bytesNeeded;
2008 else if (*pcbObjId < bytesNeeded)
2010 *pcbObjId = bytesNeeded;
2011 SetLastError(ERROR_MORE_DATA);
2016 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
2017 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
2019 pszObjId += strlen(pszObjId);
2020 for (ptr = pbEncoded + 2 + lenBytes; ret &&
2021 ptr - pbEncoded - 1 - lenBytes < dataLen; )
2025 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
2034 sprintf(pszObjId, ".%d", val);
2035 pszObjId += strlen(pszObjId);
2041 *pcbObjId = bytesNeeded;
2046 SetLastError(CRYPT_E_ASN1_BADTAG);
2050 __EXCEPT(page_fault)
2052 SetLastError(STATUS_ACCESS_VIOLATION);
2059 /* Warning: this assumes the address of value->Value.pbData is already set, in
2060 * order to avoid overwriting memory. (In some cases, it may change it, if it
2061 * doesn't copy anything to memory.) Be sure to set it correctly!
2063 static BOOL WINAPI CRYPT_AsnDecodeNameValue(const BYTE *pbEncoded,
2064 DWORD cbEncoded, DWORD dwFlags, CERT_NAME_VALUE *value, DWORD *pcbValue)
2072 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2074 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2076 switch (pbEncoded[0])
2078 case ASN_NUMERICSTRING:
2079 case ASN_PRINTABLESTRING:
2083 FIXME("Unimplemented string type %02x\n", pbEncoded[0]);
2084 SetLastError(OSS_UNIMPLEMENTED);
2089 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE);
2091 switch (pbEncoded[0])
2093 case ASN_NUMERICSTRING:
2094 case ASN_PRINTABLESTRING:
2096 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2097 bytesNeeded += dataLen;
2101 *pcbValue = bytesNeeded;
2102 else if (*pcbValue < bytesNeeded)
2104 *pcbValue = bytesNeeded;
2105 SetLastError(ERROR_MORE_DATA);
2110 *pcbValue = bytesNeeded;
2111 switch (pbEncoded[0])
2113 case ASN_NUMERICSTRING:
2114 value->dwValueType = CERT_RDN_NUMERIC_STRING;
2116 case ASN_PRINTABLESTRING:
2117 value->dwValueType = CERT_RDN_PRINTABLE_STRING;
2120 value->dwValueType = CERT_RDN_IA5_STRING;
2125 switch (pbEncoded[0])
2127 case ASN_NUMERICSTRING:
2128 case ASN_PRINTABLESTRING:
2130 value->Value.cbData = dataLen;
2131 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2132 value->Value.pbData = (BYTE *)pbEncoded + 1 +
2136 if (!value->Value.pbData)
2138 SetLastError(CRYPT_E_ASN1_INTERNAL);
2142 memcpy(value->Value.pbData,
2143 pbEncoded + 1 + lenBytes, dataLen);
2150 value->Value.cbData = 0;
2151 value->Value.pbData = NULL;
2157 __EXCEPT(page_fault)
2159 SetLastError(STATUS_ACCESS_VIOLATION);
2166 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded,
2167 DWORD cbEncoded, DWORD dwFlags, CERT_RDN_ATTR *attr, DWORD *pcbAttr)
2173 if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SEQUENCE))
2175 DWORD bytesNeeded, dataLen, size;
2178 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2180 /* The data length must be at least 4, two for the tag and
2181 * length for the OID, and two for the string (assuming both
2182 * have short-form lengths.)
2186 SetLastError(CRYPT_E_ASN1_EOD);
2191 bytesNeeded = sizeof(CERT_RDN_ATTR);
2192 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2193 ret = CRYPT_AsnDecodeOid(pbEncoded + 1 + lenBytes,
2194 cbEncoded - 1 - lenBytes, dwFlags, NULL, &size);
2197 /* ugly: need to know the size of the next element of
2198 * the sequence, so get it directly
2200 DWORD objIdOfset = 1 + lenBytes, objIdLen,
2201 nameValueOffset = 0;
2203 ret = CRYPT_GetLen(pbEncoded + objIdOfset,
2204 cbEncoded - objIdOfset, &objIdLen);
2205 bytesNeeded += size;
2206 /* hack: like encoding, this takes advantage of the
2207 * fact that the rest of the structure is identical to
2208 * a CERT_NAME_VALUE.
2212 nameValueOffset = objIdOfset + objIdLen + 1 +
2213 GET_LEN_BYTES(pbEncoded[objIdOfset]);
2214 ret = CRYPT_AsnDecodeNameValue(
2215 pbEncoded + nameValueOffset,
2216 cbEncoded - nameValueOffset, dwFlags, NULL, &size);
2220 bytesNeeded += size;
2222 *pcbAttr = bytesNeeded;
2223 else if (*pcbAttr < bytesNeeded)
2225 *pcbAttr = bytesNeeded;
2226 SetLastError(ERROR_MORE_DATA);
2231 BYTE *originalData = attr->Value.pbData;
2233 *pcbAttr = bytesNeeded;
2234 /* strange: decode the value first, because it
2235 * has a counted size, and we can store the OID
2236 * after it. Keep track of the original data
2237 * pointer, we'll need to know whether it was
2241 ret = CRYPT_AsnDecodeNameValue(
2242 pbEncoded + nameValueOffset,
2243 cbEncoded - nameValueOffset, dwFlags,
2244 (CERT_NAME_VALUE *)&attr->dwValueType, &size);
2249 /* if the data were copied to the
2250 * original location, the OID goes
2251 * after. Otherwise it goes in the
2252 * spot originally reserved for the
2255 if (attr->Value.pbData == originalData)
2257 (LPSTR)(attr->Value.pbData +
2258 attr->Value.cbData);
2260 attr->pszObjId = originalData;
2261 size = bytesNeeded - size;
2262 ret = CRYPT_AsnDecodeOid(
2263 pbEncoded + objIdOfset,
2264 cbEncoded - objIdOfset,
2265 dwFlags, attr->pszObjId, &size);
2268 attr->pszObjId = NULL;
2278 SetLastError(CRYPT_E_ASN1_BADTAG);
2282 __EXCEPT(page_fault)
2284 SetLastError(STATUS_ACCESS_VIOLATION);
2291 static BOOL WINAPI CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
2292 DWORD dwFlags, CERT_RDN *rdn, DWORD *pcbRdn)
2298 if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SETOF))
2302 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2304 DWORD bytesNeeded, cRDNAttr = 0;
2305 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2307 bytesNeeded = sizeof(CERT_RDN);
2313 for (ptr = pbEncoded + 1 + lenBytes; ret &&
2314 ptr - pbEncoded - 1 - lenBytes < dataLen; )
2316 ret = CRYPT_AsnDecodeRdnAttr(ptr,
2317 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
2323 bytesNeeded += size;
2324 ret = CRYPT_GetLen(ptr,
2325 cbEncoded - (ptr - pbEncoded), &nextLen);
2327 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
2334 *pcbRdn = bytesNeeded;
2335 else if (*pcbRdn < bytesNeeded)
2337 *pcbRdn = bytesNeeded;
2338 SetLastError(ERROR_MORE_DATA);
2347 *pcbRdn = bytesNeeded;
2348 rdn->cRDNAttr = cRDNAttr;
2349 rdn->rgRDNAttr = (CERT_RDN_ATTR *)((BYTE *)rdn +
2351 nextData = (BYTE *)rdn->rgRDNAttr +
2352 rdn->cRDNAttr * sizeof(CERT_RDN_ATTR);
2353 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
2354 i < cRDNAttr && ptr - pbEncoded - 1 - lenBytes <
2357 rdn->rgRDNAttr[i].Value.pbData = nextData;
2359 ret = CRYPT_AsnDecodeRdnAttr(ptr,
2360 cbEncoded - (ptr - pbEncoded), dwFlags,
2361 &rdn->rgRDNAttr[i], &size);
2366 bytesNeeded -= size;
2367 /* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG, the
2368 * data may not have been copied.
2370 if (rdn->rgRDNAttr[i].Value.pbData == nextData)
2372 rdn->rgRDNAttr[i].Value.cbData;
2373 /* Ugly: the OID, if copied, is stored in
2374 * memory after the value, so increment by its
2375 * string length if it's set and points here.
2377 if ((const BYTE *)rdn->rgRDNAttr[i].pszObjId
2380 rdn->rgRDNAttr[i].pszObjId) + 1;
2381 ret = CRYPT_GetLen(ptr,
2382 cbEncoded - (ptr - pbEncoded), &nextLen);
2384 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
2393 SetLastError(CRYPT_E_ASN1_BADTAG);
2397 __EXCEPT(page_fault)
2399 SetLastError(STATUS_ACCESS_VIOLATION);
2406 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
2407 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2408 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2414 if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SEQUENCEOF))
2418 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2420 DWORD bytesNeeded, cRDN = 0;
2421 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2423 bytesNeeded = sizeof(CERT_NAME_INFO);
2428 for (ptr = pbEncoded + 1 + lenBytes; ret &&
2429 ptr - pbEncoded - 1 - lenBytes < dataLen; )
2433 ret = CRYPT_AsnDecodeRdn(ptr,
2434 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
2440 bytesNeeded += size;
2441 ret = CRYPT_GetLen(ptr,
2442 cbEncoded - (ptr - pbEncoded), &nextLen);
2444 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
2451 *pcbStructInfo = bytesNeeded;
2452 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
2453 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
2455 CERT_NAME_INFO *info;
2457 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2458 pvStructInfo = *(BYTE **)pvStructInfo;
2459 info = (CERT_NAME_INFO *)pvStructInfo;
2461 if (info->cRDN == 0)
2469 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
2470 sizeof(CERT_NAME_INFO));
2471 nextData = (BYTE *)info->rgRDN +
2472 info->cRDN * sizeof(CERT_RDN);
2473 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
2474 i < cRDN && ptr - pbEncoded - 1 - lenBytes <
2477 info->rgRDN[i].rgRDNAttr =
2478 (CERT_RDN_ATTR *)nextData;
2480 ret = CRYPT_AsnDecodeRdn(ptr,
2481 cbEncoded - (ptr - pbEncoded), dwFlags,
2482 &info->rgRDN[i], &size);
2488 bytesNeeded -= size;
2489 ret = CRYPT_GetLen(ptr,
2490 cbEncoded - (ptr - pbEncoded), &nextLen);
2492 ptr += nextLen + 1 +
2493 GET_LEN_BYTES(ptr[1]);
2501 SetLastError(CRYPT_E_ASN1_BADTAG);
2507 __EXCEPT(page_fault)
2509 SetLastError(STATUS_ACCESS_VIOLATION);
2516 static BOOL WINAPI CRYPT_DecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2521 SetLastError(CRYPT_E_ASN1_CORRUPT);
2524 if (pbEncoded[0] != ASN_BOOL)
2526 SetLastError(CRYPT_E_ASN1_BADTAG);
2529 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2531 SetLastError(CRYPT_E_ASN1_CORRUPT);
2534 if (pbEncoded[1] > 1)
2536 SetLastError(CRYPT_E_ASN1_CORRUPT);
2539 *val = pbEncoded[2] ? TRUE : FALSE;
2543 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2544 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2545 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2551 if (pbEncoded[0] == ASN_SEQUENCE)
2555 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2557 /* sanity-check length, space enough for 7 bytes of integer and
2562 SetLastError(CRYPT_E_ASN1_CORRUPT);
2567 DWORD bytesNeeded = sizeof(CERT_BASIC_CONSTRAINTS2_INFO);
2570 *pcbStructInfo = bytesNeeded;
2574 CERT_BASIC_CONSTRAINTS2_INFO info = { 0 };
2576 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2577 pbEncoded += 1 + lenBytes;
2578 cbEncoded -= 1 + lenBytes;
2583 if (pbEncoded[0] == ASN_BOOL)
2585 ret = CRYPT_DecodeBool(pbEncoded, cbEncoded,
2589 cbEncoded -= 2 + pbEncoded[1];
2590 pbEncoded += 2 + pbEncoded[1];
2593 if (ret && cbEncoded && pbEncoded[0] == ASN_INTEGER)
2595 size = sizeof(info.dwPathLenConstraint);
2596 ret = CRYPT_AsnDecodeInt(dwCertEncodingType,
2597 X509_INTEGER, pbEncoded, cbEncoded, 0, NULL,
2598 &info.dwPathLenConstraint, &size);
2601 cbEncoded -= 2 + pbEncoded[1];
2602 pbEncoded += 2 + pbEncoded[1];
2605 SetLastError(CRYPT_E_ASN1_CORRUPT);
2609 info.fPathLenConstraint = TRUE;
2615 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
2616 pDecodePara, pvStructInfo, pcbStructInfo,
2619 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2620 pvStructInfo = *(BYTE **)pvStructInfo;
2621 memcpy(pvStructInfo, &info,
2622 sizeof(CERT_BASIC_CONSTRAINTS2_INFO));
2631 SetLastError(CRYPT_E_ASN1_BADTAG);
2635 __EXCEPT(page_fault)
2637 SetLastError(STATUS_ACCESS_VIOLATION);
2644 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2645 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2646 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2652 if (pbEncoded[0] == ASN_OCTETSTRING)
2654 DWORD bytesNeeded, dataLen;
2656 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2658 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2659 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2661 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2663 *pcbStructInfo = bytesNeeded;
2664 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2665 pvStructInfo, pcbStructInfo, bytesNeeded)))
2667 CRYPT_DATA_BLOB *blob;
2668 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2670 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2671 pvStructInfo = *(BYTE **)pvStructInfo;
2672 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2673 blob->cbData = dataLen;
2674 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2675 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2678 blob->pbData = (BYTE *)pvStructInfo +
2679 sizeof(CRYPT_DATA_BLOB);
2681 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2689 SetLastError(CRYPT_E_ASN1_BADTAG);
2693 __EXCEPT(page_fault)
2695 SetLastError(STATUS_ACCESS_VIOLATION);
2702 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2703 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2704 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2710 if (pbEncoded[0] == ASN_BITSTRING)
2712 DWORD bytesNeeded, dataLen;
2714 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2716 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2717 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2719 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2721 *pcbStructInfo = bytesNeeded;
2722 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2723 pvStructInfo, pcbStructInfo, bytesNeeded)))
2725 CRYPT_BIT_BLOB *blob;
2727 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2728 pvStructInfo = *(BYTE **)pvStructInfo;
2729 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2730 blob->cbData = dataLen - 1;
2731 blob->cUnusedBits = *(pbEncoded + 1 +
2732 GET_LEN_BYTES(pbEncoded[1]));
2733 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2734 blob->pbData = (BYTE *)pbEncoded + 2 +
2735 GET_LEN_BYTES(pbEncoded[1]);
2738 blob->pbData = (BYTE *)pvStructInfo +
2739 sizeof(CRYPT_BIT_BLOB);
2742 BYTE mask = 0xff << blob->cUnusedBits;
2744 memcpy(blob->pbData, pbEncoded + 2 +
2745 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2746 blob->pbData[blob->cbData - 1] &= mask;
2754 SetLastError(CRYPT_E_ASN1_BADTAG);
2758 __EXCEPT(page_fault)
2760 SetLastError(STATUS_ACCESS_VIOLATION);
2767 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2768 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2769 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2775 *pcbStructInfo = sizeof(int);
2780 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2781 DWORD size = sizeof(buf);
2783 ret = CRYPT_AsnDecodeInteger(dwCertEncodingType,
2784 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf, &size);
2787 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2789 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2790 pvStructInfo, pcbStructInfo, sizeof(int))))
2794 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2795 pvStructInfo = *(BYTE **)pvStructInfo;
2796 if (blob->pbData[blob->cbData - 1] & 0x80)
2798 /* initialize to a negative value to sign-extend */
2803 for (i = 0; i < blob->cbData; i++)
2806 val |= blob->pbData[blob->cbData - i - 1];
2808 memcpy(pvStructInfo, &val, sizeof(int));
2811 else if (GetLastError() == ERROR_MORE_DATA)
2812 SetLastError(CRYPT_E_ASN1_LARGE);
2814 __EXCEPT(page_fault)
2816 SetLastError(STATUS_ACCESS_VIOLATION);
2823 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2824 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2825 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2831 if (pbEncoded[0] == ASN_INTEGER)
2833 DWORD bytesNeeded, dataLen;
2835 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2837 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2839 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2841 *pcbStructInfo = bytesNeeded;
2842 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2843 pvStructInfo, pcbStructInfo, bytesNeeded)))
2845 CRYPT_INTEGER_BLOB *blob;
2847 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2848 pvStructInfo = *(BYTE **)pvStructInfo;
2849 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2850 blob->cbData = dataLen;
2851 blob->pbData = (BYTE *)pvStructInfo +
2852 sizeof(CRYPT_INTEGER_BLOB);
2857 for (i = 0; i < blob->cbData; i++)
2858 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2866 SetLastError(CRYPT_E_ASN1_BADTAG);
2870 __EXCEPT(page_fault)
2872 SetLastError(STATUS_ACCESS_VIOLATION);
2879 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
2880 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2881 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2887 if (pbEncoded[0] == ASN_INTEGER)
2889 DWORD bytesNeeded, dataLen;
2890 CRYPT_INTEGER_BLOB *blob;
2892 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2894 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2896 *pcbStructInfo = bytesNeeded;
2897 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2898 pvStructInfo, pcbStructInfo, bytesNeeded)))
2900 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2902 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2903 pvStructInfo = *(BYTE **)pvStructInfo;
2904 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2905 blob->cbData = dataLen;
2906 blob->pbData = (BYTE *)pvStructInfo +
2907 sizeof(CRYPT_INTEGER_BLOB);
2908 /* remove leading zero byte if it exists */
2909 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
2918 for (i = 0; i < blob->cbData; i++)
2919 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2920 pbEncoded[1] - i - 1);
2927 SetLastError(CRYPT_E_ASN1_BADTAG);
2931 __EXCEPT(page_fault)
2933 SetLastError(STATUS_ACCESS_VIOLATION);
2940 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
2941 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2942 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2948 *pcbStructInfo = sizeof(int);
2953 if (pbEncoded[0] == ASN_ENUMERATED)
2955 unsigned int val = 0, i;
2959 SetLastError(CRYPT_E_ASN1_EOD);
2962 else if (pbEncoded[1] == 0)
2964 SetLastError(CRYPT_E_ASN1_CORRUPT);
2969 /* A little strange looking, but we have to accept a sign byte:
2970 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
2971 * assuming a small length is okay here, it has to be in short
2974 if (pbEncoded[1] > sizeof(unsigned int) + 1)
2976 SetLastError(CRYPT_E_ASN1_LARGE);
2979 for (i = 0; i < pbEncoded[1]; i++)
2982 val |= pbEncoded[2 + i];
2984 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2985 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
2987 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2988 pvStructInfo = *(BYTE **)pvStructInfo;
2989 memcpy(pvStructInfo, &val, sizeof(unsigned int));
2995 SetLastError(CRYPT_E_ASN1_BADTAG);
2999 __EXCEPT(page_fault)
3001 SetLastError(STATUS_ACCESS_VIOLATION);
3008 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3011 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3016 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3018 if (!isdigit(*(pbEncoded))) \
3020 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3026 (word) += *(pbEncoded)++ - '0'; \
3031 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3032 SYSTEMTIME *sysTime)
3038 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3040 WORD hours, minutes = 0;
3041 BYTE sign = *pbEncoded++;
3044 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3045 if (ret && hours >= 24)
3047 SetLastError(CRYPT_E_ASN1_CORRUPT);
3052 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3053 if (ret && minutes >= 60)
3055 SetLastError(CRYPT_E_ASN1_CORRUPT);
3063 sysTime->wHour += hours;
3064 sysTime->wMinute += minutes;
3068 if (hours > sysTime->wHour)
3071 sysTime->wHour = 24 - (hours - sysTime->wHour);
3074 sysTime->wHour -= hours;
3075 if (minutes > sysTime->wMinute)
3078 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3081 sysTime->wMinute -= minutes;
3086 __EXCEPT(page_fault)
3088 SetLastError(STATUS_ACCESS_VIOLATION);
3095 #define MIN_ENCODED_TIME_LENGTH 10
3097 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3098 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3099 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3105 *pcbStructInfo = sizeof(FILETIME);
3110 if (pbEncoded[0] == ASN_UTCTIME)
3114 SetLastError(CRYPT_E_ASN1_EOD);
3117 else if (pbEncoded[1] > 0x7f)
3119 /* long-form date strings really can't be valid */
3120 SetLastError(CRYPT_E_ASN1_CORRUPT);
3125 SYSTEMTIME sysTime = { 0 };
3126 BYTE len = pbEncoded[1];
3128 if (len < MIN_ENCODED_TIME_LENGTH)
3130 SetLastError(CRYPT_E_ASN1_CORRUPT);
3136 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3137 if (sysTime.wYear >= 50)
3138 sysTime.wYear += 1900;
3140 sysTime.wYear += 2000;
3141 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3142 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3143 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3144 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3147 if (len >= 2 && isdigit(*pbEncoded) &&
3148 isdigit(*(pbEncoded + 1)))
3149 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3151 else if (isdigit(*pbEncoded))
3152 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3155 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3158 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3159 pDecodePara, pvStructInfo, pcbStructInfo,
3162 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3163 pvStructInfo = *(BYTE **)pvStructInfo;
3164 ret = SystemTimeToFileTime(&sysTime,
3165 (FILETIME *)pvStructInfo);
3172 SetLastError(CRYPT_E_ASN1_BADTAG);
3176 __EXCEPT(page_fault)
3178 SetLastError(STATUS_ACCESS_VIOLATION);
3185 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3186 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3187 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3193 *pcbStructInfo = sizeof(FILETIME);
3198 if (pbEncoded[0] == ASN_GENERALTIME)
3202 SetLastError(CRYPT_E_ASN1_EOD);
3205 else if (pbEncoded[1] > 0x7f)
3207 /* long-form date strings really can't be valid */
3208 SetLastError(CRYPT_E_ASN1_CORRUPT);
3213 BYTE len = pbEncoded[1];
3215 if (len < MIN_ENCODED_TIME_LENGTH)
3217 SetLastError(CRYPT_E_ASN1_CORRUPT);
3222 SYSTEMTIME sysTime = { 0 };
3225 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3226 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3227 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3228 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3231 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3234 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3236 if (ret && len > 0 && (*pbEncoded == '.' ||
3243 /* workaround macro weirdness */
3244 digits = min(len, 3);
3245 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3246 sysTime.wMilliseconds);
3249 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3252 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3253 pDecodePara, pvStructInfo, pcbStructInfo,
3256 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3257 pvStructInfo = *(BYTE **)pvStructInfo;
3258 ret = SystemTimeToFileTime(&sysTime,
3259 (FILETIME *)pvStructInfo);
3266 SetLastError(CRYPT_E_ASN1_BADTAG);
3270 __EXCEPT(page_fault)
3272 SetLastError(STATUS_ACCESS_VIOLATION);
3279 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3280 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3281 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3287 *pcbStructInfo = sizeof(FILETIME);
3293 if (pbEncoded[0] == ASN_UTCTIME)
3294 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3295 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3297 else if (pbEncoded[0] == ASN_GENERALTIME)
3298 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3299 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3300 pvStructInfo, pcbStructInfo);
3303 SetLastError(CRYPT_E_ASN1_BADTAG);
3307 __EXCEPT(page_fault)
3309 SetLastError(STATUS_ACCESS_VIOLATION);
3316 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3317 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3318 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3324 if (pbEncoded[0] == ASN_SEQUENCEOF)
3326 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3328 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3333 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3334 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3336 ptr = pbEncoded + 1 + lenBytes;
3337 remainingLen = dataLen;
3338 while (ret && remainingLen)
3342 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3345 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3347 remainingLen -= 1 + nextLenBytes + nextLen;
3348 ptr += 1 + nextLenBytes + nextLen;
3349 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3350 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3351 bytesNeeded += 1 + nextLenBytes + nextLen;
3357 CRYPT_SEQUENCE_OF_ANY *seq;
3361 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3362 pvStructInfo, pcbStructInfo, bytesNeeded)))
3364 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3365 pvStructInfo = *(BYTE **)pvStructInfo;
3366 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3367 seq->cValue = cValue;
3368 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3370 nextPtr = (BYTE *)seq->rgValue +
3371 cValue * sizeof(CRYPT_DER_BLOB);
3372 ptr = pbEncoded + 1 + lenBytes;
3373 remainingLen = dataLen;
3375 while (ret && remainingLen)
3379 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3382 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3384 seq->rgValue[i].cbData = 1 + nextLenBytes +
3386 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3387 seq->rgValue[i].pbData = (BYTE *)ptr;
3390 seq->rgValue[i].pbData = nextPtr;
3391 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3393 nextPtr += 1 + nextLenBytes + nextLen;
3395 remainingLen -= 1 + nextLenBytes + nextLen;
3396 ptr += 1 + nextLenBytes + nextLen;
3406 SetLastError(CRYPT_E_ASN1_BADTAG);
3410 __EXCEPT(page_fault)
3412 SetLastError(STATUS_ACCESS_VIOLATION);
3419 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
3420 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
3422 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3423 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3424 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3428 CryptDecodeObjectExFunc decodeFunc = NULL;
3430 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
3431 dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
3432 "(integer value)", pbEncoded, cbEncoded, dwFlags, pDecodePara,
3433 pvStructInfo, pcbStructInfo);
3435 if (!pvStructInfo && !pcbStructInfo)
3437 SetLastError(ERROR_INVALID_PARAMETER);
3440 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3441 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3443 SetLastError(ERROR_FILE_NOT_FOUND);
3446 if (!pbEncoded || !cbEncoded)
3448 SetLastError(CRYPT_E_ASN1_EOD);
3451 if (cbEncoded > MAX_ENCODED_LEN)
3453 SetLastError(CRYPT_E_ASN1_LARGE);
3457 SetLastError(NOERROR);
3458 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
3459 *(BYTE **)pvStructInfo = NULL;
3460 if (!HIWORD(lpszStructType))
3462 switch (LOWORD(lpszStructType))
3464 case (WORD)X509_EXTENSIONS:
3465 decodeFunc = CRYPT_AsnDecodeExtensions;
3467 case (WORD)X509_NAME:
3468 decodeFunc = CRYPT_AsnDecodeName;
3470 case (WORD)X509_BASIC_CONSTRAINTS2:
3471 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3473 case (WORD)X509_OCTET_STRING:
3474 decodeFunc = CRYPT_AsnDecodeOctets;
3476 case (WORD)X509_BITS:
3477 case (WORD)X509_KEY_USAGE:
3478 decodeFunc = CRYPT_AsnDecodeBits;
3480 case (WORD)X509_INTEGER:
3481 decodeFunc = CRYPT_AsnDecodeInt;
3483 case (WORD)X509_MULTI_BYTE_INTEGER:
3484 decodeFunc = CRYPT_AsnDecodeInteger;
3486 case (WORD)X509_MULTI_BYTE_UINT:
3487 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3489 case (WORD)X509_ENUMERATED:
3490 decodeFunc = CRYPT_AsnDecodeEnumerated;
3492 case (WORD)X509_CHOICE_OF_TIME:
3493 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3495 case (WORD)X509_SEQUENCE_OF_ANY:
3496 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3498 case (WORD)PKCS_UTC_TIME:
3499 decodeFunc = CRYPT_AsnDecodeUtcTime;
3502 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3505 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3506 decodeFunc = CRYPT_AsnDecodeExtensions;
3507 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3508 decodeFunc = CRYPT_AsnDecodeUtcTime;
3509 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3510 decodeFunc = CRYPT_AsnDecodeEnumerated;
3511 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3512 decodeFunc = CRYPT_AsnDecodeBits;
3513 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3514 decodeFunc = CRYPT_AsnDecodeOctets;
3515 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3516 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3518 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3519 debugstr_a(lpszStructType));
3521 decodeFunc = (CryptDecodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType,
3522 lpszStructType, "CryptDecodeObjectEx", &lib);
3524 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
3525 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3527 SetLastError(ERROR_FILE_NOT_FOUND);